Loading desktop.package.json +21 −0 Original line number Diff line number Diff line Loading @@ -361,6 +361,11 @@ "command": "gl.mcp.openUserConfig", "title": "Open User Settings (JSON)", "category": "GitLab MCP" }, { "command": "gl.knowledgeGraph.show", "title": "Show GitLab Knowledge Graph", "category": "GitLab" } ], "menus": { Loading Loading @@ -636,6 +641,10 @@ { "command": "gl.webview.newChatConversation", "when": "config.gitlab.duoChat.enabled && gitlab:chatAvailable && gitlab:chatAvailableForProject && (gitlab.featureFlags.languageServerWebviews && !gitlab:isRemoteEnvironment)" }, { "command": "gl.knowledgeGraph.show", "when": "gitlab:knowledgeGraphReady" } ], "view/title": [ Loading Loading @@ -1306,6 +1315,18 @@ "description": "Custom views in the GitLab panel" } } }, { "id": "distributed-binaries", "order": 4, "title": "GitLab Distributed Binaries", "properties": { "gitlab.distributedBinaries.skipIntegrityChecks": { "type": "boolean", "default": false, "description": "Skip integrity checks" } } } ], "walkthroughs": [ Loading src/common/constants.ts +1 −1 Original line number Diff line number Diff line Loading @@ -15,7 +15,7 @@ export const REQUEST_TIMEOUT_MILLISECONDS = 25000; export const DUO_WORKFLOW_PANEL_WEBVIEW_ID = 'duo-workflow-panel'; export const DUO_CHAT_WEBVIEW_ID = 'duo-chat-v2'; export const AGENTIC_CHAT_WEBVIEW_ID = 'agentic-duo-chat'; export const KNOWLEDGE_GRAPH_WEBVIEW_ID = 'knowledge-graph'; export const SECURITY_VULNS_WEBVIEW_ID = 'security-vuln-details'; export const AGENTIC_TABS_WEBVIEW_ID = 'agentic-tabs'; Loading src/common/language_server/language_client_wrapper.test.ts +24 −0 Original line number Diff line number Diff line Loading @@ -111,6 +111,7 @@ describe('LanguageClientWrapper', () => { registerProposedFeatures: jest.fn(), onNotification: jest.fn(), sendNotification: jest.fn(), sendRequest: jest.fn(), onRequest: jest.fn(), }); lsGitProvider = createFakePartial<LSGitProvider>({ Loading @@ -123,6 +124,7 @@ describe('LanguageClientWrapper', () => { webviewMessageRegistry = createFakePartial<WebviewMessageRegistry>({ initNotifier: jest.fn(), initRequester: jest.fn(), }); languageServerFeatureStateProvider = createFakePartial<LanguageServerFeatureStateProvider>({ Loading Loading @@ -197,6 +199,9 @@ describe('LanguageClientWrapper', () => { duoChat: { enabled: true, }, knowledgeGraph: { skipBinaryIntegrityChecks: false, }, }, }, ); Loading Loading @@ -467,6 +472,24 @@ describe('LanguageClientWrapper', () => { testMessage, ); }); it('initializes the webview message registry requester', async () => { wrapper = createWrapper(); await wrapper.initAndStart(); expect(webviewMessageRegistry.initRequester).toHaveBeenCalledWith(expect.any(Function)); const requesterFunction = jest.mocked(webviewMessageRegistry.initRequester).mock .calls[0][0]; const testMessage = { type: 'test', payload: 'data' }; await requesterFunction(testMessage); expect(client.sendRequest).toHaveBeenCalledWith( DEFAULT_WEBVIEW_REQUEST_METHOD, testMessage, ); }); }); describe('Feature State Manager notification', () => { Loading Loading @@ -632,6 +655,7 @@ describe('LanguageClientWrapper', () => { ${{ cert: 'test-cert' }} | ${{ httpAgentOptions: { cert: 'test-cert' } }} ${{ certKey: 'test-certKey' }} | ${{ httpAgentOptions: { certKey: 'test-certKey' } }} ${{ 'duo.workflow.graph': 'foo_bar' }} | ${{ duo: { enabledWithoutGitlabProject: undefined, workflow: { dockerSocket: '/var/run/docker.sock', useDocker: false, graph: 'foo_bar', executor: undefined }, agentPlatform: { enabled: true } } }} ${{ skipIntegrityChecks: true }} | ${{ knowledgeGraph: { skipBinaryIntegrityChecks: true } }} `('$expected when workspace included $configured', ({ configured, expected }) => { it('should send a configuration changed notification', async () => { setFakeWorkspaceConfiguration(configured); Loading src/common/language_server/language_client_wrapper.ts +14 −0 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ import { } from 'vscode-languageclient'; import { GitLabPlatformManagerForCodeSuggestions } from '../code_suggestions/gitlab_platform_manager_for_code_suggestions'; import { getDistributedBinariesConfiguration, getDuoCodeSuggestionsConfiguration, getDuoChatConfiguration, getHttpAgentConfiguration, Loading Loading @@ -57,6 +58,11 @@ const createNotifyFn = (param: T) => client.sendNotification(method, param); const createRequestFn = <T>(client: BaseLanguageClient, method: string) => (param: T) => client.sendRequest(method, param); export class LanguageClientWrapper { #client: BaseLanguageClient; Loading Loading @@ -159,6 +165,10 @@ export class LanguageClientWrapper { createNotifyFn(this.#client, DEFAULT_WEBVIEW_NOTIFICATION_METHOD), ); this.#webviewMessageRegistry.initRequester( createRequestFn(this.#client, DEFAULT_WEBVIEW_REQUEST_METHOD), ); this.#client.onRequest( 'workspace/applyEdit', this.#applyEditClientWrapper.handleApplyWorkspaceEdit, Loading Loading @@ -224,6 +234,7 @@ export class LanguageClientWrapper { const codeSuggestionsConfiguration = getDuoCodeSuggestionsConfiguration(); const duoChatConfiguration = getDuoChatConfiguration(); const securityScannerConfiguration = getSecurityScannerConfiguration(); const distributedBinariesConfiguration = getDistributedBinariesConfiguration(); const isEnabled = (flag: FeatureFlag) => getLocalFeatureFlagService().isEnabled(flag); const settings: ClientConfig = { baseUrl: platform.account.instanceUrl, Loading Loading @@ -274,6 +285,9 @@ export class LanguageClientWrapper { duoChat: { enabled: duoChatConfiguration.enabled, }, knowledgeGraph: { skipBinaryIntegrityChecks: distributedBinariesConfiguration.skipIntegrityChecks, }, }; log.info(`Configuring Language Server - baseUrl: ${platform.account.instanceUrl}`); Loading src/common/language_server/requester.ts 0 → 100644 +5 −0 Original line number Diff line number Diff line export type RequestFn<T> = (payload: unknown) => Promise<T>; export interface Requester<T> { initRequester(request: RequestFn<T>): void; } Loading
desktop.package.json +21 −0 Original line number Diff line number Diff line Loading @@ -361,6 +361,11 @@ "command": "gl.mcp.openUserConfig", "title": "Open User Settings (JSON)", "category": "GitLab MCP" }, { "command": "gl.knowledgeGraph.show", "title": "Show GitLab Knowledge Graph", "category": "GitLab" } ], "menus": { Loading Loading @@ -636,6 +641,10 @@ { "command": "gl.webview.newChatConversation", "when": "config.gitlab.duoChat.enabled && gitlab:chatAvailable && gitlab:chatAvailableForProject && (gitlab.featureFlags.languageServerWebviews && !gitlab:isRemoteEnvironment)" }, { "command": "gl.knowledgeGraph.show", "when": "gitlab:knowledgeGraphReady" } ], "view/title": [ Loading Loading @@ -1306,6 +1315,18 @@ "description": "Custom views in the GitLab panel" } } }, { "id": "distributed-binaries", "order": 4, "title": "GitLab Distributed Binaries", "properties": { "gitlab.distributedBinaries.skipIntegrityChecks": { "type": "boolean", "default": false, "description": "Skip integrity checks" } } } ], "walkthroughs": [ Loading
src/common/constants.ts +1 −1 Original line number Diff line number Diff line Loading @@ -15,7 +15,7 @@ export const REQUEST_TIMEOUT_MILLISECONDS = 25000; export const DUO_WORKFLOW_PANEL_WEBVIEW_ID = 'duo-workflow-panel'; export const DUO_CHAT_WEBVIEW_ID = 'duo-chat-v2'; export const AGENTIC_CHAT_WEBVIEW_ID = 'agentic-duo-chat'; export const KNOWLEDGE_GRAPH_WEBVIEW_ID = 'knowledge-graph'; export const SECURITY_VULNS_WEBVIEW_ID = 'security-vuln-details'; export const AGENTIC_TABS_WEBVIEW_ID = 'agentic-tabs'; Loading
src/common/language_server/language_client_wrapper.test.ts +24 −0 Original line number Diff line number Diff line Loading @@ -111,6 +111,7 @@ describe('LanguageClientWrapper', () => { registerProposedFeatures: jest.fn(), onNotification: jest.fn(), sendNotification: jest.fn(), sendRequest: jest.fn(), onRequest: jest.fn(), }); lsGitProvider = createFakePartial<LSGitProvider>({ Loading @@ -123,6 +124,7 @@ describe('LanguageClientWrapper', () => { webviewMessageRegistry = createFakePartial<WebviewMessageRegistry>({ initNotifier: jest.fn(), initRequester: jest.fn(), }); languageServerFeatureStateProvider = createFakePartial<LanguageServerFeatureStateProvider>({ Loading Loading @@ -197,6 +199,9 @@ describe('LanguageClientWrapper', () => { duoChat: { enabled: true, }, knowledgeGraph: { skipBinaryIntegrityChecks: false, }, }, }, ); Loading Loading @@ -467,6 +472,24 @@ describe('LanguageClientWrapper', () => { testMessage, ); }); it('initializes the webview message registry requester', async () => { wrapper = createWrapper(); await wrapper.initAndStart(); expect(webviewMessageRegistry.initRequester).toHaveBeenCalledWith(expect.any(Function)); const requesterFunction = jest.mocked(webviewMessageRegistry.initRequester).mock .calls[0][0]; const testMessage = { type: 'test', payload: 'data' }; await requesterFunction(testMessage); expect(client.sendRequest).toHaveBeenCalledWith( DEFAULT_WEBVIEW_REQUEST_METHOD, testMessage, ); }); }); describe('Feature State Manager notification', () => { Loading Loading @@ -632,6 +655,7 @@ describe('LanguageClientWrapper', () => { ${{ cert: 'test-cert' }} | ${{ httpAgentOptions: { cert: 'test-cert' } }} ${{ certKey: 'test-certKey' }} | ${{ httpAgentOptions: { certKey: 'test-certKey' } }} ${{ 'duo.workflow.graph': 'foo_bar' }} | ${{ duo: { enabledWithoutGitlabProject: undefined, workflow: { dockerSocket: '/var/run/docker.sock', useDocker: false, graph: 'foo_bar', executor: undefined }, agentPlatform: { enabled: true } } }} ${{ skipIntegrityChecks: true }} | ${{ knowledgeGraph: { skipBinaryIntegrityChecks: true } }} `('$expected when workspace included $configured', ({ configured, expected }) => { it('should send a configuration changed notification', async () => { setFakeWorkspaceConfiguration(configured); Loading
src/common/language_server/language_client_wrapper.ts +14 −0 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ import { } from 'vscode-languageclient'; import { GitLabPlatformManagerForCodeSuggestions } from '../code_suggestions/gitlab_platform_manager_for_code_suggestions'; import { getDistributedBinariesConfiguration, getDuoCodeSuggestionsConfiguration, getDuoChatConfiguration, getHttpAgentConfiguration, Loading Loading @@ -57,6 +58,11 @@ const createNotifyFn = (param: T) => client.sendNotification(method, param); const createRequestFn = <T>(client: BaseLanguageClient, method: string) => (param: T) => client.sendRequest(method, param); export class LanguageClientWrapper { #client: BaseLanguageClient; Loading Loading @@ -159,6 +165,10 @@ export class LanguageClientWrapper { createNotifyFn(this.#client, DEFAULT_WEBVIEW_NOTIFICATION_METHOD), ); this.#webviewMessageRegistry.initRequester( createRequestFn(this.#client, DEFAULT_WEBVIEW_REQUEST_METHOD), ); this.#client.onRequest( 'workspace/applyEdit', this.#applyEditClientWrapper.handleApplyWorkspaceEdit, Loading Loading @@ -224,6 +234,7 @@ export class LanguageClientWrapper { const codeSuggestionsConfiguration = getDuoCodeSuggestionsConfiguration(); const duoChatConfiguration = getDuoChatConfiguration(); const securityScannerConfiguration = getSecurityScannerConfiguration(); const distributedBinariesConfiguration = getDistributedBinariesConfiguration(); const isEnabled = (flag: FeatureFlag) => getLocalFeatureFlagService().isEnabled(flag); const settings: ClientConfig = { baseUrl: platform.account.instanceUrl, Loading Loading @@ -274,6 +285,9 @@ export class LanguageClientWrapper { duoChat: { enabled: duoChatConfiguration.enabled, }, knowledgeGraph: { skipBinaryIntegrityChecks: distributedBinariesConfiguration.skipIntegrityChecks, }, }; log.info(`Configuring Language Server - baseUrl: ${platform.account.instanceUrl}`); Loading
src/common/language_server/requester.ts 0 → 100644 +5 −0 Original line number Diff line number Diff line export type RequestFn<T> = (payload: unknown) => Promise<T>; export interface Requester<T> { initRequester(request: RequestFn<T>): void; }