Explain spel expressions and queries with copilot
This commit is contained in:
@@ -21,6 +21,7 @@ import {registerJavaDataService} from "@pivotal-tools/commons-vscode/lib/java-da
|
||||
import * as setLogLevelUi from './set-log-levels-ui';
|
||||
import { startTestJarSupport } from "./test-jar-launch";
|
||||
import { startPropertiesConversionSupport } from "./convert-props-yaml";
|
||||
import { activateCopilotFeatures } from "./copilot";
|
||||
|
||||
const PROPERTIES_LANGUAGE_ID = "spring-boot-properties";
|
||||
const YAML_LANGUAGE_ID = "spring-boot-properties-yaml";
|
||||
@@ -147,6 +148,8 @@ export function activate(context: ExtensionContext): Thenable<ExtensionAPI> {
|
||||
registerClasspathService(client);
|
||||
registerJavaDataService(client);
|
||||
|
||||
activateCopilotFeatures(context);
|
||||
|
||||
// Force classpath listener to be enabled. Boot LS can only be launched iff classpath is available and there Spring-Boot on the classpath somewhere.
|
||||
commands.executeCommand('sts.vscode-spring-boot.enableClasspathListening', true);
|
||||
|
||||
|
||||
111
vscode-extensions/vscode-spring-boot/lib/copilot/index.ts
Normal file
111
vscode-extensions/vscode-spring-boot/lib/copilot/index.ts
Normal file
@@ -0,0 +1,111 @@
|
||||
import { commands, ExtensionContext, extensions, lm, LanguageModelChatSelector, window, workspace, LogOutputChannel, version } from "vscode";
|
||||
import { SemVer } from "semver";
|
||||
|
||||
export const REQUIRED_EXTENSION = 'github.copilot-chat';
|
||||
const DEFAULT_MODEL_SELECTOR: LanguageModelChatSelector = { vendor: 'copilot', family: 'gpt-4' };
|
||||
export const logger: LogOutputChannel = window.createOutputChannel("Spring tools copilot", { log: true });
|
||||
|
||||
export async function activateCopilotFeatures(context: ExtensionContext): Promise<void> {
|
||||
if(!isLlmApiAvailable("1.90.0-insider")) { // lm API is available since 1.90.0-insider
|
||||
return;
|
||||
}
|
||||
|
||||
workspace.onDidChangeConfiguration(event => {
|
||||
if (event.affectsConfiguration('boot-java.highlight-copilot-codelens.on')) {
|
||||
promptReloadWindow();
|
||||
}
|
||||
});
|
||||
|
||||
logger.info("vscode.lm is ready.");
|
||||
await ensureExtensionInstalledAndActivated();
|
||||
await updateConfigurationBasedOnCopilotAccess();
|
||||
|
||||
// Add listener to handle installation/uninstallation of the required extension
|
||||
extensions.onDidChange(async () => {
|
||||
await ensureExtensionInstalledAndActivated();
|
||||
await updateConfigurationBasedOnCopilotAccess();
|
||||
});
|
||||
|
||||
explainQueryWithCopilot();
|
||||
|
||||
}
|
||||
|
||||
function isLlmApiAvailable(v: string): boolean {
|
||||
return new SemVer(version).compare(new SemVer(v)) >= 0;
|
||||
}
|
||||
|
||||
async function ensureExtensionInstalledAndActivated() {
|
||||
if (!isExtensionInstalled(REQUIRED_EXTENSION)) {
|
||||
logger.error(`Required extension ${REQUIRED_EXTENSION} is not installed.`);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isExtensionActivated(REQUIRED_EXTENSION)) {
|
||||
logger.error(`Required extension ${REQUIRED_EXTENSION} is not activated.`);
|
||||
await waitUntilExtensionActivated(REQUIRED_EXTENSION);
|
||||
}
|
||||
}
|
||||
|
||||
function isExtensionInstalled(extensionId: string): boolean {
|
||||
return !!extensions.getExtension(extensionId);
|
||||
}
|
||||
|
||||
function isExtensionActivated(extensionId: string): boolean {
|
||||
return !!extensions.getExtension(extensionId)?.isActive;
|
||||
}
|
||||
|
||||
async function waitUntilExtensionActivated(extensionId: string, interval: number = 3500) {
|
||||
logger.info(`Waiting for extension ${extensionId} to be activated...`);
|
||||
return new Promise<void>((resolve) => {
|
||||
const id = setInterval(() => {
|
||||
if (extensions.getExtension(extensionId)?.isActive) {
|
||||
clearInterval(id);
|
||||
resolve();
|
||||
}
|
||||
}, interval);
|
||||
});
|
||||
}
|
||||
|
||||
async function updateConfigurationBasedOnCopilotAccess() {
|
||||
|
||||
if (!isExtensionInstalled(REQUIRED_EXTENSION) || !isExtensionActivated(REQUIRED_EXTENSION)) {
|
||||
await updateConfiguration(false);
|
||||
return;
|
||||
}
|
||||
|
||||
const model = (await lm.selectChatModels(DEFAULT_MODEL_SELECTOR))?.[0];
|
||||
if (!model) {
|
||||
const models = await lm.selectChatModels();
|
||||
logger.error(`No suitable model, available models: [${models.map(m => m.name).join(', ')}]. Please make sure you have installed the latest "GitHub Copilot Chat" (v0.16.0 or later) and all \`lm\` API is enabled.`);
|
||||
await updateConfiguration(false);
|
||||
} else {
|
||||
await updateConfiguration(true);
|
||||
}
|
||||
}
|
||||
|
||||
async function updateConfiguration(value: boolean) {
|
||||
const configValue = workspace.getConfiguration().get('boot-java.highlight-copilot-codelens.on');
|
||||
if(value && configValue === true) {
|
||||
commands.executeCommand('sts/enable/copilot/features', value);
|
||||
}
|
||||
}
|
||||
|
||||
async function explainQueryWithCopilot() {
|
||||
commands.registerCommand('vscode-spring-boot.query.explain', async (userPrompt) => {
|
||||
console.log('spel.explain: ' + userPrompt);
|
||||
console.log('messages: ' + userPrompt);
|
||||
|
||||
await commands.executeCommand('workbench.action.chat.open', { query: userPrompt });
|
||||
})
|
||||
}
|
||||
|
||||
async function promptReloadWindow() {
|
||||
const reload = await window.showInformationMessage(
|
||||
'Configuration updated. Please reload VS Code to apply changes.',
|
||||
'Reload'
|
||||
);
|
||||
|
||||
if (reload === 'Reload') {
|
||||
await commands.executeCommand('workbench.action.reloadWindow');
|
||||
}
|
||||
}
|
||||
19261
vscode-extensions/vscode-spring-boot/lib/vscode.d.ts
vendored
Normal file
19261
vscode-extensions/vscode-spring-boot/lib/vscode.d.ts
vendored
Normal file
File diff suppressed because it is too large
Load Diff
@@ -16,7 +16,9 @@
|
||||
},
|
||||
"categories": [
|
||||
"Programming Languages",
|
||||
"Linters"
|
||||
"Linters",
|
||||
"AI",
|
||||
"Chat"
|
||||
],
|
||||
"keywords": [
|
||||
"java-properties",
|
||||
@@ -241,6 +243,11 @@
|
||||
"enablement": "vscode-spring-boot.active-app-state == 'connected'",
|
||||
"icon": "$(refresh)",
|
||||
"category": "Spring Boot"
|
||||
},
|
||||
{
|
||||
"command": "vscode-spring-boot.query.explain",
|
||||
"title": "Explain Spel Expressions and Queries",
|
||||
"category": "Spring Boot"
|
||||
}
|
||||
],
|
||||
"configuration": [
|
||||
@@ -379,6 +386,11 @@
|
||||
],
|
||||
"scope": "window",
|
||||
"description": "Defines which browser to use when opening Spring Boot apps web pages."
|
||||
},
|
||||
"boot-java.highlight-copilot-codelens.on": {
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"description": "Explain SpEL Expressions and queries using Copilot"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -1252,7 +1264,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^18.8.0",
|
||||
"@types/vscode": "1.75.0",
|
||||
"@types/semver": "^7.5.8",
|
||||
"@vscode/vsce": "^2.22.0",
|
||||
"typescript": "^4.8.0"
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user