diff --git a/.azure-pipelines/nightly.yml b/.azure-pipelines/nightly.yml index ae3cc0f45..6ae1e9a1a 100644 --- a/.azure-pipelines/nightly.yml +++ b/.azure-pipelines/nightly.yml @@ -54,9 +54,9 @@ extends: version: '8.0.x' - task: JavaToolInstaller@0 - displayName: Use Java 17 + displayName: Use Java 21 inputs: - versionSpec: "17" + versionSpec: "21" jdkArchitectureOption: x64 jdkSourceOption: PreInstalled 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 d9990ac3f..a0394415d 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@b843ebf9b913146b38da2eaa7aeddf76074ae1ad # v6.1.0 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 4ce1d6d5e..9ba68598d 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"; public static final String SUPPRESS_COMPATIBILITY_NOTICE_0_23 = "suppressCompatibilityNotice0.23"; // Auto-Approve settings 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/.settings/org.eclipse.jdt.core.prefs b/com.microsoft.copilot.eclipse.ui.jobs.test/.settings/org.eclipse.jdt.core.prefs index 62ef3488c..23fa13b17 100644 --- a/com.microsoft.copilot.eclipse.ui.jobs.test/.settings/org.eclipse.jdt.core.prefs +++ b/com.microsoft.copilot.eclipse.ui.jobs.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.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.test/pom.xml b/com.microsoft.copilot.eclipse.ui.test/pom.xml index d62961866..50d7361be 100644 --- a/com.microsoft.copilot.eclipse.ui.test/pom.xml +++ b/com.microsoft.copilot.eclipse.ui.test/pom.xml @@ -40,6 +40,25 @@ + + org.eclipse.tycho + target-platform-configuration + ${tycho-version} + + + + + + eclipse-plugin + com.microsoft.copilot.eclipse.ui.terminal + 0.0.0 + + + + + org.eclipse.tycho tycho-surefire-plugin diff --git a/com.microsoft.copilot.eclipse.ui.test/src/com/microsoft/copilot/eclipse/terminal/api/TerminalServiceManagerTest.java b/com.microsoft.copilot.eclipse.ui.test/src/com/microsoft/copilot/eclipse/terminal/api/TerminalServiceManagerTest.java new file mode 100644 index 000000000..6f5d6a06e --- /dev/null +++ b/com.microsoft.copilot.eclipse.ui.test/src/com/microsoft/copilot/eclipse/terminal/api/TerminalServiceManagerTest.java @@ -0,0 +1,72 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +package com.microsoft.copilot.eclipse.terminal.api; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.TimeUnit; + +import org.eclipse.core.runtime.Platform; +import org.junit.jupiter.api.Test; +import org.osgi.framework.Bundle; +import org.osgi.framework.Constants; +import org.osgi.framework.FrameworkUtil; + +/** + * Verifies that the terminal implementation bundle is started by the framework and registers its + * {@link IRunInTerminalTool} service without anyone calling {@link Bundle#start()} explicitly, the way it is + * installed by p2 as an ordinary plug-in of the feature. + */ +class TerminalServiceManagerTest { + + private static final String TERMINAL_BUNDLE_ID = "com.microsoft.copilot.eclipse.ui.terminal"; + private static final long SERVICE_TIMEOUT_SECONDS = 30; + + @Test + void testTerminalBundle_declaresLazyActivationPolicy_soEquinoxAutoStartsIt() { + Bundle terminalBundle = getInstalledTerminalBundle(); + + // Equinox marks lazy bundles as auto-started on install (osgi.compatibility.eagerStart.LazyActivation) + assertEquals(Constants.ACTIVATION_LAZY, terminalBundle.getHeaders("").get(Constants.BUNDLE_ACTIVATIONPOLICY), + "Without a lazy activation policy the terminal bundle stays RESOLVED and its DS component is never activated"); + } + + @Test + void testTerminalBundle_installedWithoutExplicitStart_isStarted() { + Bundle terminalBundle = getInstalledTerminalBundle(); + + int state = terminalBundle.getState(); + assertTrue(state == Bundle.STARTING || state == Bundle.ACTIVE, + "Terminal bundle should have been started by the framework, but its state is " + state); + } + + @Test + void testGetCurrentService_terminalBundleInstalled_providesRunInTerminalTool() throws Exception { + Bundle terminalBundle = getInstalledTerminalBundle(); + TerminalServiceManager manager = TerminalServiceManager.getInstance(); + assertNotNull(manager); + + CompletableFuture serviceFuture = new CompletableFuture<>(); + TerminalServiceManager.TerminalServiceListener listener = serviceFuture::complete; + manager.addListener(listener); + try { + IRunInTerminalTool service = manager.getCurrentService() != null ? manager.getCurrentService() + : serviceFuture.get(SERVICE_TIMEOUT_SECONDS, TimeUnit.SECONDS); + + assertNotNull(service); + assertEquals(terminalBundle, FrameworkUtil.getBundle(service.getClass())); + } finally { + manager.removeListener(listener); + } + } + + private static Bundle getInstalledTerminalBundle() { + Bundle terminalBundle = Platform.getBundle(TERMINAL_BUNDLE_ID); + assertNotNull(terminalBundle, TERMINAL_BUNDLE_ID + " is not installed in the test runtime"); + return terminalBundle; + } +} diff --git a/com.microsoft.copilot.eclipse.ui.test/src/com/microsoft/copilot/eclipse/ui/CompatibilityNoticeTest.java b/com.microsoft.copilot.eclipse.ui.test/src/com/microsoft/copilot/eclipse/ui/CompatibilityNoticeTest.java index c2e3cf402..e309d1341 100644 --- a/com.microsoft.copilot.eclipse.ui.test/src/com/microsoft/copilot/eclipse/ui/CompatibilityNoticeTest.java +++ b/com.microsoft.copilot.eclipse.ui.test/src/com/microsoft/copilot/eclipse/ui/CompatibilityNoticeTest.java @@ -95,7 +95,6 @@ void testShouldShow_nextStartupWithoutDismissal_returnsTrue() { @Test void testShouldShow_otherNoticesDisabled_returnsTrue() { preferences.putBoolean(Constants.AUTO_SHOW_WHAT_IS_NEW, false); - preferences.putBoolean(Constants.SUPPRESS_TERMINAL_DEPENDENCY_DIALOG, true); CompatibilityNotice notice = new CompatibilityNotice(preferences); assertTrue(notice.shouldShow(new Version(4, 37, 0), 21)); diff --git a/com.microsoft.copilot.eclipse.ui.test/src/com/microsoft/copilot/eclipse/ui/chat/tools/RunInTerminalToolAdapterTest.java b/com.microsoft.copilot.eclipse.ui.test/src/com/microsoft/copilot/eclipse/ui/chat/tools/RunInTerminalToolAdapterTest.java index 5f6aa92c6..8bf51276d 100644 --- a/com.microsoft.copilot.eclipse.ui.test/src/com/microsoft/copilot/eclipse/ui/chat/tools/RunInTerminalToolAdapterTest.java +++ b/com.microsoft.copilot.eclipse.ui.test/src/com/microsoft/copilot/eclipse/ui/chat/tools/RunInTerminalToolAdapterTest.java @@ -72,19 +72,16 @@ void testInvokeWithEmptyCommandReturnsErrorStatus() throws InterruptedException, LanguageModelToolResult[] results = future.get(); // Assert - // In test environment with no terminal service, the "no terminal" error is returned - // before command validation. This is the actual behavior of the implementation. assertNotNull(results); assertEquals(1, results.length); assertEquals(ToolInvocationStatus.error, results[0].getStatus()); - assertEquals("No terminal implementation available. Terminal service not yet loaded or failed to load.", + assertEquals("The tool cannot be invoked due to the command is null or empty.", results[0].getContent().get(0).getValue()); } @Test - void testInvokeWithNoTerminalServiceReturnsErrorStatus() throws InterruptedException, ExecutionException { - // Arrange - Since we can't mock the singleton, this test verifies error handling - // when no terminal service is available (which is the typical case in unit tests) + void testInvokeWithCommandReturnsWellFormedResult() throws InterruptedException, ExecutionException { + // Arrange Map input = new HashMap<>(); input.put("command", "echo test"); input.put("isBackground", false); @@ -93,11 +90,9 @@ void testInvokeWithNoTerminalServiceReturnsErrorStatus() throws InterruptedExcep CompletableFuture future = runInTerminalToolAdapter.invoke(input, null); LanguageModelToolResult[] results = future.get(); - // Assert - When no terminal service is available, we expect an error + // Assert - the outcome depends on the host's terminal, so only the result's shape is verified assertNotNull(results); assertEquals(1, results.length); - // The result will be either error (no terminal service) or success (if service is available) - // We just verify the result is properly formed assertNotNull(results[0].getStatus()); assertNotNull(results[0].getContent()); } @@ -115,7 +110,7 @@ void testToolName() { } @Test - void testGetTerminalOutputToolWithNoTerminalServiceReturnsErrorStatus() + void testGetTerminalOutputToolWithUnknownIdReturnsErrorStatus() throws InterruptedException, ExecutionException { // Arrange RunInTerminalToolAdapter.GetTerminalOutputTool getTool = new RunInTerminalToolAdapter.GetTerminalOutputTool(); @@ -126,13 +121,11 @@ void testGetTerminalOutputToolWithNoTerminalServiceReturnsErrorStatus() CompletableFuture future = getTool.invoke(input, null); LanguageModelToolResult[] results = future.get(); - // Assert - When no terminal service is available, we expect an error + // Assert assertNotNull(results); assertEquals(1, results.length); - // The result will be either error (no terminal service or invalid ID) - // We just verify the result is properly formed - assertNotNull(results[0].getStatus()); - assertNotNull(results[0].getContent()); + assertEquals(ToolInvocationStatus.error, results[0].getStatus()); + assertEquals("Invalid terminal ID terminal-123", results[0].getContent().get(0).getValue()); } @Test 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 207830e05..58d95671d 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;x-friends:="com.microsoft.copil 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 49eecad03..5c8e00cf9 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 @@ -47,7 +47,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; /** @@ -93,11 +92,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 769f94ad0..f6db1b2e6 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; - public static String compatibilityNotice_title; public static String compatibilityNotice_message; public static String compatibilityNotice_dontRemindAgain; 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 8d7d1f33d..d55ac3d57 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 @@ -10,15 +10,6 @@ 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 - compatibilityNotice_title=GitHub Copilot Compatibility Update compatibilityNotice_message=Starting with GitHub Copilot for Eclipse 0.23.0, you will need Eclipse IDE 2025-12 (4.38) or later and Java 21 or later to run Eclipse.\n\nYour projects can keep their existing Java versions. This version of Copilot still supports your current environment.\n\nPlease upgrade Eclipse and its Java runtime before updating to 0.23.0. If you cannot upgrade, continue using the last compatible 0.22.x release ZIP from GitHub Releases. compatibilityNotice_dontRemindAgain=Don't remind me 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