diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md
index 24d0c2d2c..0c05e6334 100644
--- a/.github/copilot-instructions.md
+++ b/.github/copilot-instructions.md
@@ -13,7 +13,7 @@ This is the **GitHub Copilot for Eclipse** plugin - an Eclipse IDE extension tha
- **Multi-Platform Support**: Windows, macOS (x64/aarch64), and Linux (x64/aarch64)
### Tech Stack
-- **Java**: Primary language (Java 17+, with Eclipse 4.31+ requiring Java 21+)
+- **Java**: Primary language (Java 21+, with Eclipse 4.38+ requiring Java 21+)
- **Eclipse RCP/OSGi**: Plugin architecture using Eclipse platform APIs
- **Maven/Tycho**: Build system for Eclipse plugin development
- **LSP4E**: Language Server Protocol integration for Eclipse
@@ -46,7 +46,7 @@ You MUST verify compilation and code quality before declaring work complete!
- Root POM coordinates multi-module build with Tycho
- Each bundle/feature/test has its own POM inheriting from root
- Checkstyle validation runs during `verify` phase
-- Target platform defined in `base.target`, `target-terminal.target`, `target-tm-terminal.target`
+- Target platform defined in `target-platforms/2025-12.target`
### Code Change Review Trigger
@@ -117,12 +117,6 @@ The project follows Eclipse plugin conventions with multiple OSGi bundles:
- **Service**: `IRunInTerminalTool` implementation
- **Dependencies**: `org.eclipse.terminal.*` packages
-**`com.microsoft.copilot.eclipse.ui.terminal.tm`** - TM Terminal integration (legacy)
-- **Package**: `com.microsoft.copilot.eclipse.ui.terminal.tm`
-- **Purpose**: Implementation for TM Terminal (Eclipse 4.36 and lower)
-- **Service**: `IRunInTerminalTool` implementation
-- **Dependencies**: `org.eclipse.tm.terminal.*` packages
-
#### Platform-Specific Agent Bundles
These bundles contain the Node.js-based Copilot language server agent for each platform:
@@ -569,7 +563,7 @@ distinguish repeated controls with stable context or an ordinal
**When** writing tests → use JUnit 5 for core logic; integration tests for Eclipse integration
-**When** adding dependencies → only add necessary bundles; check `base.target` for Eclipse 2024-03 version constraints
+**When** adding dependencies → only add necessary bundles; check `target-platforms/2025-12.target` for Eclipse 2025-12 version constraints
**When** targeting Eclipse versions → support multiple versions when possible
diff --git a/.github/skills/ui-action/REFERENCE.md b/.github/skills/ui-action/REFERENCE.md
index 65d4fb3ef..22eda5bb4 100644
--- a/.github/skills/ui-action/REFERENCE.md
+++ b/.github/skills/ui-action/REFERENCE.md
@@ -8,7 +8,7 @@ with `useUIHarness=true` and `useUIThread=false`. It loads the JSON array from
artifacts, and fails the Maven build if any failed step has `failFast` enabled.
Before the bot starts, the runner pre-populates configuration-scope preferences
-so Quick Start, What's New, Welcome, and "Terminal Support Unavailable" dialogs
+so Quick Start, What's New, and Welcome dialogs
do not block normal probes.
`screenshot` and failure screenshots capture the active workbench shell with
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 3823ab471..7d45575de 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -32,10 +32,10 @@ jobs:
working-directory: com.microsoft.copilot.eclipse.core/copilot-agent
run: npm i -f
- - name: Set up JDK 17
+ - name: Set up JDK 21
uses: actions/setup-java@de7274f081f381c8f8158605e0321c36c376e2e6 # v6.0.1
with:
- java-version: '17'
+ java-version: '21'
distribution: 'temurin'
cache: maven
diff --git a/.gitignore b/.gitignore
index 650f8dc02..a792baab1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -36,9 +36,6 @@ replay_pid*
# whatisnew html file in runtime
**/whatisnew.html
-# Terminal bundles
-**/terminal-bundles/*.jar
-
# Fragment bundle copilot-agent directories
com.microsoft.copilot.eclipse.core.agent.linux.x64/copilot-agent/
com.microsoft.copilot.eclipse.core.agent.linux.aarch64/copilot-agent/
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index e78e21d46..4ee7f13dc 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -16,10 +16,10 @@ When you submit a pull request, a CLA bot will automatically determine whether y
### Prerequisites
-- **Java 17** or later (CI uses Temurin 17; use a newer JDK if required by your Eclipse IDE)
+- **Java 21** or later (CI uses Temurin 21; use a newer JDK if required by your Eclipse IDE)
- **Maven 3.8+** (or use the provided Maven wrapper `./mvnw`)
- **Node.js 22.13** or later, with npm
-- **Eclipse IDE for Eclipse Committers 2024-03** or later (for development)
+- **Eclipse IDE for Eclipse Committers 2025-12** or later (for development)
- Recommended: **Eclipse Checkstyle plugin** for code style compliance
(e.g. install from update site: https://checkstyle.org/eclipse-cs-update-site/)
@@ -60,9 +60,8 @@ The installable P2 repository is generated in `com.microsoft.copilot.eclipse.rep
activate the check box *Search for nested projects*, and finish the wizard.
* Do also import the agent bundle for your OS (e.g., `com.microsoft.copilot.eclipse.core.agent.win32`)
after building the project with npm and maven or import all OS-specific agent bundles.
-2. Activate one of the target platforms, i.e. open one of the target definition files and select `Set As Active Target Platform`.
- * target-terminal.target (Eclipse 4.37+)
- * target-tm-terminal.target (Eclipse 4.36 and earlier)
+2. Activate the target platform, i.e. open the target definition file `target-platforms/2025-12.target`
+ (Eclipse 2025-12 / 4.38, providing the modern `org.eclipse.terminal.*` bundles) and select `Set As Active Target Platform`.
3. For using the Checkstyle configuration (assuming you have installed the Eclipse Checkstyle plugin, see prerequisites),
add a new named Checkstyle configuration.
* Select *Window > Preferences > Checkstyle* and press the *New...* button.
@@ -112,8 +111,7 @@ The project is a multi-module Maven/Tycho build consisting of OSGi bundles:
| `com.microsoft.copilot.eclipse.ui` | User interface: chat view, completion UI, agent tools |
| `com.microsoft.copilot.eclipse.ui.jobs` | Copilot Jobs view integration |
| `com.microsoft.copilot.eclipse.terminal.api` | Terminal tool API definitions |
-| `com.microsoft.copilot.eclipse.ui.terminal` | Terminal integration (Eclipse 4.37+) |
-| `com.microsoft.copilot.eclipse.ui.terminal.tm` | TM Terminal integration (Eclipse 4.36 and earlier) |
+| `com.microsoft.copilot.eclipse.ui.terminal` | Terminal integration (runs on Eclipse >= 2025-09 / 4.37) |
| `com.microsoft.copilot.eclipse.branding` | Product branding and about dialog |
| `com.microsoft.copilot.eclipse.core.agent.*` | Platform-specific Copilot language server agent bundles |
| `com.microsoft.copilot.eclipse.feature` | Eclipse feature definition |
diff --git a/base.target b/base.target
deleted file mode 100644
index a6fc6705a..000000000
--- a/base.target
+++ /dev/null
@@ -1,77 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- org.mockito
- mockito-core
- 5.14.2
- jar
-
-
- org.mockito
- mockito-junit-jupiter
- 5.14.2
- jar
-
-
- org.objenesis
- objenesis
- 3.4
- jar
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/com.microsoft.copilot.eclipse.core.agent.linux.aarch64/META-INF/MANIFEST.MF b/com.microsoft.copilot.eclipse.core.agent.linux.aarch64/META-INF/MANIFEST.MF
index eb31b095a..b08c1bcf5 100644
--- a/com.microsoft.copilot.eclipse.core.agent.linux.aarch64/META-INF/MANIFEST.MF
+++ b/com.microsoft.copilot.eclipse.core.agent.linux.aarch64/META-INF/MANIFEST.MF
@@ -6,5 +6,5 @@ Automatic-Module-Name: com.microsoft.copilot.eclipse.core.agent.linux.aarch64
Bundle-Version: 0.21.0.qualifier
Bundle-Vendor: GitHub Copilot
Fragment-Host: com.microsoft.copilot.eclipse.core
-Bundle-RequiredExecutionEnvironment: JavaSE-17
+Bundle-RequiredExecutionEnvironment: JavaSE-21
Eclipse-PlatformFilter: (&(osgi.os=linux)(osgi.arch=aarch64))
diff --git a/com.microsoft.copilot.eclipse.core.agent.linux.x64/META-INF/MANIFEST.MF b/com.microsoft.copilot.eclipse.core.agent.linux.x64/META-INF/MANIFEST.MF
index d422d0113..855176ae8 100644
--- a/com.microsoft.copilot.eclipse.core.agent.linux.x64/META-INF/MANIFEST.MF
+++ b/com.microsoft.copilot.eclipse.core.agent.linux.x64/META-INF/MANIFEST.MF
@@ -6,5 +6,5 @@ Automatic-Module-Name: com.microsoft.copilot.eclipse.core.agent.linux.x64
Bundle-Version: 0.21.0.qualifier
Bundle-Vendor: GitHub Copilot
Fragment-Host: com.microsoft.copilot.eclipse.core
-Bundle-RequiredExecutionEnvironment: JavaSE-17
+Bundle-RequiredExecutionEnvironment: JavaSE-21
Eclipse-PlatformFilter: (&(osgi.os=linux)(osgi.arch=x86_64))
diff --git a/com.microsoft.copilot.eclipse.core.agent.macosx.aarch64/META-INF/MANIFEST.MF b/com.microsoft.copilot.eclipse.core.agent.macosx.aarch64/META-INF/MANIFEST.MF
index 4e91f8354..eaae707a2 100644
--- a/com.microsoft.copilot.eclipse.core.agent.macosx.aarch64/META-INF/MANIFEST.MF
+++ b/com.microsoft.copilot.eclipse.core.agent.macosx.aarch64/META-INF/MANIFEST.MF
@@ -6,5 +6,5 @@ Automatic-Module-Name: com.microsoft.copilot.eclipse.core.agent.macosx.aarch64
Bundle-Version: 0.21.0.qualifier
Bundle-Vendor: GitHub Copilot
Fragment-Host: com.microsoft.copilot.eclipse.core
-Bundle-RequiredExecutionEnvironment: JavaSE-17
+Bundle-RequiredExecutionEnvironment: JavaSE-21
Eclipse-PlatformFilter: (&(osgi.os=macosx) (osgi.arch=aarch64))
diff --git a/com.microsoft.copilot.eclipse.core.agent.macosx.x64/META-INF/MANIFEST.MF b/com.microsoft.copilot.eclipse.core.agent.macosx.x64/META-INF/MANIFEST.MF
index f00dbc951..387ad4ddb 100644
--- a/com.microsoft.copilot.eclipse.core.agent.macosx.x64/META-INF/MANIFEST.MF
+++ b/com.microsoft.copilot.eclipse.core.agent.macosx.x64/META-INF/MANIFEST.MF
@@ -6,5 +6,5 @@ Automatic-Module-Name: com.microsoft.copilot.eclipse.core.agent.macosx.x64
Bundle-Version: 0.21.0.qualifier
Bundle-Vendor: GitHub Copilot
Fragment-Host: com.microsoft.copilot.eclipse.core
-Bundle-RequiredExecutionEnvironment: JavaSE-17
+Bundle-RequiredExecutionEnvironment: JavaSE-21
Eclipse-PlatformFilter: (&(osgi.os=macosx)(osgi.arch=x86_64))
diff --git a/com.microsoft.copilot.eclipse.core.agent.win32/META-INF/MANIFEST.MF b/com.microsoft.copilot.eclipse.core.agent.win32/META-INF/MANIFEST.MF
index e8f912c1d..11d3e10d1 100644
--- a/com.microsoft.copilot.eclipse.core.agent.win32/META-INF/MANIFEST.MF
+++ b/com.microsoft.copilot.eclipse.core.agent.win32/META-INF/MANIFEST.MF
@@ -6,5 +6,5 @@ Automatic-Module-Name: com.microsoft.copilot.eclipse.core.agent.win32
Bundle-Version: 0.21.0.qualifier
Bundle-Vendor: GitHub Copilot
Fragment-Host: com.microsoft.copilot.eclipse.core
-Bundle-RequiredExecutionEnvironment: JavaSE-17
+Bundle-RequiredExecutionEnvironment: JavaSE-21
Eclipse-PlatformFilter: (osgi.os=win32)
diff --git a/com.microsoft.copilot.eclipse.core.test/.classpath b/com.microsoft.copilot.eclipse.core.test/.classpath
index 38f401ad4..766df48f2 100644
--- a/com.microsoft.copilot.eclipse.core.test/.classpath
+++ b/com.microsoft.copilot.eclipse.core.test/.classpath
@@ -1,11 +1,15 @@
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/com.microsoft.copilot.eclipse.core.test/.settings/org.eclipse.core.resources.prefs b/com.microsoft.copilot.eclipse.core.test/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 000000000..4824b8026
--- /dev/null
+++ b/com.microsoft.copilot.eclipse.core.test/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,2 @@
+eclipse.preferences.version=1
+encoding/=UTF-8
diff --git a/com.microsoft.copilot.eclipse.core.test/.settings/org.eclipse.jdt.core.prefs b/com.microsoft.copilot.eclipse.core.test/.settings/org.eclipse.jdt.core.prefs
index 21eccc094..a98206bc4 100644
--- a/com.microsoft.copilot.eclipse.core.test/.settings/org.eclipse.jdt.core.prefs
+++ b/com.microsoft.copilot.eclipse.core.test/.settings/org.eclipse.jdt.core.prefs
@@ -1,12 +1,12 @@
eclipse.preferences.version=1
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=17
-org.eclipse.jdt.core.compiler.compliance=17
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=21
+org.eclipse.jdt.core.compiler.compliance=21
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning
org.eclipse.jdt.core.compiler.release=enabled
-org.eclipse.jdt.core.compiler.source=17
+org.eclipse.jdt.core.compiler.source=21
org.eclipse.jdt.core.formatter.align_arrows_in_switch_on_columns=false
org.eclipse.jdt.core.formatter.align_assignment_statements_on_columns=false
org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines=2147483647
diff --git a/com.microsoft.copilot.eclipse.core.test/META-INF/MANIFEST.MF b/com.microsoft.copilot.eclipse.core.test/META-INF/MANIFEST.MF
index ebf877391..e4eedf0c0 100644
--- a/com.microsoft.copilot.eclipse.core.test/META-INF/MANIFEST.MF
+++ b/com.microsoft.copilot.eclipse.core.test/META-INF/MANIFEST.MF
@@ -4,7 +4,7 @@ Bundle-Name: com.microsoft.copilot.eclipse.core.test
Bundle-SymbolicName: com.microsoft.copilot.eclipse.core.test;singleton:=true
Bundle-Version: 0.21.0.qualifier
Bundle-Vendor: GitHub Copilot
-Bundle-RequiredExecutionEnvironment: JavaSE-17
+Bundle-RequiredExecutionEnvironment: JavaSE-21
Fragment-Host: com.microsoft.copilot.eclipse.core
Automatic-Module-Name: com.microsoft.copilot.eclipse.core.test
Import-Package: org.objenesis;version="[3.4.0,4.0.0)",
diff --git a/com.microsoft.copilot.eclipse.core.test/build.properties b/com.microsoft.copilot.eclipse.core.test/build.properties
index 100b378a5..3cb14ae9c 100644
--- a/com.microsoft.copilot.eclipse.core.test/build.properties
+++ b/com.microsoft.copilot.eclipse.core.test/build.properties
@@ -1,5 +1,5 @@
-source.. = src
-output.. = target/classes
+source.. = src/
+output.. = target/classes/
bin.includes = META-INF/,\
.
diff --git a/com.microsoft.copilot.eclipse.core/.classpath b/com.microsoft.copilot.eclipse.core/.classpath
index 8d8612144..b1415d56b 100644
--- a/com.microsoft.copilot.eclipse.core/.classpath
+++ b/com.microsoft.copilot.eclipse.core/.classpath
@@ -1,7 +1,11 @@
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
diff --git a/com.microsoft.copilot.eclipse.core/.settings/org.eclipse.core.resources.prefs b/com.microsoft.copilot.eclipse.core/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 000000000..4824b8026
--- /dev/null
+++ b/com.microsoft.copilot.eclipse.core/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,2 @@
+eclipse.preferences.version=1
+encoding/=UTF-8
diff --git a/com.microsoft.copilot.eclipse.core/.settings/org.eclipse.jdt.core.prefs b/com.microsoft.copilot.eclipse.core/.settings/org.eclipse.jdt.core.prefs
index 21eccc094..2fc4a03ea 100644
--- a/com.microsoft.copilot.eclipse.core/.settings/org.eclipse.jdt.core.prefs
+++ b/com.microsoft.copilot.eclipse.core/.settings/org.eclipse.jdt.core.prefs
@@ -1,12 +1,17 @@
eclipse.preferences.version=1
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=17
-org.eclipse.jdt.core.compiler.compliance=17
+org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=21
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=21
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning
org.eclipse.jdt.core.compiler.release=enabled
-org.eclipse.jdt.core.compiler.source=17
+org.eclipse.jdt.core.compiler.source=21
org.eclipse.jdt.core.formatter.align_arrows_in_switch_on_columns=false
org.eclipse.jdt.core.formatter.align_assignment_statements_on_columns=false
org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines=2147483647
diff --git a/com.microsoft.copilot.eclipse.core/META-INF/MANIFEST.MF b/com.microsoft.copilot.eclipse.core/META-INF/MANIFEST.MF
index e96a614f6..b78d04d83 100644
--- a/com.microsoft.copilot.eclipse.core/META-INF/MANIFEST.MF
+++ b/com.microsoft.copilot.eclipse.core/META-INF/MANIFEST.MF
@@ -23,10 +23,10 @@ Export-Package: com.microsoft.copilot.eclipse.core,
com.microsoft.copilot.eclipse.core.lsp.protocol.quota,
com.microsoft.copilot.eclipse.core.lsp.protocol.tools,
com.microsoft.copilot.eclipse.core.nes;x-friends:="com.microsoft.copilot.eclipse.ui",
- com.microsoft.copilot.eclipse.core.persistence;x-friends:="com.microsoft.copilot.eclipse.ui,com.microsoft.copilot.eclipse.core.test,com.microsoft.copilot.eclipse.core.utils",
+ com.microsoft.copilot.eclipse.core.persistence;x-friends:="com.microsoft.copilot.eclipse.ui,com.microsoft.copilot.eclipse.core.test,com.microsoft.copilot.eclipse.core.utils",
com.microsoft.copilot.eclipse.core.utils
Bundle-Activator: com.microsoft.copilot.eclipse.core.CopilotCore
-Bundle-RequiredExecutionEnvironment: JavaSE-17
+Bundle-RequiredExecutionEnvironment: JavaSE-21
Automatic-Module-Name: com.microsoft.copilot.eclipse.core
Bundle-ActivationPolicy: lazy
Import-Package: org.eclipse.ui,
diff --git a/com.microsoft.copilot.eclipse.core/build.properties b/com.microsoft.copilot.eclipse.core/build.properties
index d6219466d..326a0702b 100644
--- a/com.microsoft.copilot.eclipse.core/build.properties
+++ b/com.microsoft.copilot.eclipse.core/build.properties
@@ -1,5 +1,5 @@
-source.. = src
-output.. = target/classes
+source.. = src/
+output.. = target/classes/
bin.includes = META-INF/,\
.,\
plugin.xml,\
diff --git a/com.microsoft.copilot.eclipse.core/src/com/microsoft/copilot/eclipse/core/Constants.java b/com.microsoft.copilot.eclipse.core/src/com/microsoft/copilot/eclipse/core/Constants.java
index 73817770d..954a67ad2 100644
--- a/com.microsoft.copilot.eclipse.core/src/com/microsoft/copilot/eclipse/core/Constants.java
+++ b/com.microsoft.copilot.eclipse.core/src/com/microsoft/copilot/eclipse/core/Constants.java
@@ -50,7 +50,6 @@ private Constants() {
public static final String AUTO_SHOW_WHAT_IS_NEW = "autoShowWhatsNew";
public static final String AUTO_BREAKPOINT_RESPONSE = "autoBreakpointResponse";
public static final String GITHUB_JOBS_VIEW_ID = "com.microsoft.copilot.eclipse.ui.jobs.JobsView";
- public static final String SUPPRESS_TERMINAL_DEPENDENCY_DIALOG = "suppressTerminalDependencyDialog";
// Auto-Approve settings
public static final String AUTO_APPROVE_TERMINAL_RULES = "autoApproveTerminalRules";
diff --git a/com.microsoft.copilot.eclipse.feature/feature.xml b/com.microsoft.copilot.eclipse.feature/feature.xml
index 6cdfb8113..980f3c9b0 100644
--- a/com.microsoft.copilot.eclipse.feature/feature.xml
+++ b/com.microsoft.copilot.eclipse.feature/feature.xml
@@ -56,6 +56,10 @@ For the purpose of improving GitHub Copilot, Microsoft and GitHub may share with
id="com.microsoft.copilot.eclipse.terminal.api"
version="0.0.0"/>
+
+
diff --git a/com.microsoft.copilot.eclipse.repository/category.xml b/com.microsoft.copilot.eclipse.repository/category.xml
index 78f864fa1..3b147199d 100644
--- a/com.microsoft.copilot.eclipse.repository/category.xml
+++ b/com.microsoft.copilot.eclipse.repository/category.xml
@@ -3,5 +3,15 @@
+
+
+
+
+
+
+
+
+
-
\ No newline at end of file
+
+
diff --git a/com.microsoft.copilot.eclipse.swtbot.test/.classpath b/com.microsoft.copilot.eclipse.swtbot.test/.classpath
index 38f401ad4..766df48f2 100644
--- a/com.microsoft.copilot.eclipse.swtbot.test/.classpath
+++ b/com.microsoft.copilot.eclipse.swtbot.test/.classpath
@@ -1,11 +1,15 @@
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/com.microsoft.copilot.eclipse.swtbot.test/.settings/org.eclipse.core.resources.prefs b/com.microsoft.copilot.eclipse.swtbot.test/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 000000000..4824b8026
--- /dev/null
+++ b/com.microsoft.copilot.eclipse.swtbot.test/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,2 @@
+eclipse.preferences.version=1
+encoding/=UTF-8
diff --git a/com.microsoft.copilot.eclipse.swtbot.test/.settings/org.eclipse.jdt.core.prefs b/com.microsoft.copilot.eclipse.swtbot.test/.settings/org.eclipse.jdt.core.prefs
index 62ef3488c..23fa13b17 100644
--- a/com.microsoft.copilot.eclipse.swtbot.test/.settings/org.eclipse.jdt.core.prefs
+++ b/com.microsoft.copilot.eclipse.swtbot.test/.settings/org.eclipse.jdt.core.prefs
@@ -1,9 +1,9 @@
eclipse.preferences.version=1
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=17
-org.eclipse.jdt.core.compiler.compliance=17
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=21
+org.eclipse.jdt.core.compiler.compliance=21
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning
org.eclipse.jdt.core.compiler.release=enabled
-org.eclipse.jdt.core.compiler.source=17
+org.eclipse.jdt.core.compiler.source=21
diff --git a/com.microsoft.copilot.eclipse.swtbot.test/META-INF/MANIFEST.MF b/com.microsoft.copilot.eclipse.swtbot.test/META-INF/MANIFEST.MF
index 468b60478..3a2731834 100644
--- a/com.microsoft.copilot.eclipse.swtbot.test/META-INF/MANIFEST.MF
+++ b/com.microsoft.copilot.eclipse.swtbot.test/META-INF/MANIFEST.MF
@@ -4,7 +4,7 @@ Bundle-Name: com.microsoft.copilot.eclipse.swtbot.test
Bundle-SymbolicName: com.microsoft.copilot.eclipse.swtbot.test;singleton:=true
Bundle-Version: 0.21.0.qualifier
Bundle-Vendor: GitHub Copilot
-Bundle-RequiredExecutionEnvironment: JavaSE-17
+Bundle-RequiredExecutionEnvironment: JavaSE-21
Automatic-Module-Name: com.microsoft.copilot.eclipse.swtbot.test
Require-Bundle: org.eclipse.swtbot.swt.finder;bundle-version="4.1.0",
org.eclipse.swtbot.eclipse.finder;bundle-version="4.1.0",
diff --git a/com.microsoft.copilot.eclipse.swtbot.test/build.properties b/com.microsoft.copilot.eclipse.swtbot.test/build.properties
index 8e6b406ec..73ec1c618 100644
--- a/com.microsoft.copilot.eclipse.swtbot.test/build.properties
+++ b/com.microsoft.copilot.eclipse.swtbot.test/build.properties
@@ -1,5 +1,5 @@
-source.. = src
-output.. = target/classes
+source.. = src/
+output.. = target/classes/
bin.includes = META-INF/,\
.,\
plugin.xml,\
diff --git a/com.microsoft.copilot.eclipse.swtbot.test/src/com/microsoft/copilot/eclipse/swtbot/test/probe/ProbeRunner.java b/com.microsoft.copilot.eclipse.swtbot.test/src/com/microsoft/copilot/eclipse/swtbot/test/probe/ProbeRunner.java
index f64e037c0..1a2a2c746 100644
--- a/com.microsoft.copilot.eclipse.swtbot.test/src/com/microsoft/copilot/eclipse/swtbot/test/probe/ProbeRunner.java
+++ b/com.microsoft.copilot.eclipse.swtbot.test/src/com/microsoft/copilot/eclipse/swtbot/test/probe/ProbeRunner.java
@@ -64,9 +64,8 @@ public static void assumeScript() {
/**
* Pre-populates the Copilot UI plugin's configuration-scope preferences so the
- * workbench-startup logic in {@code CopilotUi#showHintIfNecessary} and
- * {@code MissingTerminalDependenciesDialog#showIfNotSuppressed} skip their
- * "first run" dialogs (Quick Start, What's New, Terminal Support Unavailable).
+ * workbench-startup logic in {@code CopilotUi#showHintIfNecessary} skips its
+ * "first run" dialogs (Quick Start, What's New).
* Runs before the workbench bot exists; best-effort — any failure is logged
* and the probe continues.
*/
@@ -76,7 +75,6 @@ private static void suppressNuisancePreferences() {
prefs.putInt(Constants.COPILOT_QUICK_START_VERSION, Constants.CURRENT_COPILOT_QUICK_START_VERSION);
prefs.putBoolean(Constants.AUTO_SHOW_WHAT_IS_NEW, false);
prefs.put(Constants.LAST_USED_COPILOT_PLUGIN_VERSION, currentUiBundleMajorMinor());
- prefs.putBoolean(Constants.SUPPRESS_TERMINAL_DEPENDENCY_DIALOG, true);
prefs.flush();
} catch (BackingStoreException | RuntimeException e) {
System.err.println("[ProbeRunner] Failed to preset nuisance-dialog preferences: " + e);
diff --git a/com.microsoft.copilot.eclipse.swtbot.test/test-plans/byok/byok.md b/com.microsoft.copilot.eclipse.swtbot.test/test-plans/byok/byok.md
index cd05b935a..0fe960804 100644
--- a/com.microsoft.copilot.eclipse.swtbot.test/test-plans/byok/byok.md
+++ b/com.microsoft.copilot.eclipse.swtbot.test/test-plans/byok/byok.md
@@ -55,7 +55,7 @@ Not exercised in this plan (separate scenarios):
- For Ollama-specific TCs: Ollama 0.6.4 or newer is running and has at least
one installed model.
- No previously opened Preferences dialog. The probe runner pre-suppresses
- Quick Start, What's New, Welcome, and "Terminal Support Unavailable"
+ Quick Start, What's New, and Welcome
pop-ups — keep that contract when authoring follow-up plans.
- Each TC starts from a freshly launched workbench (the probe sandbox
satisfies this automatically). When running manually, close the
diff --git a/com.microsoft.copilot.eclipse.swtbot.test/test-plans/chat-send-receive/chat-send-receive.md b/com.microsoft.copilot.eclipse.swtbot.test/test-plans/chat-send-receive/chat-send-receive.md
index 3aee9d818..0622d09ff 100644
--- a/com.microsoft.copilot.eclipse.swtbot.test/test-plans/chat-send-receive/chat-send-receive.md
+++ b/com.microsoft.copilot.eclipse.swtbot.test/test-plans/chat-send-receive/chat-send-receive.md
@@ -40,8 +40,8 @@ Not exercised in TC-001 (separate scenarios):
- Network access to `api.githubcopilot.com` (and the GitHub auth host if a
token refresh is needed).
- No modal dialogs queued on workbench startup. The probe runner
- pre-populates preferences to suppress Quick Start, What's New, Welcome, and
- "Terminal Support Unavailable" pop-ups; authoring additional tests on top
+ pre-populates preferences to suppress Quick Start, What's New, and
+ Welcome pop-ups; authoring additional tests on top
of this scenario should keep that contract.
---
diff --git a/com.microsoft.copilot.eclipse.terminal.api/.classpath b/com.microsoft.copilot.eclipse.terminal.api/.classpath
index 8d8612144..b1415d56b 100644
--- a/com.microsoft.copilot.eclipse.terminal.api/.classpath
+++ b/com.microsoft.copilot.eclipse.terminal.api/.classpath
@@ -1,7 +1,11 @@
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
diff --git a/com.microsoft.copilot.eclipse.terminal.api/.settings/org.eclipse.core.resources.prefs b/com.microsoft.copilot.eclipse.terminal.api/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 000000000..4824b8026
--- /dev/null
+++ b/com.microsoft.copilot.eclipse.terminal.api/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,2 @@
+eclipse.preferences.version=1
+encoding/=UTF-8
diff --git a/com.microsoft.copilot.eclipse.terminal.api/.settings/org.eclipse.jdt.core.prefs b/com.microsoft.copilot.eclipse.terminal.api/.settings/org.eclipse.jdt.core.prefs
index 62ef3488c..23fa13b17 100644
--- a/com.microsoft.copilot.eclipse.terminal.api/.settings/org.eclipse.jdt.core.prefs
+++ b/com.microsoft.copilot.eclipse.terminal.api/.settings/org.eclipse.jdt.core.prefs
@@ -1,9 +1,9 @@
eclipse.preferences.version=1
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=17
-org.eclipse.jdt.core.compiler.compliance=17
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=21
+org.eclipse.jdt.core.compiler.compliance=21
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning
org.eclipse.jdt.core.compiler.release=enabled
-org.eclipse.jdt.core.compiler.source=17
+org.eclipse.jdt.core.compiler.source=21
diff --git a/com.microsoft.copilot.eclipse.terminal.api/META-INF/MANIFEST.MF b/com.microsoft.copilot.eclipse.terminal.api/META-INF/MANIFEST.MF
index fbcc5c79a..9a0d746cf 100644
--- a/com.microsoft.copilot.eclipse.terminal.api/META-INF/MANIFEST.MF
+++ b/com.microsoft.copilot.eclipse.terminal.api/META-INF/MANIFEST.MF
@@ -7,7 +7,7 @@ Bundle-Vendor: GitHub Copilot
Export-Package: com.microsoft.copilot.eclipse.terminal.api
Automatic-Module-Name: com.microsoft.copilot.eclipse.terminal.api
Bundle-ActivationPolicy: lazy
-Bundle-RequiredExecutionEnvironment: JavaSE-17
+Bundle-RequiredExecutionEnvironment: JavaSE-21
Import-Package: org.osgi.framework;version="[1.10.0,2.0.0)"
Require-Bundle: org.eclipse.core.runtime;bundle-version="[3.30.0,4.0.0)",
com.microsoft.copilot.eclipse.core;bundle-version="0.21.0",
diff --git a/com.microsoft.copilot.eclipse.terminal.api/build.properties b/com.microsoft.copilot.eclipse.terminal.api/build.properties
index f38581b94..eb7c4c161 100644
--- a/com.microsoft.copilot.eclipse.terminal.api/build.properties
+++ b/com.microsoft.copilot.eclipse.terminal.api/build.properties
@@ -1,5 +1,5 @@
source.. = src/
-output.. = bin/
+output.. = target/classes/
bin.includes = META-INF/,\
.,\
scripts/
diff --git a/com.microsoft.copilot.eclipse.terminal.api/src/com/microsoft/copilot/eclipse/terminal/api/TerminalServiceManager.java b/com.microsoft.copilot.eclipse.terminal.api/src/com/microsoft/copilot/eclipse/terminal/api/TerminalServiceManager.java
index 8d1c39fc4..2532a89fb 100644
--- a/com.microsoft.copilot.eclipse.terminal.api/src/com/microsoft/copilot/eclipse/terminal/api/TerminalServiceManager.java
+++ b/com.microsoft.copilot.eclipse.terminal.api/src/com/microsoft/copilot/eclipse/terminal/api/TerminalServiceManager.java
@@ -1,500 +1,151 @@
-// Copyright (c) Microsoft Corporation.
-// Licensed under the MIT license.
-
-package com.microsoft.copilot.eclipse.terminal.api;
-
-import java.io.IOException;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Set;
-import java.util.concurrent.CopyOnWriteArrayList;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.jar.JarInputStream;
-import java.util.jar.Manifest;
-
-import org.eclipse.core.runtime.FileLocator;
-import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.core.runtime.IStatus;
-import org.eclipse.core.runtime.Path;
-import org.eclipse.core.runtime.Platform;
-import org.eclipse.core.runtime.Status;
-import org.eclipse.core.runtime.jobs.Job;
-import org.eclipse.osgi.util.ManifestElement;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.BundleException;
-import org.osgi.framework.Constants;
-import org.osgi.framework.FrameworkEvent;
-import org.osgi.framework.FrameworkListener;
-import org.osgi.framework.FrameworkUtil;
-import org.osgi.framework.ServiceReference;
-import org.osgi.framework.Version;
-import org.osgi.framework.wiring.FrameworkWiring;
-import org.osgi.util.tracker.ServiceTracker;
-import org.osgi.util.tracker.ServiceTrackerCustomizer;
-
-import com.microsoft.copilot.eclipse.core.CopilotCore;
-import com.microsoft.copilot.eclipse.core.utils.PlatformUtils;
-
-/**
- * Central manager for terminal services. Handles service discovery, bundle installation.
- */
-public class TerminalServiceManager {
-
- private static final String TERMINAL_BUNDLES_PATH = "terminal-bundles/";
- private static final String MODERN_TERMINAL_BUNDLE_JAR = "com.microsoft.copilot.eclipse.ui.terminal.jar";
- private static final String TM_TERMINAL_BUNDLE_JAR = "com.microsoft.copilot.eclipse.ui.terminal.tm.jar";
- private static final String MODERN_TERMINAL_BUNDLE_ID = "com.microsoft.copilot.eclipse.ui.terminal";
- private static final String TM_TERMINAL_BUNDLE_ID = "com.microsoft.copilot.eclipse.ui.terminal.tm";
- private static final String MODERN_TERMINAL_TYPE = "Terminal Feature";
- private static final String TM_TERMINAL_TYPE = "TM Terminal";
- private static final Version TARGET_PLATFORM_VERSION = new Version(4, 37, 0);
-
- /**
- * Static inner class for lazy initialization of singleton instance.
- */
- private static class InstanceHolder {
- private static final TerminalServiceManager INSTANCE = createInstance();
-
- private static TerminalServiceManager createInstance() {
- Bundle apiBundle = FrameworkUtil.getBundle(TerminalServiceManager.class);
- if (apiBundle != null) {
- BundleContext context = apiBundle.getBundleContext();
- if (context != null) {
- TerminalServiceManager instance = new TerminalServiceManager(context);
- instance.start();
- return instance;
- }
- }
- return null;
- }
- }
-
- private final BundleContext bundleContext;
- private ServiceTracker serviceTracker;
- private final AtomicBoolean installationAttempted = new AtomicBoolean(false);
- private final CopyOnWriteArrayList listeners = new CopyOnWriteArrayList<>();
- private volatile IRunInTerminalTool currentService = null;
- private volatile List cachedMissingDependencies = null;
- private final boolean isModernTerminal;
-
- /**
- * Interface for listening to terminal service availability changes.
- */
- public interface TerminalServiceListener {
- /**
- * Called when a terminal service becomes available.
- *
- * @param service the available terminal service
- */
- void onServiceAvailable(IRunInTerminalTool service);
-
- /**
- * Called when terminal dependencies are missing and need user action.
- *
- * @param terminalType the type of terminal (e.g., "Terminal Feature" or "TM Terminal")
- * @param missingDependencies list of missing bundle symbolic names
- */
- void onMissingDependencies(String terminalType, List missingDependencies);
- }
-
- private TerminalServiceManager(BundleContext bundleContext) {
- this.bundleContext = bundleContext;
- this.isModernTerminal = detectModernTerminal();
- }
-
- /**
- * Get the singleton instance of TerminalServiceManager.
- */
- public static TerminalServiceManager getInstance() {
- return InstanceHolder.INSTANCE;
- }
-
- /**
- * Add a listener for terminal service events.
- */
- public void addListener(TerminalServiceListener listener) {
- if (listener != null) {
- listeners.add(listener);
-
- // If service is already available, notify immediately
- if (currentService != null) {
- listener.onServiceAvailable(currentService);
- }
-
- // Notify with cached missing dependencies if available
- if (cachedMissingDependencies != null && !cachedMissingDependencies.isEmpty()) {
- listener.onMissingDependencies(isModernTerminal ? MODERN_TERMINAL_TYPE : TM_TERMINAL_TYPE,
- cachedMissingDependencies);
- }
- }
- }
-
- /**
- * Remove a listener for terminal service events.
- */
- public void removeListener(TerminalServiceListener listener) {
- listeners.remove(listener);
- }
-
- /**
- * Get the current terminal service if available.
- */
- public IRunInTerminalTool getCurrentService() {
- return currentService;
- }
-
- /**
- * Start tracking terminal services.
- */
- private void start() {
- ServiceTrackerCustomizer customizer = new ServiceTrackerCustomizer<>() {
- @Override
- public IRunInTerminalTool addingService(ServiceReference reference) {
- IRunInTerminalTool service = bundleContext.getService(reference);
- if (service != null) {
- currentService = service;
- notifyServiceAvailable(service);
- }
- return service;
- }
-
- @Override
- public void modifiedService(ServiceReference reference, IRunInTerminalTool service) {
- if (service != null) {
- currentService = service;
- notifyServiceAvailable(service);
- }
- }
-
- @Override
- public void removedService(ServiceReference reference, IRunInTerminalTool service) {
- }
- };
-
- serviceTracker = new ServiceTracker<>(bundleContext, IRunInTerminalTool.class, customizer);
- serviceTracker.open();
-
- IRunInTerminalTool[] services = serviceTracker.getServices(new IRunInTerminalTool[0]);
- if (services != null && services.length > 0) {
- currentService = services[0];
- }
- // Check if bundle needs to be installed or updated
- attemptTerminalBundleInstallation();
- }
-
- /**
- * Stop the service manager.
- */
- public void stop() {
- if (serviceTracker != null) {
- serviceTracker.close();
- serviceTracker = null;
- }
- currentService = null;
- listeners.clear();
- }
-
- private void notifyServiceAvailable(IRunInTerminalTool service) {
- for (TerminalServiceListener listener : listeners) {
- listener.onServiceAvailable(service);
- }
- }
-
- private void notifyMissingDependencies(String terminalType, List missingDependencies) {
- for (TerminalServiceListener listener : listeners) {
- listener.onMissingDependencies(terminalType, missingDependencies);
- }
- }
-
- /**
- * Attempt to install or update terminal bundle. Skips if bundle is already installed with sufficient version.
- */
- private void attemptTerminalBundleInstallation() {
- if (!installationAttempted.compareAndSet(false, true)) {
- return;
- }
-
- Job installationJob = new Job("Installing Terminal Bundle") {
- @Override
- protected IStatus run(IProgressMonitor monitor) {
- monitor.beginTask("Installing terminal bundle", 100);
- try {
- // Step 1: Check if installation/update is needed
- monitor.subTask("Checking existing installation");
- String symbolicName = isModernTerminal ? MODERN_TERMINAL_BUNDLE_ID : TM_TERMINAL_BUNDLE_ID;
- Bundle existingBundle = getInstalledBundle(symbolicName);
- Version requiredVersion = getEmbeddedBundleVersion();
-
- if (existingBundle != null) {
- Version installedVersion = existingBundle.getVersion();
- boolean needsUpdate = requiredVersion != null && installedVersion.compareTo(requiredVersion) < 0;
-
- if (!needsUpdate) {
- // Already up-to-date, just ensure it's started
- ensureStarted(existingBundle);
- monitor.done();
- return Status.OK_STATUS;
- }
- }
- monitor.worked(20);
-
- // Step 2: Check if required dependencies are available
- monitor.subTask("Checking dependencies");
- List missingDependencies = getMissingDependencies();
- monitor.worked(20);
-
- if (missingDependencies.isEmpty()) {
- // Dependencies available, install or update from embedded JAR
- return installFromEmbeddedJar(existingBundle, monitor);
- } else {
- // Dependencies missing, cache and notify listeners
- cachedMissingDependencies = missingDependencies;
- notifyMissingDependencies(isModernTerminal ? MODERN_TERMINAL_TYPE : TM_TERMINAL_TYPE, missingDependencies);
- return new Status(IStatus.WARNING, bundleContext.getBundle().getSymbolicName(),
- "Terminal dependencies not available. User needs to install them manually.");
- }
-
- } catch (BundleException e) {
- monitor.done();
- CopilotCore.LOGGER.error("Failed to install terminal bundle", e);
- return new Status(IStatus.ERROR, bundleContext.getBundle().getSymbolicName(),
- "Failed to install terminal bundle", e);
- }
- }
- };
- installationJob.setSystem(true);
- installationJob.schedule();
- }
-
- /**
- * Install terminal bundle from embedded JAR file (bundled with the plugin).
- *
- * @param existingBundle the existing bundle to update, or null if installing new
- * @param monitor progress monitor
- */
- private IStatus installFromEmbeddedJar(Bundle existingBundle, IProgressMonitor monitor) {
- try {
- monitor.subTask("Locating embedded bundle resource");
- String jarName = isModernTerminal ? MODERN_TERMINAL_BUNDLE_JAR : TM_TERMINAL_BUNDLE_JAR;
- URL bundleUrl = getEmbeddedBundleUrl(jarName);
- if (bundleUrl == null) {
- return new Status(IStatus.ERROR, bundleContext.getBundle().getSymbolicName(),
- "Failed to locate terminal bundle JAR: " + jarName);
- }
- monitor.worked(20);
-
- monitor.subTask(existingBundle != null ? "Updating bundle" : "Installing bundle");
- return installOrUpdateBundle(bundleUrl, existingBundle, monitor);
- } catch (InterruptedException | BundleException e) {
- CopilotCore.LOGGER.error("Failed to install from embedded JAR", e);
- return new Status(IStatus.ERROR, bundleContext.getBundle().getSymbolicName(),
- "Failed to install from embedded JAR", e);
- }
- }
-
- /**
- * Get the version of the terminal bundle. All Copilot bundles share the same version.
- *
- * @return the terminal bundle version, or null if not available
- */
- private Version getEmbeddedBundleVersion() {
- String versionStr = PlatformUtils.getBundleVersion();
- if (versionStr == null || "unknown".equals(versionStr)) {
- return null;
- }
- try {
- return Version.parseVersion(versionStr);
- } catch (IllegalArgumentException e) {
- CopilotCore.LOGGER.error("Failed to parse Copilot bundle version: " + versionStr, e);
- return null;
- }
- }
-
- /**
- * Get URL to the embedded terminal bundle JAR from the UI plugin.
- */
- private URL getEmbeddedBundleUrl(String bundleJarName) {
- try {
- Bundle[] bundles = bundleContext.getBundles();
- for (Bundle bundle : bundles) {
- if ("com.microsoft.copilot.eclipse.ui".equals(bundle.getSymbolicName())) {
- URL bundleUrl = FileLocator.find(bundle, new Path(TERMINAL_BUNDLES_PATH + bundleJarName));
- if (bundleUrl != null) {
- return FileLocator.toFileURL(bundleUrl);
- }
- }
- }
- return null;
-
- } catch (IOException e) {
- CopilotCore.LOGGER.error("Failed to locate embedded bundle resource: " + bundleJarName, e);
- return null;
- }
- }
-
- /**
- * Install or update bundle from embedded JAR URL.
- *
- * @param bundleUrl URL to the bundle JAR
- * @param existingBundle existing bundle to update, or null to install new
- * @param monitor progress monitor
- */
- private IStatus installOrUpdateBundle(URL bundleUrl, Bundle existingBundle, IProgressMonitor monitor)
- throws InterruptedException, BundleException {
- Bundle targetBundle;
-
- if (existingBundle != null) {
- // Update existing bundle
- try (var in = bundleUrl.openStream()) {
- existingBundle.update(in);
- targetBundle = existingBundle;
- } catch (BundleException | IOException e) {
- CopilotCore.LOGGER.error("Failed to update terminal bundle", e);
- return new Status(IStatus.ERROR, bundleContext.getBundle().getSymbolicName(),
- "Failed to update terminal bundle: " + e.getMessage(), e);
- }
- } else {
- // Install new bundle
- try {
- targetBundle = bundleContext.installBundle(bundleUrl.toString());
- } catch (BundleException e) {
- CopilotCore.LOGGER.error("Failed to install terminal bundle", e);
- return new Status(IStatus.ERROR, bundleContext.getBundle().getSymbolicName(),
- "Failed to install terminal bundle: " + e.getMessage(), e);
- }
- }
- monitor.worked(20);
-
- // Refresh and start the bundle
- monitor.subTask("Refreshing bundles");
- refreshBundles(Set.of(targetBundle));
- monitor.worked(20);
-
- monitor.subTask("Starting bundle");
- ensureStarted(targetBundle);
- monitor.worked(20);
-
- return Status.OK_STATUS;
- }
-
- /**
- * Get missing dependencies by reading Require-Bundle from the embedded JAR's MANIFEST.MF and checking which ones are
- * not available in the runtime.
- *
- * @return list of missing bundle symbolic names, empty if all dependencies are available
- */
- private List getMissingDependencies() {
- List missing = new ArrayList<>();
-
- try {
- String jarName = isModernTerminal ? MODERN_TERMINAL_BUNDLE_JAR : TM_TERMINAL_BUNDLE_JAR;
- URL bundleUrl = getEmbeddedBundleUrl(jarName);
- if (bundleUrl == null) {
- return missing;
- }
-
- try (JarInputStream jarStream = new JarInputStream(bundleUrl.openStream())) {
- Manifest manifest = jarStream.getManifest();
- if (manifest != null) {
- String requireBundle = manifest.getMainAttributes().getValue("Require-Bundle");
- if (requireBundle != null) {
- for (String bundleName : parseRequireBundle(requireBundle)) {
- if (Platform.getBundle(bundleName) == null) {
- missing.add(bundleName);
- }
- }
- }
- }
- }
- } catch (IOException e) {
- CopilotCore.LOGGER.error("Failed to check dependencies from embedded JAR", e);
- }
-
- return missing;
- }
-
- /**
- * Parse the Require-Bundle manifest header to extract bundle symbolic names. Uses Eclipse's ManifestElement parser
- * for accurate OSGi header parsing.
- *
- * @param requireBundle the Require-Bundle header value
- * @return array of bundle symbolic names
- */
- private String[] parseRequireBundle(String requireBundle) {
- List dependencies = new ArrayList<>();
-
- try {
- ManifestElement[] elements = ManifestElement.parseHeader(Constants.REQUIRE_BUNDLE, requireBundle);
- if (elements != null) {
- for (ManifestElement element : elements) {
- String bundleName = element.getValue();
- if (bundleName != null && !bundleName.isEmpty()) {
- dependencies.add(bundleName);
- }
- }
- }
- } catch (BundleException e) {
- CopilotCore.LOGGER.error("Failed to parse Require-Bundle header", e);
- }
-
- return dependencies.toArray(new String[0]);
- }
-
- /**
- * Detect if the current Eclipse platform supports modern terminal (Eclipse 4.37+).
- */
- private static boolean detectModernTerminal() {
- Version currentVersion = PlatformUtils.getEclipseVersion();
- if (currentVersion == null) {
- // Default to modern terminal if version check fails
- return true;
- }
- return currentVersion.compareTo(TARGET_PLATFORM_VERSION) >= 0;
- }
-
- /**
- * Get an installed bundle by symbolic name.
- */
- private Bundle getInstalledBundle(String symbolicName) {
- for (Bundle bundle : bundleContext.getBundles()) {
- if (symbolicName.equals(bundle.getSymbolicName())) {
- return bundle;
- }
- }
- return null;
- }
-
- /**
- * Refresh bundles to apply wiring changes.
- */
- private void refreshBundles(Set toRefresh) throws InterruptedException {
- if (!toRefresh.isEmpty()) {
- final CountDownLatch latch = new CountDownLatch(1);
- FrameworkWiring frameworkWiring = bundleContext.getBundle(0).adapt(FrameworkWiring.class);
- frameworkWiring.refreshBundles(toRefresh, new FrameworkListener() {
- @Override
- public void frameworkEvent(FrameworkEvent event) {
- if (event.getType() == FrameworkEvent.PACKAGES_REFRESHED) {
- latch.countDown();
- } else if (event.getType() == FrameworkEvent.ERROR) {
- latch.countDown();
- }
- }
- });
- latch.await(10, TimeUnit.SECONDS);
- }
- }
-
- /**
- * Ensure a bundle is started.
- */
- private void ensureStarted(Bundle bundle) throws BundleException {
- if (bundle.getState() != Bundle.ACTIVE && bundle.getState() != Bundle.STARTING) {
- bundle.start(Bundle.START_TRANSIENT | Bundle.START_ACTIVATION_POLICY);
- }
- }
-}
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT license.
+
+package com.microsoft.copilot.eclipse.terminal.api;
+
+import java.util.concurrent.CopyOnWriteArrayList;
+
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.FrameworkUtil;
+import org.osgi.framework.ServiceReference;
+import org.osgi.util.tracker.ServiceTracker;
+import org.osgi.util.tracker.ServiceTrackerCustomizer;
+
+/**
+ * Central manager for terminal services. Tracks the {@link IRunInTerminalTool} OSGi service provided by the terminal
+ * implementation bundle and notifies listeners when it becomes available.
+ */
+public class TerminalServiceManager {
+
+ /**
+ * Static inner class for lazy initialization of singleton instance.
+ */
+ private static class InstanceHolder {
+ private static final TerminalServiceManager INSTANCE = createInstance();
+
+ private static TerminalServiceManager createInstance() {
+ Bundle apiBundle = FrameworkUtil.getBundle(TerminalServiceManager.class);
+ if (apiBundle != null) {
+ BundleContext context = apiBundle.getBundleContext();
+ if (context != null) {
+ TerminalServiceManager instance = new TerminalServiceManager(context);
+ instance.start();
+ return instance;
+ }
+ }
+ return null;
+ }
+ }
+
+ private final BundleContext bundleContext;
+ private ServiceTracker serviceTracker;
+ private final CopyOnWriteArrayList listeners = new CopyOnWriteArrayList<>();
+ private volatile IRunInTerminalTool currentService = null;
+
+ /**
+ * Interface for listening to terminal service availability changes.
+ */
+ public interface TerminalServiceListener {
+ /**
+ * Called when a terminal service becomes available.
+ *
+ * @param service the available terminal service
+ */
+ void onServiceAvailable(IRunInTerminalTool service);
+ }
+
+ private TerminalServiceManager(BundleContext bundleContext) {
+ this.bundleContext = bundleContext;
+ }
+
+ /**
+ * Get the singleton instance of TerminalServiceManager.
+ */
+ public static TerminalServiceManager getInstance() {
+ return InstanceHolder.INSTANCE;
+ }
+
+ /**
+ * Add a listener for terminal service events.
+ */
+ public void addListener(TerminalServiceListener listener) {
+ if (listener != null) {
+ listeners.add(listener);
+
+ // If service is already available, notify immediately
+ if (currentService != null) {
+ listener.onServiceAvailable(currentService);
+ }
+ }
+ }
+
+ /**
+ * Remove a listener for terminal service events.
+ */
+ public void removeListener(TerminalServiceListener listener) {
+ listeners.remove(listener);
+ }
+
+ /**
+ * Get the current terminal service if available.
+ */
+ public IRunInTerminalTool getCurrentService() {
+ return currentService;
+ }
+
+ /**
+ * Start tracking terminal services.
+ */
+ private void start() {
+ ServiceTrackerCustomizer customizer = new ServiceTrackerCustomizer<>() {
+ @Override
+ public IRunInTerminalTool addingService(ServiceReference reference) {
+ IRunInTerminalTool service = bundleContext.getService(reference);
+ if (service != null) {
+ currentService = service;
+ notifyServiceAvailable(service);
+ }
+ return service;
+ }
+
+ @Override
+ public void modifiedService(ServiceReference reference, IRunInTerminalTool service) {
+ if (service != null) {
+ currentService = service;
+ notifyServiceAvailable(service);
+ }
+ }
+
+ @Override
+ public void removedService(ServiceReference reference, IRunInTerminalTool service) {
+ }
+ };
+
+ serviceTracker = new ServiceTracker<>(bundleContext, IRunInTerminalTool.class, customizer);
+ serviceTracker.open();
+
+ IRunInTerminalTool[] services = serviceTracker.getServices(new IRunInTerminalTool[0]);
+ if (services != null && services.length > 0) {
+ currentService = services[0];
+ }
+ }
+
+ /**
+ * Stop the service manager.
+ */
+ public void stop() {
+ if (serviceTracker != null) {
+ serviceTracker.close();
+ serviceTracker = null;
+ }
+ currentService = null;
+ listeners.clear();
+ }
+
+ private void notifyServiceAvailable(IRunInTerminalTool service) {
+ for (TerminalServiceListener listener : listeners) {
+ listener.onServiceAvailable(service);
+ }
+ }
+}
diff --git a/com.microsoft.copilot.eclipse.ui.jobs.test/.classpath b/com.microsoft.copilot.eclipse.ui.jobs.test/.classpath
index 38f401ad4..2167a547d 100644
--- a/com.microsoft.copilot.eclipse.ui.jobs.test/.classpath
+++ b/com.microsoft.copilot.eclipse.ui.jobs.test/.classpath
@@ -1,6 +1,6 @@
-
+
diff --git a/com.microsoft.copilot.eclipse.ui.jobs.test/META-INF/MANIFEST.MF b/com.microsoft.copilot.eclipse.ui.jobs.test/META-INF/MANIFEST.MF
index 7acdbcaf6..4be973136 100644
--- a/com.microsoft.copilot.eclipse.ui.jobs.test/META-INF/MANIFEST.MF
+++ b/com.microsoft.copilot.eclipse.ui.jobs.test/META-INF/MANIFEST.MF
@@ -4,10 +4,11 @@ Bundle-Name: com.microsoft.copilot.eclipse.ui.jobs.test
Bundle-SymbolicName: com.microsoft.copilot.eclipse.ui.jobs.test;singleton:=true
Bundle-Version: 0.21.0.qualifier
Bundle-Vendor: GitHub Copilot
-Bundle-RequiredExecutionEnvironment: JavaSE-17
+Bundle-RequiredExecutionEnvironment: JavaSE-21
Automatic-Module-Name: com.microsoft.copilot.eclipse.ui.jobs.test
-Require-Bundle: junit-jupiter-api;bundle-version="5.10.1",
- junit-jupiter-params;bundle-version="5.10.1",
+Require-Bundle: junit-jupiter-api;bundle-version="[5.10.1,6.0.0)",
+ junit-jupiter-engine;bundle-version="[5.10.1,6.0.0)",
+ junit-jupiter-params;bundle-version="[5.10.1,6.0.0)",
org.eclipse.core.runtime;bundle-version="[3.30.0,4.0.0)",
com.microsoft.copilot.eclipse.ui.jobs;bundle-version="0.21.0"
Import-Package: org.osgi.framework;version="[1.10.0,2.0.0)"
diff --git a/com.microsoft.copilot.eclipse.ui.jobs/.classpath b/com.microsoft.copilot.eclipse.ui.jobs/.classpath
index 5508535a4..b1415d56b 100644
--- a/com.microsoft.copilot.eclipse.ui.jobs/.classpath
+++ b/com.microsoft.copilot.eclipse.ui.jobs/.classpath
@@ -1,7 +1,11 @@
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
diff --git a/com.microsoft.copilot.eclipse.ui.jobs/.settings/org.eclipse.core.resources.prefs b/com.microsoft.copilot.eclipse.ui.jobs/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 000000000..4824b8026
--- /dev/null
+++ b/com.microsoft.copilot.eclipse.ui.jobs/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,2 @@
+eclipse.preferences.version=1
+encoding/=UTF-8
diff --git a/com.microsoft.copilot.eclipse.ui.jobs/.settings/org.eclipse.jdt.core.prefs b/com.microsoft.copilot.eclipse.ui.jobs/.settings/org.eclipse.jdt.core.prefs
index 20cc7b588..f7d4b5bfd 100644
--- a/com.microsoft.copilot.eclipse.ui.jobs/.settings/org.eclipse.jdt.core.prefs
+++ b/com.microsoft.copilot.eclipse.ui.jobs/.settings/org.eclipse.jdt.core.prefs
@@ -1,10 +1,10 @@
eclipse.preferences.version=1
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=17
-org.eclipse.jdt.core.compiler.compliance=17
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=21
+org.eclipse.jdt.core.compiler.compliance=21
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
-org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=error
org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning
org.eclipse.jdt.core.compiler.release=enabled
-org.eclipse.jdt.core.compiler.source=17
+org.eclipse.jdt.core.compiler.source=21
diff --git a/com.microsoft.copilot.eclipse.ui.jobs/META-INF/MANIFEST.MF b/com.microsoft.copilot.eclipse.ui.jobs/META-INF/MANIFEST.MF
index 0fee3467d..e76c9cd27 100644
--- a/com.microsoft.copilot.eclipse.ui.jobs/META-INF/MANIFEST.MF
+++ b/com.microsoft.copilot.eclipse.ui.jobs/META-INF/MANIFEST.MF
@@ -5,7 +5,7 @@ Bundle-SymbolicName: com.microsoft.copilot.eclipse.ui.jobs;singleton:=true
Bundle-Version: 0.21.0.qualifier
Bundle-Vendor: GitHub Copilot
Bundle-Activator: com.microsoft.copilot.eclipse.ui.jobs.CopilotJobs
-Bundle-RequiredExecutionEnvironment: JavaSE-17
+Bundle-RequiredExecutionEnvironment: JavaSE-21
Bundle-Localization: plugin
Automatic-Module-Name: com.microsoft.copilot.eclipse.ui.jobs
Bundle-ActivationPolicy: lazy
diff --git a/com.microsoft.copilot.eclipse.ui.jobs/build.properties b/com.microsoft.copilot.eclipse.ui.jobs/build.properties
index 18012dbed..2257d7129 100644
--- a/com.microsoft.copilot.eclipse.ui.jobs/build.properties
+++ b/com.microsoft.copilot.eclipse.ui.jobs/build.properties
@@ -1,5 +1,5 @@
source.. = src/
-output.. = bin/
+output.. = target/classes/
bin.includes = META-INF/,\
.,\
plugin.xml,\
diff --git a/com.microsoft.copilot.eclipse.ui.terminal.tm/.checkstyle b/com.microsoft.copilot.eclipse.ui.terminal.tm/.checkstyle
deleted file mode 100644
index 357a84774..000000000
--- a/com.microsoft.copilot.eclipse.ui.terminal.tm/.checkstyle
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
-
-
-
diff --git a/com.microsoft.copilot.eclipse.ui.terminal.tm/.classpath b/com.microsoft.copilot.eclipse.ui.terminal.tm/.classpath
deleted file mode 100644
index 8d8612144..000000000
--- a/com.microsoft.copilot.eclipse.ui.terminal.tm/.classpath
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
-
-
-
diff --git a/com.microsoft.copilot.eclipse.ui.terminal.tm/.project b/com.microsoft.copilot.eclipse.ui.terminal.tm/.project
deleted file mode 100644
index cac3b0de6..000000000
--- a/com.microsoft.copilot.eclipse.ui.terminal.tm/.project
+++ /dev/null
@@ -1,45 +0,0 @@
-
-
- com.microsoft.copilot.eclipse.ui.terminal.tm
-
-
-
-
-
- org.eclipse.jdt.core.javabuilder
-
-
-
-
- org.eclipse.pde.ManifestBuilder
-
-
-
-
- org.eclipse.pde.SchemaBuilder
-
-
-
-
- net.sf.eclipsecs.core.CheckstyleBuilder
-
-
-
-
- org.eclipse.m2e.core.maven2Builder
-
-
-
-
- org.eclipse.pde.ds.core.builder
-
-
-
-
-
- org.eclipse.m2e.core.maven2Nature
- org.eclipse.pde.PluginNature
- org.eclipse.jdt.core.javanature
- net.sf.eclipsecs.core.CheckstyleNature
-
-
diff --git a/com.microsoft.copilot.eclipse.ui.terminal.tm/.settings/org.eclipse.jdt.core.prefs b/com.microsoft.copilot.eclipse.ui.terminal.tm/.settings/org.eclipse.jdt.core.prefs
deleted file mode 100644
index 62ef3488c..000000000
--- a/com.microsoft.copilot.eclipse.ui.terminal.tm/.settings/org.eclipse.jdt.core.prefs
+++ /dev/null
@@ -1,9 +0,0 @@
-eclipse.preferences.version=1
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=17
-org.eclipse.jdt.core.compiler.compliance=17
-org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
-org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
-org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
-org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning
-org.eclipse.jdt.core.compiler.release=enabled
-org.eclipse.jdt.core.compiler.source=17
diff --git a/com.microsoft.copilot.eclipse.ui.terminal.tm/.settings/org.eclipse.m2e.core.prefs b/com.microsoft.copilot.eclipse.ui.terminal.tm/.settings/org.eclipse.m2e.core.prefs
deleted file mode 100644
index f897a7f1c..000000000
--- a/com.microsoft.copilot.eclipse.ui.terminal.tm/.settings/org.eclipse.m2e.core.prefs
+++ /dev/null
@@ -1,4 +0,0 @@
-activeProfiles=
-eclipse.preferences.version=1
-resolveWorkspaceProjects=true
-version=1
diff --git a/com.microsoft.copilot.eclipse.ui.terminal.tm/META-INF/MANIFEST.MF b/com.microsoft.copilot.eclipse.ui.terminal.tm/META-INF/MANIFEST.MF
deleted file mode 100644
index c4a5f14bc..000000000
--- a/com.microsoft.copilot.eclipse.ui.terminal.tm/META-INF/MANIFEST.MF
+++ /dev/null
@@ -1,21 +0,0 @@
-Manifest-Version: 1.0
-Bundle-ManifestVersion: 2
-Bundle-Name: com.microsoft.copilot.eclipse.ui.terminal.tm
-Bundle-SymbolicName: com.microsoft.copilot.eclipse.ui.terminal.tm;singleton:=true
-Bundle-Version: 0.21.0.qualifier
-Bundle-Vendor: GitHub Copilot
-Bundle-RequiredExecutionEnvironment: JavaSE-17
-Automatic-Module-Name: com.microsoft.copilot.eclipse.ui.terminal.tm
-Bundle-ActivationPolicy: lazy
-Service-Component: OSGI-INF/component.xml
-Import-Package: org.osgi.framework;version="[1.10.0,2.0.0)",
- org.osgi.service.component
-Require-Bundle: com.microsoft.copilot.eclipse.terminal.api;bundle-version="0.21.0",
- org.eclipse.tm.terminal.view.core,
- org.eclipse.tm.terminal.view.ui,
- org.eclipse.tm.terminal.control,
- org.eclipse.tm.terminal.connector.local,
- org.eclipse.tm.terminal.connector.process,
- org.eclipse.ui;bundle-version="3.205.0",
- org.apache.commons.lang3;bundle-version="3.13.0",
- org.eclipse.core.runtime;bundle-version="[3.30.0,4.0.0)"
diff --git a/com.microsoft.copilot.eclipse.ui.terminal.tm/OSGI-INF/component.xml b/com.microsoft.copilot.eclipse.ui.terminal.tm/OSGI-INF/component.xml
deleted file mode 100644
index c21fca9cb..000000000
--- a/com.microsoft.copilot.eclipse.ui.terminal.tm/OSGI-INF/component.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
-
-
-
diff --git a/com.microsoft.copilot.eclipse.ui.terminal.tm/build.properties b/com.microsoft.copilot.eclipse.ui.terminal.tm/build.properties
deleted file mode 100644
index 4aee9b7ab..000000000
--- a/com.microsoft.copilot.eclipse.ui.terminal.tm/build.properties
+++ /dev/null
@@ -1,5 +0,0 @@
-source.. = src/
-output.. = bin/
-bin.includes = META-INF/,\
- .,\
- OSGI-INF/component.xml
\ No newline at end of file
diff --git a/com.microsoft.copilot.eclipse.ui.terminal.tm/pom.xml b/com.microsoft.copilot.eclipse.ui.terminal.tm/pom.xml
deleted file mode 100644
index 1d4b39049..000000000
--- a/com.microsoft.copilot.eclipse.ui.terminal.tm/pom.xml
+++ /dev/null
@@ -1,37 +0,0 @@
-
- 4.0.0
-
- com.microsoft.copilot.eclipse
- github-copilot-for-eclipse
- ${copilot-plugin-version}
-
- com.microsoft.copilot.eclipse.ui.terminal.tm
- eclipse-plugin
- ${base.name} :: TM Terminal
-
-
-
- org.eclipse.tycho
- target-platform-configuration
- ${tycho-version}
-
-
- ../target-tm-terminal.target
-
-
-
-
- org.eclipse.tycho
- tycho-maven-plugin
- ${tycho-version}
- true
-
-
- org.eclipse.tycho
- tycho-packaging-plugin
-
-
-
-
\ No newline at end of file
diff --git a/com.microsoft.copilot.eclipse.ui.terminal.tm/src/com/microsoft/copilot/eclipse/ui/terminal/tm/RunInTerminalTool.java b/com.microsoft.copilot.eclipse.ui.terminal.tm/src/com/microsoft/copilot/eclipse/ui/terminal/tm/RunInTerminalTool.java
deleted file mode 100644
index 4e27a0d30..000000000
--- a/com.microsoft.copilot.eclipse.ui.terminal.tm/src/com/microsoft/copilot/eclipse/ui/terminal/tm/RunInTerminalTool.java
+++ /dev/null
@@ -1,437 +0,0 @@
-// Copyright (c) Microsoft Corporation.
-// Licensed under the MIT license.
-
-package com.microsoft.copilot.eclipse.ui.terminal.tm;
-
-import java.nio.charset.StandardCharsets;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.UUID;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.atomic.AtomicReference;
-import java.util.function.Supplier;
-
-import org.apache.commons.lang3.StringUtils;
-import org.eclipse.core.runtime.Platform;
-import org.eclipse.swt.custom.CTabFolder;
-import org.eclipse.swt.custom.CTabItem;
-import org.eclipse.swt.events.DisposeListener;
-import org.eclipse.swt.graphics.Image;
-import org.eclipse.swt.widgets.Display;
-import org.eclipse.tm.internal.terminal.control.ITerminalViewControl;
-import org.eclipse.tm.internal.terminal.provisional.api.ITerminalControl;
-import org.eclipse.tm.terminal.view.core.TerminalServiceFactory;
-import org.eclipse.tm.terminal.view.core.interfaces.ITerminalService;
-import org.eclipse.tm.terminal.view.core.interfaces.ITerminalServiceOutputStreamMonitorListener;
-import org.eclipse.tm.terminal.view.core.interfaces.constants.ITerminalsConnectorConstants;
-import org.eclipse.tm.terminal.view.ui.activator.UIPlugin;
-import org.eclipse.tm.terminal.view.ui.interfaces.IPreferenceKeys;
-import org.eclipse.tm.terminal.view.ui.interfaces.IUIConstants;
-import org.eclipse.ui.IViewPart;
-import org.eclipse.ui.IWorkbench;
-import org.eclipse.ui.IWorkbenchPage;
-import org.eclipse.ui.IWorkbenchWindow;
-import org.eclipse.ui.PartInitException;
-import org.eclipse.ui.PlatformUI;
-import org.osgi.service.component.annotations.Component;
-
-import com.microsoft.copilot.eclipse.terminal.api.IRunInTerminalTool;
-import com.microsoft.copilot.eclipse.terminal.api.ShellIntegrationScripts;
-import com.microsoft.copilot.eclipse.terminal.api.TerminalCommandProcessor;
-import com.microsoft.copilot.eclipse.terminal.api.TerminalCommandProcessor.CompletionCheckResult;
-import com.microsoft.copilot.eclipse.terminal.api.TerminalCommandProcessor.CompletionCheckState;
-
-/**
- * terminal tool implementation for older Eclipse versions.
- */
-@Component(service = IRunInTerminalTool.class, immediate = true)
-public class RunInTerminalTool implements IRunInTerminalTool {
- // Shared constants and static fields
- private static final Object lock = new Object();
- private static final Map backgroundCommandOutputs = new HashMap<>();
- private static final String BACKGROUND_TERMINAL_PREFIX = "Copilot-";
- private static final String POWERSHELL_SCRIPT_ENV = "COPILOT_POWERSHELL_INTEGRATION_SCRIPT";
- private static final String COMMAND_CANCELLED_MESSAGE = "Terminal command cancelled.";
- private static final String COMMAND_INTERRUPTED_MESSAGE = "Terminal command interrupted by a new command.";
-
- // Non-background terminal field
- private ITerminalViewControl persistentTerminalViewControl;
-
- // Terminal UI-related fields
- private ITerminalControl terminalControl;
- private CTabFolder tabFolder;
- private CTabItem copilotTabItem;
- private Supplier terminalIconSupplier;
-
- // Output and command state
- private StringBuilder sb;
- private volatile ForegroundCommand foregroundCommand;
-
- /**
- * Constructor for RunInTerminalTool.
- */
- public RunInTerminalTool() {
- this.sb = new StringBuilder();
- }
-
- @Override
- public CompletableFuture executeCommand(String command, boolean isBackground, String workingDirectory) {
- if (StringUtils.isBlank(command)) {
- return CompletableFuture.completedFuture("The command is null or empty.");
- }
-
- if (!isBackground) {
- closeRunningForegroundTerminal(COMMAND_INTERRUPTED_MESSAGE);
- }
-
- CompletableFuture commandFuture = new CompletableFuture<>();
- ForegroundCommand commandState = isBackground ? null
- : new ForegroundCommand(commandFuture, hasShellIntegrationMarker());
-
- if (commandState != null) {
- foregroundCommand = commandState;
- if (!commandState.useMarker()) {
- // Retain only the last line (prompt) in the output buffer
- if (!sb.isEmpty()) {
- int lastLineStart = sb.lastIndexOf(StringUtils.LF);
- if (lastLineStart > 0) {
- sb.delete(0, lastLineStart);
- }
- }
- } else {
- // For marker-based detection, clear the buffer
- sb.setLength(0);
- }
- }
-
- String executionId = UUID.randomUUID().toString();
- final String finalCommand = TerminalCommandProcessor.formatForExecution(command, useBracketedPaste());
-
- synchronized (lock) {
- if (!isBackground && this.persistentTerminalViewControl != null) {
- revealTerminal();
- sendCommand(this.persistentTerminalViewControl, finalCommand);
- return commandFuture;
- }
-
- ITerminalService service = TerminalServiceFactory.getService();
- if (service == null) {
- clearForegroundCommand(commandState);
- return CompletableFuture.completedFuture("Failed to open terminal console due to terminal service is null.");
- }
-
- service.openConsole(prepareTerminalProperties(isBackground, executionId, workingDirectory), status -> {
- if (status.isOK()) {
- if (commandFuture.isDone()) {
- return;
- }
- ITerminalViewControl terminalViewControl = finalizeTerminalSetup(executionId, isBackground);
- if (terminalViewControl == null) {
- clearForegroundCommand(commandState);
- commandFuture.complete("Terminal view control cannot be setup for RunInTerminalTool.");
- return;
- }
-
- if (!isBackground) {
- this.persistentTerminalViewControl = terminalViewControl;
- revealTerminal();
- }
- sendCommand(terminalViewControl, finalCommand);
- } else {
- clearForegroundCommand(commandState);
- commandFuture.complete("Failed to open terminal console: " + status.getException());
- }
- });
- }
-
- if (isBackground) {
- return CompletableFuture.completedFuture("Command is running in terminal with ID=" + executionId);
- }
-
- return commandFuture;
- }
-
- @Override
- public Map prepareTerminalProperties(boolean runInBackground, String executionId,
- String workingDirectory) {
- Map properties = new HashMap<>();
-
- properties.put(ITerminalsConnectorConstants.PROP_ENCODING, "UTF-8");
- properties.put(ITerminalsConnectorConstants.PROP_TITLE_DISABLE_ANSI_TITLE, true);
- if (StringUtils.isNotBlank(workingDirectory)) {
- properties.put(ITerminalsConnectorConstants.PROP_PROCESS_WORKING_DIR, workingDirectory);
- }
-
- if (Platform.getOS().equals(Platform.OS_WIN32)) {
- properties.put(ITerminalsConnectorConstants.PROP_PROCESS_PATH, "powershell.exe");
- String scriptPath = ShellIntegrationScripts.getPowerShellScriptPath();
- if (scriptPath != null) {
- String[] environment = new String[] { POWERSHELL_SCRIPT_ENV + "=" + scriptPath };
- String args = "-NoExit -ExecutionPolicy Bypass -Command \". $env:" + POWERSHELL_SCRIPT_ENV + "\"";
- properties.put(ITerminalsConnectorConstants.PROP_PROCESS_ENVIRONMENT, environment);
- properties.put(ITerminalsConnectorConstants.PROP_PROCESS_MERGE_ENVIRONMENT, true);
- properties.put(ITerminalsConnectorConstants.PROP_PROCESS_ARGS, args);
- }
- } else if (Platform.getOS().equals(Platform.OS_LINUX)) {
- properties.put(ITerminalsConnectorConstants.PROP_PROCESS_PATH, "/bin/bash");
- String scriptPath = ShellIntegrationScripts.getBashScriptPath();
- if (scriptPath != null) {
- properties.put(ITerminalsConnectorConstants.PROP_PROCESS_ARGS, "--init-file \"" + scriptPath + "\" -i");
- }
- } else {
- // macOS or other Unix-like: keep existing behavior, only set args if empty
- String args = UIPlugin.getScopedPreferences()
- .getString(IPreferenceKeys.PREF_LOCAL_TERMINAL_DEFAULT_SHELL_UNIX_ARGS);
- if (StringUtils.isBlank(args)) {
- properties.put(ITerminalsConnectorConstants.PROP_PROCESS_ARGS, "-l");
- }
- }
-
- properties.put(ITerminalsConnectorConstants.PROP_FORCE_NEW, true);
- properties.put(ITerminalsConnectorConstants.PROP_DELEGATE_ID,
- "org.eclipse.tm.terminal.connector.local.launcher.local");
-
- if (runInBackground) {
- properties.put(ITerminalsConnectorConstants.PROP_TITLE, buildBackgroundTerminalTitle(executionId));
- properties.put(ITerminalsConnectorConstants.PROP_STDOUT_LISTENERS,
- new ITerminalServiceOutputStreamMonitorListener[] { buildOutputStreamMonitorListener(true, executionId) });
- } else {
- properties.put(ITerminalsConnectorConstants.PROP_TITLE, "Copilot");
- properties.put(ITerminalsConnectorConstants.PROP_STDOUT_LISTENERS,
- new ITerminalServiceOutputStreamMonitorListener[] { buildOutputStreamMonitorListener(false, null) });
- }
-
- return properties;
- }
-
- @Override
- public StringBuilder getBackgroundCommandOutput(String executionId) {
- StringBuilder output = backgroundCommandOutputs.get(executionId);
- return output;
- }
-
- @Override
- public void cancelCurrentCommand() {
- closeRunningForegroundTerminal(COMMAND_CANCELLED_MESSAGE);
- }
-
- private void closeRunningForegroundTerminal(String completionMessage) {
- ForegroundCommand commandState = foregroundCommand;
- if (commandState != null && !commandState.future().isDone()) {
- closeCurrentForegroundTerminal(completionMessage);
- }
- }
-
- private void closeCurrentForegroundTerminal(String completionMessage) {
- ForegroundCommand commandState = null;
- CTabItem tabItem = null;
- synchronized (lock) {
- commandState = foregroundCommand;
- foregroundCommand = null;
- persistentTerminalViewControl = null;
- tabItem = copilotTabItem;
- copilotTabItem = null;
- sb.setLength(0);
- }
-
- if (tabItem != null) {
- final CTabItem tabItemToDispose = tabItem;
- // Keep this synchronous so a new foreground command cannot open before the old terminal tab is disposed.
- Display.getDefault().syncExec(() -> {
- if (!tabItemToDispose.isDisposed()) {
- tabItemToDispose.dispose();
- }
- });
- }
- if (commandState != null && !commandState.future().isDone()) {
- commandState.future().complete(completionMessage);
- }
- }
-
- private void clearForegroundCommand(ForegroundCommand commandState) {
- if (commandState != null && foregroundCommand == commandState) {
- foregroundCommand = null;
- }
- }
-
- private void sendCommand(ITerminalViewControl terminalViewControl, String command) {
- terminalViewControl.pasteString(command);
- }
-
- private boolean hasShellIntegrationMarker() {
- if (Platform.getOS().equals(Platform.OS_WIN32)) {
- return ShellIntegrationScripts.getPowerShellScriptPath() != null;
- }
- if (Platform.getOS().equals(Platform.OS_LINUX)) {
- return ShellIntegrationScripts.getBashScriptPath() != null;
- }
- return false;
- }
-
- private boolean useBracketedPaste() {
- // macOS terminal multiline handling differs from PowerShell/Bash integration, so keep its existing plain input.
- return Platform.getOS().equals(Platform.OS_WIN32) || Platform.getOS().equals(Platform.OS_LINUX);
- }
-
- private ITerminalViewControl finalizeTerminalSetup(String executionId, boolean isBackground) {
- String title = isBackground ? buildBackgroundTerminalTitle(executionId) : "Copilot";
- synchronized (lock) {
- terminalControl = getTerminalControl(title, isBackground);
- if (terminalControl != null && terminalControl instanceof ITerminalViewControl iterminalviewcontrol) {
- return iterminalviewcontrol;
- }
- }
- return null;
- }
-
- private ITerminalControl getTerminalControl(String terminalTitle, boolean isBackground) {
- AtomicReference ref = new AtomicReference<>();
-
- Display.getDefault().syncExec(() -> {
- try {
- IWorkbenchPage page = getActivePage();
- if (page != null) {
- IViewPart view = page.showView(IUIConstants.ID, null, IWorkbenchPage.VIEW_VISIBLE);
- if (view != null) {
- tabFolder = view.getAdapter(CTabFolder.class);
- if (tabFolder != null) {
- for (CTabItem item : tabFolder.getItems()) {
- if (terminalTitle.equals(item.getText())) {
- Image terminalIcon = resolveTerminalIcon();
- if (terminalIcon != null && !terminalIcon.isDisposed()) {
- item.setImage(terminalIcon);
- }
- item.addDisposeListener(
- buildDisposeListener(terminalTitle.replace(BACKGROUND_TERMINAL_PREFIX, ""), isBackground));
- if (!isBackground) {
- // Foreground terminal command will reuse the tab item, so keep a reference to the tab item
- copilotTabItem = item;
- }
- ref.set((ITerminalControl) item.getData());
- break;
- }
- }
- }
- }
- }
- } catch (PartInitException e) {
- // Skip exception
- }
- });
-
- return ref.get();
- }
-
- private ITerminalServiceOutputStreamMonitorListener buildOutputStreamMonitorListener(boolean isBackground,
- String executionId) {
- StringBuilder output = isBackground ? new StringBuilder() : sb;
- if (isBackground) {
- backgroundCommandOutputs.put(executionId, output);
- }
-
- return (byteBuffer, bytesRead) -> {
- String content = new String(byteBuffer, 0, bytesRead, StandardCharsets.UTF_8);
- // Remove ANSI escape sequences while preserving only real line breaks from the terminal output.
- content = content.replaceAll("\u001B\\[(\\?)?[\\d;]*[a-zA-Z]", "");
-
- // Handle Windows terminal title sequences - using Platform instead of
- // PlatformUtils
- if (Platform.getOS().equals(Platform.OS_WIN32)) {
- // Remove terminal title sequences in Windows
- // It sometimes appears at the last line, which will also destroy the validation
- // of the last prompt line.
- content = content.replaceAll("\u001B\\][0-9];.*?(\u0007|\u001B\\\\)", "");
- }
-
- output.append(content);
-
- // Detect completion based on platform strategy
- ForegroundCommand commandState = foregroundCommand;
- if (!isBackground && commandState != null && !commandState.future().isDone()) {
- CompletionCheckResult completionResult = commandState.useMarker()
- ? TerminalCommandProcessor.tryCompleteWithMarker(output)
- : TerminalCommandProcessor.tryCompleteWithPrompt(output);
- handleCompletionResult(commandState, completionResult);
- }
- };
- }
-
- private void handleCompletionResult(ForegroundCommand commandState, CompletionCheckResult completionResult) {
- if (completionResult.state() == CompletionCheckState.INCOMPLETE) {
- return;
- }
- if (foregroundCommand == commandState) {
- foregroundCommand = null;
- }
- if (!commandState.future().isDone()) {
- commandState.future().complete(completionResult.output());
- }
- }
-
- private DisposeListener buildDisposeListener(String executionId, boolean isBackground) {
- return e -> {
- if (isBackground) {
- backgroundCommandOutputs.remove(executionId);
- } else {
- persistentTerminalViewControl = null;
- }
-
- if (backgroundCommandOutputs.isEmpty() && persistentTerminalViewControl == null) {
- terminalControl = null;
- }
- };
- }
-
- private void revealTerminal() {
- if (tabFolder != null && copilotTabItem != null) {
- Display.getDefault().syncExec(() -> {
- try {
- IWorkbenchPage page = getActivePage();
- if (page != null) {
- IViewPart view = page.showView(IUIConstants.ID, null, IWorkbenchPage.VIEW_VISIBLE);
- if (tabFolder.isDisposed() && view != null) {
- tabFolder = view.getAdapter(CTabFolder.class);
- }
- }
- if (tabFolder != null && !tabFolder.isDisposed()) {
- tabFolder.setSelection(copilotTabItem);
- }
- } catch (PartInitException e) {
- // Skip exception
- }
- });
- }
- }
-
- private String buildBackgroundTerminalTitle(String executionId) {
- return BACKGROUND_TERMINAL_PREFIX + executionId;
- }
-
- private record ForegroundCommand(CompletableFuture future, boolean useMarker) {
- }
-
- /**
- * Get active workbench page without UiUtils dependency.
- */
- private IWorkbenchPage getActivePage() {
- IWorkbench workbench = PlatformUI.getWorkbench();
- IWorkbenchWindow window = workbench.getActiveWorkbenchWindow();
- if (window != null) {
- return window.getActivePage();
- }
- return null;
- }
-
- @Override
- public void setTerminalIconSupplier(Supplier terminalIconSupplier) {
- this.terminalIconSupplier = terminalIconSupplier;
- }
-
- /** Call this method from UI thread only. */
- private Image resolveTerminalIcon() {
- if (terminalIconSupplier == null) {
- return null;
- }
- return terminalIconSupplier.get();
- }
-}
diff --git a/com.microsoft.copilot.eclipse.ui.terminal/.classpath b/com.microsoft.copilot.eclipse.ui.terminal/.classpath
index e0ce1f7ec..b1415d56b 100644
--- a/com.microsoft.copilot.eclipse.ui.terminal/.classpath
+++ b/com.microsoft.copilot.eclipse.ui.terminal/.classpath
@@ -1,8 +1,11 @@
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
diff --git a/com.microsoft.copilot.eclipse.ui.terminal/.settings/org.eclipse.core.resources.prefs b/com.microsoft.copilot.eclipse.ui.terminal/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 000000000..4824b8026
--- /dev/null
+++ b/com.microsoft.copilot.eclipse.ui.terminal/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,2 @@
+eclipse.preferences.version=1
+encoding/=UTF-8
diff --git a/com.microsoft.copilot.eclipse.ui.terminal/.settings/org.eclipse.jdt.core.prefs b/com.microsoft.copilot.eclipse.ui.terminal/.settings/org.eclipse.jdt.core.prefs
index 62ef3488c..23fa13b17 100644
--- a/com.microsoft.copilot.eclipse.ui.terminal/.settings/org.eclipse.jdt.core.prefs
+++ b/com.microsoft.copilot.eclipse.ui.terminal/.settings/org.eclipse.jdt.core.prefs
@@ -1,9 +1,9 @@
eclipse.preferences.version=1
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=17
-org.eclipse.jdt.core.compiler.compliance=17
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=21
+org.eclipse.jdt.core.compiler.compliance=21
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning
org.eclipse.jdt.core.compiler.release=enabled
-org.eclipse.jdt.core.compiler.source=17
+org.eclipse.jdt.core.compiler.source=21
diff --git a/com.microsoft.copilot.eclipse.ui.terminal/META-INF/MANIFEST.MF b/com.microsoft.copilot.eclipse.ui.terminal/META-INF/MANIFEST.MF
index 4aa767cfc..bb646a7e7 100644
--- a/com.microsoft.copilot.eclipse.ui.terminal/META-INF/MANIFEST.MF
+++ b/com.microsoft.copilot.eclipse.ui.terminal/META-INF/MANIFEST.MF
@@ -3,7 +3,7 @@ Bundle-Name: com.microsoft.copilot.eclipse.ui.terminal
Bundle-SymbolicName: com.microsoft.copilot.eclipse.ui.terminal;singleton:=true
Bundle-Version: 0.21.0.qualifier
Bundle-Vendor: GitHub Copilot
-Bundle-RequiredExecutionEnvironment: JavaSE-17
+Bundle-RequiredExecutionEnvironment: JavaSE-21
Automatic-Module-Name: com.microsoft.copilot.eclipse.ui.terminal
Bundle-ActivationPolicy: lazy
Service-Component: OSGI-INF/component.xml
diff --git a/com.microsoft.copilot.eclipse.ui.terminal/build.properties b/com.microsoft.copilot.eclipse.ui.terminal/build.properties
index 4aee9b7ab..367dd831e 100644
--- a/com.microsoft.copilot.eclipse.ui.terminal/build.properties
+++ b/com.microsoft.copilot.eclipse.ui.terminal/build.properties
@@ -1,5 +1,5 @@
source.. = src/
-output.. = bin/
+output.. = target/classes/
bin.includes = META-INF/,\
.,\
OSGI-INF/component.xml
\ No newline at end of file
diff --git a/com.microsoft.copilot.eclipse.ui.terminal/pom.xml b/com.microsoft.copilot.eclipse.ui.terminal/pom.xml
index f70016ec1..830edfbf6 100644
--- a/com.microsoft.copilot.eclipse.ui.terminal/pom.xml
+++ b/com.microsoft.copilot.eclipse.ui.terminal/pom.xml
@@ -18,7 +18,7 @@
${tycho-version}
- ../target-terminal.target
+ ../target-platforms/2025-12.target
diff --git a/com.microsoft.copilot.eclipse.ui.test/.classpath b/com.microsoft.copilot.eclipse.ui.test/.classpath
index 38f401ad4..766df48f2 100644
--- a/com.microsoft.copilot.eclipse.ui.test/.classpath
+++ b/com.microsoft.copilot.eclipse.ui.test/.classpath
@@ -1,11 +1,15 @@
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/com.microsoft.copilot.eclipse.ui.test/.settings/org.eclipse.core.resources.prefs b/com.microsoft.copilot.eclipse.ui.test/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 000000000..4824b8026
--- /dev/null
+++ b/com.microsoft.copilot.eclipse.ui.test/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,2 @@
+eclipse.preferences.version=1
+encoding/=UTF-8
diff --git a/com.microsoft.copilot.eclipse.ui.test/.settings/org.eclipse.jdt.core.prefs b/com.microsoft.copilot.eclipse.ui.test/.settings/org.eclipse.jdt.core.prefs
index 62ef3488c..23fa13b17 100644
--- a/com.microsoft.copilot.eclipse.ui.test/.settings/org.eclipse.jdt.core.prefs
+++ b/com.microsoft.copilot.eclipse.ui.test/.settings/org.eclipse.jdt.core.prefs
@@ -1,9 +1,9 @@
eclipse.preferences.version=1
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=17
-org.eclipse.jdt.core.compiler.compliance=17
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=21
+org.eclipse.jdt.core.compiler.compliance=21
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning
org.eclipse.jdt.core.compiler.release=enabled
-org.eclipse.jdt.core.compiler.source=17
+org.eclipse.jdt.core.compiler.source=21
diff --git a/com.microsoft.copilot.eclipse.ui.test/META-INF/MANIFEST.MF b/com.microsoft.copilot.eclipse.ui.test/META-INF/MANIFEST.MF
index ab85b21d7..cba4993d7 100644
--- a/com.microsoft.copilot.eclipse.ui.test/META-INF/MANIFEST.MF
+++ b/com.microsoft.copilot.eclipse.ui.test/META-INF/MANIFEST.MF
@@ -4,7 +4,7 @@ Bundle-Name: com.microsoft.copilot.eclipse.ui.test
Bundle-SymbolicName: com.microsoft.copilot.eclipse.ui.test;singleton:=true
Bundle-Version: 0.21.0.qualifier
Bundle-Vendor: GitHub Copilot
-Bundle-RequiredExecutionEnvironment: JavaSE-17
+Bundle-RequiredExecutionEnvironment: JavaSE-21
Fragment-Host: com.microsoft.copilot.eclipse.ui
Automatic-Module-Name: com.microsoft.copilot.eclipse.ui.test
Import-Package: org.objenesis;version="[3.4.0,4.0.0)"
diff --git a/com.microsoft.copilot.eclipse.ui.test/build.properties b/com.microsoft.copilot.eclipse.ui.test/build.properties
index 07c97efed..8ffd63634 100644
--- a/com.microsoft.copilot.eclipse.ui.test/build.properties
+++ b/com.microsoft.copilot.eclipse.ui.test/build.properties
@@ -1,5 +1,5 @@
-source.. = src
-output.. = target/classes
+source.. = src/
+output.. = target/classes/
bin.includes = META-INF/,\
.,\
fragment.xml
diff --git a/com.microsoft.copilot.eclipse.ui/.classpath b/com.microsoft.copilot.eclipse.ui/.classpath
index 8d8612144..b1415d56b 100644
--- a/com.microsoft.copilot.eclipse.ui/.classpath
+++ b/com.microsoft.copilot.eclipse.ui/.classpath
@@ -1,7 +1,11 @@
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
diff --git a/com.microsoft.copilot.eclipse.ui/.settings/org.eclipse.core.resources.prefs b/com.microsoft.copilot.eclipse.ui/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 000000000..4824b8026
--- /dev/null
+++ b/com.microsoft.copilot.eclipse.ui/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,2 @@
+eclipse.preferences.version=1
+encoding/=UTF-8
diff --git a/com.microsoft.copilot.eclipse.ui/.settings/org.eclipse.jdt.core.prefs b/com.microsoft.copilot.eclipse.ui/.settings/org.eclipse.jdt.core.prefs
index 21eccc094..a98206bc4 100644
--- a/com.microsoft.copilot.eclipse.ui/.settings/org.eclipse.jdt.core.prefs
+++ b/com.microsoft.copilot.eclipse.ui/.settings/org.eclipse.jdt.core.prefs
@@ -1,12 +1,12 @@
eclipse.preferences.version=1
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=17
-org.eclipse.jdt.core.compiler.compliance=17
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=21
+org.eclipse.jdt.core.compiler.compliance=21
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning
org.eclipse.jdt.core.compiler.release=enabled
-org.eclipse.jdt.core.compiler.source=17
+org.eclipse.jdt.core.compiler.source=21
org.eclipse.jdt.core.formatter.align_arrows_in_switch_on_columns=false
org.eclipse.jdt.core.formatter.align_assignment_statements_on_columns=false
org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines=2147483647
diff --git a/com.microsoft.copilot.eclipse.ui/META-INF/MANIFEST.MF b/com.microsoft.copilot.eclipse.ui/META-INF/MANIFEST.MF
index a7cc5c25d..73b4f6120 100644
--- a/com.microsoft.copilot.eclipse.ui/META-INF/MANIFEST.MF
+++ b/com.microsoft.copilot.eclipse.ui/META-INF/MANIFEST.MF
@@ -21,7 +21,7 @@ Export-Package: com.microsoft.copilot.eclipse.ui,
com.microsoft.copilot.eclipse.ui.extensions,
com.microsoft.copilot.eclipse.ui.nes;x-friends:="com.microsoft.copilot.eclipse.ui.test"
Bundle-Activator: com.microsoft.copilot.eclipse.ui.CopilotUi
-Bundle-RequiredExecutionEnvironment: JavaSE-17
+Bundle-RequiredExecutionEnvironment: JavaSE-21
Automatic-Module-Name: com.microsoft.copilot.eclipse.ui
Bundle-ActivationPolicy: lazy
Import-Package: org.osgi.framework;version="[1.10.0,2.0.0)"
diff --git a/com.microsoft.copilot.eclipse.ui/build.properties b/com.microsoft.copilot.eclipse.ui/build.properties
index 5ba08abef..495210f7a 100644
--- a/com.microsoft.copilot.eclipse.ui/build.properties
+++ b/com.microsoft.copilot.eclipse.ui/build.properties
@@ -1,5 +1,5 @@
-source.. = src
-output.. = target/classes
+source.. = src/
+output.. = target/classes/
bin.includes = META-INF/,\
.,\
plugin.xml,\
@@ -7,5 +7,4 @@ bin.includes = META-INF/,\
plugin.properties,\
css/,\
intro/,\
- terminal-bundles/*.jar,\
contexts.xml
diff --git a/com.microsoft.copilot.eclipse.ui/pom.xml b/com.microsoft.copilot.eclipse.ui/pom.xml
index ebe39c403..5bbe2df3f 100644
--- a/com.microsoft.copilot.eclipse.ui/pom.xml
+++ b/com.microsoft.copilot.eclipse.ui/pom.xml
@@ -23,30 +23,6 @@
${tycho-version}
true
-
- org.apache.maven.plugins
- maven-antrun-plugin
- 3.1.0
-
-
- copy-terminal-jars
- process-resources
-
- run
-
-
-
-
-
-
-
-
-
-
org.eclipse.tycho
tycho-packaging-plugin
diff --git a/com.microsoft.copilot.eclipse.ui/src/com/microsoft/copilot/eclipse/ui/UiConstants.java b/com.microsoft.copilot.eclipse.ui/src/com/microsoft/copilot/eclipse/ui/UiConstants.java
index 6cfbb8371..2d163907b 100644
--- a/com.microsoft.copilot.eclipse.ui/src/com/microsoft/copilot/eclipse/ui/UiConstants.java
+++ b/com.microsoft.copilot.eclipse.ui/src/com/microsoft/copilot/eclipse/ui/UiConstants.java
@@ -36,6 +36,5 @@ private UiConstants() {
public static final String GITHUB_COPILOT_CODING_AGENT_SLUG = "github-copilot-coding-agent";
public static final String GITHUB_COPILOT_CODING_AGENT_LEARN_MORE_URL = "https://aka.ms/learn-copilot-coding-agent";
- public static final String TERMINAL_DEPENDENCY_GUIDE_URL = "https://aka.ms/terminal-dependency-guide";
public static final String COPILOT_RATE_LIMIT_INFO_URL = "https://aka.ms/github-copilot-rate-limit-error";
}
diff --git a/com.microsoft.copilot.eclipse.ui/src/com/microsoft/copilot/eclipse/ui/chat/services/AgentToolService.java b/com.microsoft.copilot.eclipse.ui/src/com/microsoft/copilot/eclipse/ui/chat/services/AgentToolService.java
index c7a013c2a..2ce55d56b 100644
--- a/com.microsoft.copilot.eclipse.ui/src/com/microsoft/copilot/eclipse/ui/chat/services/AgentToolService.java
+++ b/com.microsoft.copilot.eclipse.ui/src/com/microsoft/copilot/eclipse/ui/chat/services/AgentToolService.java
@@ -49,7 +49,6 @@
import com.microsoft.copilot.eclipse.ui.chat.tools.JavaDebuggerToolAdapter;
import com.microsoft.copilot.eclipse.ui.chat.tools.RunInTerminalToolAdapter;
import com.microsoft.copilot.eclipse.ui.chat.tools.RunInTerminalToolAdapter.GetTerminalOutputTool;
-import com.microsoft.copilot.eclipse.ui.dialogs.MissingTerminalDependenciesDialog;
import com.microsoft.copilot.eclipse.ui.utils.SwtUtils;
/**
@@ -95,11 +94,6 @@ public void onServiceAvailable(IRunInTerminalTool service) {
}
}
- @Override
- public void onMissingDependencies(String terminalType, List missingDependencies) {
- MissingTerminalDependenciesDialog.showIfNotSuppressed(terminalType, missingDependencies);
- }
-
/**
* Register default tools.
*/
diff --git a/com.microsoft.copilot.eclipse.ui/src/com/microsoft/copilot/eclipse/ui/dialogs/Messages.java b/com.microsoft.copilot.eclipse.ui/src/com/microsoft/copilot/eclipse/ui/dialogs/Messages.java
index 29fee450d..3c0ed05c1 100644
--- a/com.microsoft.copilot.eclipse.ui/src/com/microsoft/copilot/eclipse/ui/dialogs/Messages.java
+++ b/com.microsoft.copilot.eclipse.ui/src/com/microsoft/copilot/eclipse/ui/dialogs/Messages.java
@@ -21,15 +21,6 @@ public final class Messages extends NLS {
public static String projectSelectionDialog_button_continue;
public static String githubCodingAgent_link_learnMore;
- // Terminal dependency dialog
- public static String terminalDependencyDialog_shellTitle;
- public static String terminalDependencyDialog_title;
- public static String terminalDependencyDialog_message;
- public static String terminalDependencyDialog_missingDependencies;
- public static String terminalDependencyDialog_instruction;
- public static String terminalDependencyDialog_helpLink;
- public static String terminalDependencyDialog_dontShowAgain;
-
static {
// initialize resource bundle
NLS.initializeMessages("com.microsoft.copilot.eclipse.ui.dialogs.messages", Messages.class);
diff --git a/com.microsoft.copilot.eclipse.ui/src/com/microsoft/copilot/eclipse/ui/dialogs/MissingTerminalDependenciesDialog.java b/com.microsoft.copilot.eclipse.ui/src/com/microsoft/copilot/eclipse/ui/dialogs/MissingTerminalDependenciesDialog.java
deleted file mode 100644
index 1e87cdfcc..000000000
--- a/com.microsoft.copilot.eclipse.ui/src/com/microsoft/copilot/eclipse/ui/dialogs/MissingTerminalDependenciesDialog.java
+++ /dev/null
@@ -1,195 +0,0 @@
-// Copyright (c) Microsoft Corporation.
-// Licensed under the MIT license.
-
-package com.microsoft.copilot.eclipse.ui.dialogs;
-
-import java.util.List;
-
-import org.eclipse.core.runtime.preferences.ConfigurationScope;
-import org.eclipse.core.runtime.preferences.IEclipsePreferences;
-import org.eclipse.jface.dialogs.IDialogConstants;
-import org.eclipse.jface.dialogs.TitleAreaDialog;
-import org.eclipse.jface.resource.JFaceResources;
-import org.eclipse.osgi.util.NLS;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.events.SelectionAdapter;
-import org.eclipse.swt.events.SelectionEvent;
-import org.eclipse.swt.graphics.Image;
-import org.eclipse.swt.layout.GridData;
-import org.eclipse.swt.layout.GridLayout;
-import org.eclipse.swt.program.Program;
-import org.eclipse.swt.widgets.Button;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Control;
-import org.eclipse.swt.widgets.Label;
-import org.eclipse.swt.widgets.Link;
-import org.eclipse.swt.widgets.Shell;
-import org.eclipse.ui.PlatformUI;
-import org.osgi.service.prefs.BackingStoreException;
-
-import com.microsoft.copilot.eclipse.core.Constants;
-import com.microsoft.copilot.eclipse.core.CopilotCore;
-import com.microsoft.copilot.eclipse.ui.CopilotImages;
-import com.microsoft.copilot.eclipse.ui.CopilotUi;
-import com.microsoft.copilot.eclipse.ui.UiConstants;
-import com.microsoft.copilot.eclipse.ui.utils.SwtUtils;
-
-/**
- * Dialog to inform users about missing terminal dependencies. Provides information about what needs to be installed and
- * a link to documentation.
- */
-public class MissingTerminalDependenciesDialog extends TitleAreaDialog {
-
- private final String terminalType;
- private final List missingDependencies;
- private Button dontShowAgainCheckbox;
-
- /**
- * Creates the dialog.
- *
- * @param parentShell the parent shell
- * @param terminalType the type of terminal (e.g., "Eclipse Terminal" or "TM Terminal")
- * @param missingDependencies list of missing bundle symbolic names
- */
- public MissingTerminalDependenciesDialog(Shell parentShell, String terminalType, List missingDependencies) {
- super(parentShell);
- this.terminalType = terminalType;
- this.missingDependencies = missingDependencies;
- setShellStyle(getShellStyle() | SWT.RESIZE);
- }
-
- @Override
- protected void configureShell(Shell shell) {
- super.configureShell(shell);
- shell.setText(Messages.terminalDependencyDialog_shellTitle);
- loadIcon(shell);
- }
-
- private void loadIcon(Shell shell) {
- Image icon = CopilotImages.getImage(CopilotImages.IMG_GITHUB_COPILOT);
- if (icon != null) {
- shell.setImage(icon);
- }
- }
-
- @Override
- protected Control createDialogArea(Composite parent) {
- setTitle(Messages.terminalDependencyDialog_title);
- setMessage(NLS.bind(Messages.terminalDependencyDialog_message, terminalType));
-
- Composite area = (Composite) super.createDialogArea(parent);
-
- Composite container = new Composite(area, SWT.NONE);
- container.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
- GridLayout layout = new GridLayout(1, false);
- layout.marginWidth = 15;
- layout.marginHeight = 15;
- layout.verticalSpacing = 10;
- container.setLayout(layout);
-
- // Missing dependencies section
- Label depsLabel = new Label(container, SWT.NONE);
- depsLabel.setText(Messages.terminalDependencyDialog_missingDependencies);
- depsLabel.setFont(JFaceResources.getFontRegistry().getBold(JFaceResources.DEFAULT_FONT));
- for (String dep : missingDependencies) {
- Label depItem = new Label(container, SWT.NONE);
- depItem.setText(" - " + dep);
- depItem.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
- }
-
- Label instructionLabel = new Label(container, SWT.WRAP);
- instructionLabel.setText(NLS.bind(Messages.terminalDependencyDialog_instruction, terminalType));
- GridData instructionData = new GridData(SWT.FILL, SWT.CENTER, true, false);
- instructionData.widthHint = 400;
- instructionData.verticalIndent = 10;
- instructionLabel.setLayoutData(instructionData);
-
- // Help link
- Link link = new Link(container, SWT.NONE);
- link.setText(NLS.bind(Messages.terminalDependencyDialog_helpLink, UiConstants.TERMINAL_DEPENDENCY_GUIDE_URL));
- link.addSelectionListener(new SelectionAdapter() {
- @Override
- public void widgetSelected(SelectionEvent e) {
- Program.launch(e.text);
- }
- });
- GridData linkData = new GridData(SWT.FILL, SWT.CENTER, true, false);
- linkData.verticalIndent = 5;
- link.setLayoutData(linkData);
-
- // Don't show again checkbox
- dontShowAgainCheckbox = new Button(container, SWT.CHECK);
- dontShowAgainCheckbox.setText(Messages.terminalDependencyDialog_dontShowAgain);
- GridData checkboxData = new GridData(SWT.FILL, SWT.CENTER, true, false);
- checkboxData.verticalIndent = 15;
- dontShowAgainCheckbox.setLayoutData(checkboxData);
-
- return area;
- }
-
- @Override
- protected void createButtonsForButtonBar(Composite parent) {
- createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true);
- }
-
- @Override
- protected void okPressed() {
- if (dontShowAgainCheckbox != null && dontShowAgainCheckbox.getSelection()) {
- setSuppressDialog(true);
- }
- super.okPressed();
- }
-
- /**
- * Check if the dialog has been suppressed by user preference.
- *
- * @return true if the dialog should not be shown
- */
- public static boolean isDialogSuppressed() {
- IEclipsePreferences prefs = ConfigurationScope.INSTANCE
- .getNode(CopilotUi.getPlugin().getBundle().getSymbolicName());
- return prefs.getBoolean(Constants.SUPPRESS_TERMINAL_DEPENDENCY_DIALOG, false);
- }
-
- /**
- * Set whether to suppress the dialog.
- *
- * @param suppress true to suppress future dialogs
- */
- private static void setSuppressDialog(boolean suppress) {
- try {
- IEclipsePreferences prefs = ConfigurationScope.INSTANCE
- .getNode(CopilotUi.getPlugin().getBundle().getSymbolicName());
- prefs.putBoolean(Constants.SUPPRESS_TERMINAL_DEPENDENCY_DIALOG, suppress);
- prefs.flush();
- } catch (BackingStoreException e) {
- CopilotCore.LOGGER.error("Failed to persist terminal dialog preference", e);
- }
- }
-
- /**
- * Shows the dialog if not suppressed by user preference.
- *
- * @param terminalType the type of terminal required
- * @param missingDependencies list of missing dependencies
- */
- public static void showIfNotSuppressed(String terminalType, List missingDependencies) {
- if (isDialogSuppressed()) {
- return;
- }
-
- SwtUtils.invokeOnDisplayThreadAsync(() -> {
- if (!PlatformUI.isWorkbenchRunning()) {
- return;
- }
- var window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
- if (window == null) {
- return;
- }
- Shell shell = window.getShell();
- MissingTerminalDependenciesDialog dialog = new MissingTerminalDependenciesDialog(shell, terminalType,
- missingDependencies);
- dialog.open();
- });
- }
-}
diff --git a/com.microsoft.copilot.eclipse.ui/src/com/microsoft/copilot/eclipse/ui/dialogs/messages.properties b/com.microsoft.copilot.eclipse.ui/src/com/microsoft/copilot/eclipse/ui/dialogs/messages.properties
index 69e7eadd1..62dd88314 100644
--- a/com.microsoft.copilot.eclipse.ui/src/com/microsoft/copilot/eclipse/ui/dialogs/messages.properties
+++ b/com.microsoft.copilot.eclipse.ui/src/com/microsoft/copilot/eclipse/ui/dialogs/messages.properties
@@ -9,12 +9,3 @@ projectSelectionDialog_label_selectProject=Select Project:
projectSelectionDialog_button_cancel=Cancel
projectSelectionDialog_button_continue=Continue
githubCodingAgent_link_learnMore=Learn about coding agent
-
-# Terminal dependency dialog
-terminalDependencyDialog_shellTitle=GitHub Copilot
-terminalDependencyDialog_title=Terminal Support Unavailable
-terminalDependencyDialog_message=GitHub Copilot's terminal functionality requires the {0}, which is not installed in your Eclipse.
-terminalDependencyDialog_missingDependencies=Missing dependencies:
-terminalDependencyDialog_instruction=To enable terminal support, please install the {0} from your Eclipse update site.
-terminalDependencyDialog_helpLink=Learn how to install terminal support
-terminalDependencyDialog_dontShowAgain=Don''t show this message again
diff --git a/com.microsoft.copilot.eclipse.ui/src/com/microsoft/copilot/eclipse/ui/perspectives/CopilotPerspectiveFactory.java b/com.microsoft.copilot.eclipse.ui/src/com/microsoft/copilot/eclipse/ui/perspectives/CopilotPerspectiveFactory.java
index 2015a0630..7ca15104a 100644
--- a/com.microsoft.copilot.eclipse.ui/src/com/microsoft/copilot/eclipse/ui/perspectives/CopilotPerspectiveFactory.java
+++ b/com.microsoft.copilot.eclipse.ui/src/com/microsoft/copilot/eclipse/ui/perspectives/CopilotPerspectiveFactory.java
@@ -40,7 +40,7 @@ public void createInitialLayout(IPageLayout layout) {
IFolderLayout consoleLayout = layout.createFolder("bottom", IPageLayout.BOTTOM, 0.8f, editorArea);
consoleLayout.addView(IPageLayout.ID_PROBLEM_VIEW);
consoleLayout.addView(IConsoleConstants.ID_CONSOLE_VIEW);
- consoleLayout.addView("org.eclipse.tm.terminal.view.ui.TerminalsView");
+ consoleLayout.addView("org.eclipse.terminal.view.ui.TerminalsView");
consoleLayout.addPlaceholder(IPageLayout.ID_BOOKMARKS);
consoleLayout.addPlaceholder(IProgressConstants.PROGRESS_VIEW_ID);
@@ -55,7 +55,7 @@ public void createInitialLayout(IPageLayout layout) {
layout.addShowViewShortcut(IProgressConstants.PROGRESS_VIEW_ID);
layout.addShowViewShortcut(IPageLayout.ID_PROJECT_EXPLORER);
layout.addShowViewShortcut(TemplatesView.ID);
- layout.addShowViewShortcut("org.eclipse.tm.terminal.view.ui.TerminalsView");
+ layout.addShowViewShortcut("org.eclipse.terminal.view.ui.TerminalsView");
layout.addShowViewShortcut("org.eclipse.pde.runtime.LogView");
layout.addShowViewShortcut("org.eclipse.search.ui.views.SearchView");
layout.addShowViewShortcut(Constants.GITHUB_JOBS_VIEW_ID);
diff --git a/com.microsoft.copilot.eclipse.ui/terminal-bundles/.gitkeep b/com.microsoft.copilot.eclipse.ui/terminal-bundles/.gitkeep
deleted file mode 100644
index e69de29bb..000000000
diff --git a/launch/Verify Copilot for Eclipse.launch b/launch/Verify Copilot for Eclipse.launch
new file mode 100644
index 000000000..e2537bd26
--- /dev/null
+++ b/launch/Verify Copilot for Eclipse.launch
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/launch/plugin_debug_configuration.launch b/launch/plugin_debug_configuration.launch
index 8c8419e65..eedd1787c 100644
--- a/launch/plugin_debug_configuration.launch
+++ b/launch/plugin_debug_configuration.launch
@@ -19,7 +19,7 @@
-
+
diff --git a/pom.xml b/pom.xml
index ba917990f..d66246443 100644
--- a/pom.xml
+++ b/pom.xml
@@ -21,10 +21,9 @@
-
+
com.microsoft.copilot.eclipse.terminal.api
com.microsoft.copilot.eclipse.ui.terminal
- com.microsoft.copilot.eclipse.ui.terminal.tm
com.microsoft.copilot.eclipse.core
com.microsoft.copilot.eclipse.ui
@@ -96,7 +95,7 @@
${tycho-version}
- ../base.target
+ ../target-platforms/2025-12.target
JavaSE-21
diff --git a/target-platforms/2025-12.target b/target-platforms/2025-12.target
new file mode 100644
index 000000000..d5ba85bde
--- /dev/null
+++ b/target-platforms/2025-12.target
@@ -0,0 +1,77 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/target-terminal.target b/target-terminal.target
deleted file mode 100644
index ad2e7c962..000000000
--- a/target-terminal.target
+++ /dev/null
@@ -1,14 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/target-tm-terminal.target b/target-tm-terminal.target
deleted file mode 100644
index ff989f093..000000000
--- a/target-tm-terminal.target
+++ /dev/null
@@ -1,14 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file