diff --git a/apps/vscode/package.json b/apps/vscode/package.json index 6fca84bc22..e5cc8a27f5 100644 --- a/apps/vscode/package.json +++ b/apps/vscode/package.json @@ -789,6 +789,12 @@ ], "default": "all", "description": "Controls which notifications are shown for Nx Cloud." + }, + "nxConsole.enableNxCopilotFeatures": { + "type": "boolean", + "default": false, + "scope": "machine", + "description": "Enable Nx-specific copilot features (Experimental)." } } }, diff --git a/libs/vscode/configuration/src/lib/configuration-keys.ts b/libs/vscode/configuration/src/lib/configuration-keys.ts index f15231c493..1e7aefcee0 100644 --- a/libs/vscode/configuration/src/lib/configuration-keys.ts +++ b/libs/vscode/configuration/src/lib/configuration-keys.ts @@ -14,6 +14,7 @@ export const GLOBAL_CONFIG_KEYS = [ 'showNodeVersionOnStartup', 'nxWorkspacePath', 'nxCloudNotifications', + 'enableNxCopilotFeatures', ] as const; export type GlobalConfig = { @@ -32,6 +33,7 @@ export type GlobalConfig = { showNodeVersionOnStartup: boolean; nxWorkspacePath: string; nxCloudNotifications: 'all' | 'errors' | 'none'; + enableNxCopilotFeatures: boolean; }; /** diff --git a/libs/vscode/copilot/src/lib/init-copilot.ts b/libs/vscode/copilot/src/lib/init-copilot.ts index c39e65fe45..0cda43ca1a 100644 --- a/libs/vscode/copilot/src/lib/init-copilot.ts +++ b/libs/vscode/copilot/src/lib/init-copilot.ts @@ -8,9 +8,15 @@ import { LanguageModelChatMessage, Uri, chat, + commands, + Command, } from 'vscode'; import { getNxWorkspace } from '@nx-console/vscode-nx-workspace'; -import { BASE_PROMPT } from './prompt.js'; +import { BASE_PROMPT, GENERATE_PROMPT } from './prompt.js'; +import type { TargetConfiguration } from 'nx/src/devkit-exports.js'; +import { GlobalConfigurationStore } from '@nx-console/vscode-configuration'; + +const OPEN_COPILOT_SETTING_COMMAND = 'nxConsole.openCopilotSettings'; export function initCopilot(context: ExtensionContext) { const nxParticipant = chat.createChatParticipant('nx-console.nx', handler); @@ -27,12 +33,33 @@ const handler: ChatRequestHandler = async ( stream: ChatResponseStream, token: CancellationToken ) => { + const enableNxCopilotFeaturesSetting = GlobalConfigurationStore.instance.get( + 'enableNxCopilotFeatures', + false + ); + + if (!enableNxCopilotFeaturesSetting) { + stream.markdown( + 'The @nx copilot chat participant is experimental. To use it, please enable it in the settings.' + ); + + stream.button({ + title: 'Enable Nx Copilot', + command: 'workbench.action.openSettings', + arguments: ['nxConsole.enableNxCopilotFeatures'], + }); + return; + } const prompt = BASE_PROMPT; stream.progress('Retrieving workspace information...'); const projectGraph = await getPrunedProjectGraph(); + // if (request.command === 'generate') { + // prompt = GENERATE_PROMPT; + // } + const messages = [LanguageModelChatMessage.User(prompt)]; messages.push(LanguageModelChatMessage.User(request.prompt)); @@ -59,6 +86,31 @@ async function getPrunedProjectGraph() { if (node.data.metadata?.technologies) { prunedNode.technologies = node.data.metadata.technologies; } + if (node.data.targets) { + prunedNode.targets = Object.entries(node.data.targets) + .map(([key, target]) => { + const prunedTarget = { + executor: target.executor, + } as Partial; + if (target.command) { + prunedTarget.command = target.command; + } + if (target.options.commands) { + prunedTarget.command = target.options.commands; + } + if (target.configurations) { + prunedTarget.configurations = Object.keys( + target.configurations + ); + } + return [key, prunedTarget] as const; + }) + .reduce((acc, [key, target]) => { + acc[key] = target; + return acc; + }, {}); + } + return [name, prunedNode] as const; }) .reduce((acc, [name, node]) => { diff --git a/libs/vscode/copilot/src/lib/prompt.ts b/libs/vscode/copilot/src/lib/prompt.ts index 91c19d46ac..804f25f75f 100644 --- a/libs/vscode/copilot/src/lib/prompt.ts +++ b/libs/vscode/copilot/src/lib/prompt.ts @@ -9,3 +9,9 @@ Remember to: - Use code examples when applicable - Be concise and clear `; + +export const GENERATE_PROMPT = ` +You are an AI assistant specialized in Nx workspaces and monorepo development. +You have access to the project graph and schemas for running nx generators. +Use the user prompt to create a generator invocation and return a cli command to run the generator. +`; diff --git a/libs/vscode/copilot/tsconfig.json b/libs/vscode/copilot/tsconfig.json index 78eb950bdd..ed5f294064 100644 --- a/libs/vscode/copilot/tsconfig.json +++ b/libs/vscode/copilot/tsconfig.json @@ -3,6 +3,9 @@ "files": [], "include": [], "references": [ + { + "path": "../configuration" + }, { "path": "../nx-workspace" }, diff --git a/libs/vscode/copilot/tsconfig.lib.json b/libs/vscode/copilot/tsconfig.lib.json index 38d96ef841..54de6a0338 100644 --- a/libs/vscode/copilot/tsconfig.lib.json +++ b/libs/vscode/copilot/tsconfig.lib.json @@ -7,6 +7,9 @@ "include": ["src/**/*.ts"], "exclude": ["jest.config.ts", "src/**/*.spec.ts", "src/**/*.test.ts"], "references": [ + { + "path": "../configuration/tsconfig.lib.json" + }, { "path": "../nx-workspace/tsconfig.lib.json" }