Loading src/common/diagnostics/feature_state_diagnostics/feature_state_diagnostics_renderer.test.ts +25 −5 Original line number Diff line number Diff line Loading @@ -102,11 +102,16 @@ const createMockState = (engaged: boolean): AllFeaturesState => { engagedChecks: engaged ? [ createCheck('authentication-required', 'Authentication required.'), createCheck( 'agentic-chat-feature-flag-disabled' as StateCheckId, 'Feature flag disabled', ), createCheck('agentic-chat-no-support', 'Not supported'), ] : [], allChecks: [ createCheck('authentication-required', 'Authentication required.'), createCheck('agentic-chat-feature-flag-disabled' as StateCheckId, 'Feature flag disabled'), createCheck('agentic-chat-no-support', 'Not supported'), ], }, Loading @@ -115,12 +120,12 @@ const createMockState = (engaged: boolean): AllFeaturesState => { engagedChecks: engaged ? [ createCheck('authentication-required', 'Authentication required.'), createCheck('agentic-chat-no-support', 'Not supported'), createCheck('agent-platform-disabled-by-user', 'Agent Platform disabled by user'), ] : [], allChecks: [ createCheck('authentication-required', 'Authentication required.'), createCheck('agentic-chat-no-support', 'Not supported'), createCheck('agent-platform-disabled-by-user', 'Agent Platform disabled by user'), ], }, [AGENT_PLATFORM_GA_ROLLOUT]: { Loading @@ -131,9 +136,15 @@ const createMockState = (engaged: boolean): AllFeaturesState => { [FLOWS]: { featureId: FLOWS, engagedChecks: engaged ? [createCheck('authentication-required', 'Authentication required.')] ? [ createCheck('authentication-required', 'Authentication required.'), createCheck('agentic-chat-no-support', 'Not supported'), ] : [], allChecks: [createCheck('authentication-required', 'Authentication required.')], allChecks: [ createCheck('authentication-required', 'Authentication required.'), createCheck('agentic-chat-no-support', 'Not supported'), ], }, }; }; Loading Loading @@ -179,8 +190,15 @@ describe('FeatureStateDiagnosticsRenderer', () => { const expectedTerminalContext = `- ${checkStatusPre} Include terminal context is enabled for user ${checkStatusAppend}`; // Note: Only checks with labels in STATE_CHECK_USER_READABLE_LABELS will appear // The 'agentic-chat-feature-flag-disabled' check doesn't have a label, so it's filtered out const expectedAgenticChat = `- ${checkStatusPre} User is authenticated ${checkStatusAppend} - ${checkStatusPre} Agentic Chat is supported for the current project ${checkStatusAppend}`; - ${checkStatusPre} Agentic Chat is supported for the current project ${checkStatusAppend} - ${checkStatusPre} Agent Platform is enabled in settings ${checkStatusAppend}`; const expectedFlows = `- ${checkStatusPre} User is authenticated ${checkStatusAppend} - ${checkStatusPre} Agentic Chat is supported for the current project ${checkStatusAppend} - ${checkStatusPre} Agent Platform is enabled in settings ${checkStatusAppend}`; expect(result[0].title).toBe(`GitLab Duo Code Suggestions (${expectedStatus})`); expect(result[0].content).toBe(expectedCodeSuggestions); Loading @@ -190,6 +208,8 @@ describe('FeatureStateDiagnosticsRenderer', () => { expect(result[2].content).toBe(expectedTerminalContext); expect(result[3].title).toBe(`GitLab Agentic Chat (${expectedStatus})`); expect(result[3].content).toBe(expectedAgenticChat); expect(result[4].title).toBe(`GitLab Flows (${expectedStatus})`); expect(result[4].content).toBe(expectedFlows); }, ); Loading src/common/diagnostics/feature_state_diagnostics/feature_state_diagnostics_renderer.ts +23 −4 Original line number Diff line number Diff line import { AGENT_PLATFORM, CHAT, CODE_SUGGESTIONS, FeatureState, Loading @@ -22,16 +23,23 @@ const checkEnabledMapper = ({ engaged, checkId }: FeatureStateCheck<StateCheckId const createFeatureStateDiagnosticsSection = ( title: string, checks: FeatureState, additionalChecks?: FeatureStateCheck<StateCheckId>[], ): DiagnosticsSection => { // UNSUPPORTED_LANGUAGE check returns false by default on markdown files const diagnosticsChecks = checks.allChecks.filter( ch => STATE_CHECK_USER_READABLE_LABELS[ch.checkId] && ch.checkId !== UNSUPPORTED_LANGUAGE, ); const onOff = diagnosticsChecks.find(ch => ch.engaged) ? 'Off' : 'On'; // Merge additional checks if provided const allChecks = additionalChecks ? [...diagnosticsChecks, ...additionalChecks] : diagnosticsChecks; const onOff = allChecks.find(ch => ch.engaged) ? 'Off' : 'On'; return { title: `${title} (${onOff})`, content: diagnosticsChecks.map(checkEnabledMapper).join('\n') || '', content: allChecks.map(checkEnabledMapper).join('\n') || '', }; }; Loading @@ -43,12 +51,23 @@ export class FeatureStateDiagnosticsRenderer implements DiagnosticsRenderer<[All return []; } // Get only the "Agent Platform is enabled in settings" check to merge into Agentic Chat and Flows // We filter out the authentication check and only include the platform-specific check const agentPlatformEnabledCheck = state[AGENT_PLATFORM].allChecks.filter( ch => STATE_CHECK_USER_READABLE_LABELS[ch.checkId] && ch.checkId !== 'authentication-required', ); return [ createFeatureStateDiagnosticsSection('GitLab Duo Code Suggestions', state[CODE_SUGGESTIONS]), createFeatureStateDiagnosticsSection('GitLab Duo Chat', state[CHAT]), createFeatureStateDiagnosticsSection('Terminal Context', state[CHAT_TERMINAL_CONTEXT]), createFeatureStateDiagnosticsSection('GitLab Agentic Chat', state[AGENTIC_CHAT]), createFeatureStateDiagnosticsSection('GitLab Flows', state[FLOWS]), createFeatureStateDiagnosticsSection( 'GitLab Agentic Chat', state[AGENTIC_CHAT], agentPlatformEnabledCheck, ), createFeatureStateDiagnosticsSection('GitLab Flows', state[FLOWS], agentPlatformEnabledCheck), ]; } } src/common/state/settings_state_provider.test.ts +11 −0 Original line number Diff line number Diff line Loading @@ -5,8 +5,10 @@ import { import { DuoChatConfiguration, DuoCodeSuggestionsConfiguration, DuoAgentPlatformConfiguration, getDuoChatConfiguration, getDuoCodeSuggestionsConfiguration, getAgentPlatformConfiguration, getHttpAgentConfiguration, getSecurityScannerConfiguration, httpAgentConfiguration, Loading @@ -18,6 +20,7 @@ import { SettingsStateProvider } from './settings_state_provider'; jest.mock('../utils/extension_configuration', () => ({ getDuoCodeSuggestionsConfiguration: jest.fn(), getDuoChatConfiguration: jest.fn(), getAgentPlatformConfiguration: jest.fn(), getHttpAgentConfiguration: jest.fn(), getSecurityScannerConfiguration: jest.fn(), })); Loading @@ -39,6 +42,12 @@ describe('SettingsStateProvider', () => { duoChat: createFakePartial<DuoChatConfiguration>({ enabled: true, }), duoAgentPlatform: createFakePartial<DuoAgentPlatformConfiguration>({ enabled: true, connectionType: 'websocket', defaultNamespace: '', editFileDiffBehavior: 'foreground', }), http: createFakePartial<httpAgentConfiguration>({ ca: 'ca', cert: 'cert', Loading @@ -54,6 +63,7 @@ describe('SettingsStateProvider', () => { extensionConfiguration: mockConfigs.extension, duoCodeSuggestionsConfiguration: mockConfigs.duo, duoChatConfiguration: mockConfigs.duoChat, duoAgentPlatformConfiguration: mockConfigs.duoAgentPlatform, httpProxyConfiguration: mockConfigs.http, securityScannerConfiguration: mockConfigs.security, }; Loading @@ -67,6 +77,7 @@ describe('SettingsStateProvider', () => { beforeAll(() => { jest.mocked(getDuoCodeSuggestionsConfiguration).mockReturnValue(mockConfigs.duo); jest.mocked(getDuoChatConfiguration).mockReturnValue(mockConfigs.duoChat); jest.mocked(getAgentPlatformConfiguration).mockReturnValue(mockConfigs.duoAgentPlatform); jest.mocked(getHttpAgentConfiguration).mockReturnValue(mockConfigs.http); jest.mocked(getSecurityScannerConfiguration).mockReturnValue(mockConfigs.security); }); Loading src/common/state/settings_state_provider.ts +4 −0 Original line number Diff line number Diff line Loading @@ -6,8 +6,10 @@ import { import { DuoChatConfiguration, DuoCodeSuggestionsConfiguration, DuoAgentPlatformConfiguration, getDuoChatConfiguration, getDuoCodeSuggestionsConfiguration, getAgentPlatformConfiguration, getHttpAgentConfiguration, getSecurityScannerConfiguration, httpAgentConfiguration, Loading @@ -19,6 +21,7 @@ export interface SettingsDetails { extensionConfiguration: ExtensionConfiguration; duoCodeSuggestionsConfiguration: DuoCodeSuggestionsConfiguration; duoChatConfiguration: DuoChatConfiguration; duoAgentPlatformConfiguration: DuoAgentPlatformConfiguration; httpProxyConfiguration: httpAgentConfiguration; securityScannerConfiguration: SecurityScannerConfiguration; } Loading @@ -44,6 +47,7 @@ export class SettingsStateProvider implements ExtensionStateProvider<SettingsDet extensionConfiguration: this.#configurationService.getConfiguration(), duoCodeSuggestionsConfiguration: getDuoCodeSuggestionsConfiguration(), duoChatConfiguration: getDuoChatConfiguration(), duoAgentPlatformConfiguration: getAgentPlatformConfiguration(), httpProxyConfiguration: getHttpAgentConfiguration(), securityScannerConfiguration: getSecurityScannerConfiguration(), }; Loading src/common/test_utils/diagnostics_configuration.ts +7 −0 Original line number Diff line number Diff line Loading @@ -3,6 +3,7 @@ import { SettingsDetails } from '../state/settings_state_provider'; import { DuoChatConfiguration, DuoCodeSuggestionsConfiguration, DuoAgentPlatformConfiguration, httpAgentConfiguration, SecurityScannerConfiguration, } from '../utils/extension_configuration'; Loading Loading @@ -35,6 +36,12 @@ export const createMockSettingsDetails = (): SettingsDetails => ({ duoChatConfiguration: createFakePartial<DuoChatConfiguration>({ enabled: true, }), duoAgentPlatformConfiguration: createFakePartial<DuoAgentPlatformConfiguration>({ enabled: true, connectionType: 'websocket', defaultNamespace: '', editFileDiffBehavior: 'foreground', }), httpProxyConfiguration: createFakePartial<httpAgentConfiguration>({ ca: 'ca-cert', cert: 'cert-file', Loading Loading
src/common/diagnostics/feature_state_diagnostics/feature_state_diagnostics_renderer.test.ts +25 −5 Original line number Diff line number Diff line Loading @@ -102,11 +102,16 @@ const createMockState = (engaged: boolean): AllFeaturesState => { engagedChecks: engaged ? [ createCheck('authentication-required', 'Authentication required.'), createCheck( 'agentic-chat-feature-flag-disabled' as StateCheckId, 'Feature flag disabled', ), createCheck('agentic-chat-no-support', 'Not supported'), ] : [], allChecks: [ createCheck('authentication-required', 'Authentication required.'), createCheck('agentic-chat-feature-flag-disabled' as StateCheckId, 'Feature flag disabled'), createCheck('agentic-chat-no-support', 'Not supported'), ], }, Loading @@ -115,12 +120,12 @@ const createMockState = (engaged: boolean): AllFeaturesState => { engagedChecks: engaged ? [ createCheck('authentication-required', 'Authentication required.'), createCheck('agentic-chat-no-support', 'Not supported'), createCheck('agent-platform-disabled-by-user', 'Agent Platform disabled by user'), ] : [], allChecks: [ createCheck('authentication-required', 'Authentication required.'), createCheck('agentic-chat-no-support', 'Not supported'), createCheck('agent-platform-disabled-by-user', 'Agent Platform disabled by user'), ], }, [AGENT_PLATFORM_GA_ROLLOUT]: { Loading @@ -131,9 +136,15 @@ const createMockState = (engaged: boolean): AllFeaturesState => { [FLOWS]: { featureId: FLOWS, engagedChecks: engaged ? [createCheck('authentication-required', 'Authentication required.')] ? [ createCheck('authentication-required', 'Authentication required.'), createCheck('agentic-chat-no-support', 'Not supported'), ] : [], allChecks: [createCheck('authentication-required', 'Authentication required.')], allChecks: [ createCheck('authentication-required', 'Authentication required.'), createCheck('agentic-chat-no-support', 'Not supported'), ], }, }; }; Loading Loading @@ -179,8 +190,15 @@ describe('FeatureStateDiagnosticsRenderer', () => { const expectedTerminalContext = `- ${checkStatusPre} Include terminal context is enabled for user ${checkStatusAppend}`; // Note: Only checks with labels in STATE_CHECK_USER_READABLE_LABELS will appear // The 'agentic-chat-feature-flag-disabled' check doesn't have a label, so it's filtered out const expectedAgenticChat = `- ${checkStatusPre} User is authenticated ${checkStatusAppend} - ${checkStatusPre} Agentic Chat is supported for the current project ${checkStatusAppend}`; - ${checkStatusPre} Agentic Chat is supported for the current project ${checkStatusAppend} - ${checkStatusPre} Agent Platform is enabled in settings ${checkStatusAppend}`; const expectedFlows = `- ${checkStatusPre} User is authenticated ${checkStatusAppend} - ${checkStatusPre} Agentic Chat is supported for the current project ${checkStatusAppend} - ${checkStatusPre} Agent Platform is enabled in settings ${checkStatusAppend}`; expect(result[0].title).toBe(`GitLab Duo Code Suggestions (${expectedStatus})`); expect(result[0].content).toBe(expectedCodeSuggestions); Loading @@ -190,6 +208,8 @@ describe('FeatureStateDiagnosticsRenderer', () => { expect(result[2].content).toBe(expectedTerminalContext); expect(result[3].title).toBe(`GitLab Agentic Chat (${expectedStatus})`); expect(result[3].content).toBe(expectedAgenticChat); expect(result[4].title).toBe(`GitLab Flows (${expectedStatus})`); expect(result[4].content).toBe(expectedFlows); }, ); Loading
src/common/diagnostics/feature_state_diagnostics/feature_state_diagnostics_renderer.ts +23 −4 Original line number Diff line number Diff line import { AGENT_PLATFORM, CHAT, CODE_SUGGESTIONS, FeatureState, Loading @@ -22,16 +23,23 @@ const checkEnabledMapper = ({ engaged, checkId }: FeatureStateCheck<StateCheckId const createFeatureStateDiagnosticsSection = ( title: string, checks: FeatureState, additionalChecks?: FeatureStateCheck<StateCheckId>[], ): DiagnosticsSection => { // UNSUPPORTED_LANGUAGE check returns false by default on markdown files const diagnosticsChecks = checks.allChecks.filter( ch => STATE_CHECK_USER_READABLE_LABELS[ch.checkId] && ch.checkId !== UNSUPPORTED_LANGUAGE, ); const onOff = diagnosticsChecks.find(ch => ch.engaged) ? 'Off' : 'On'; // Merge additional checks if provided const allChecks = additionalChecks ? [...diagnosticsChecks, ...additionalChecks] : diagnosticsChecks; const onOff = allChecks.find(ch => ch.engaged) ? 'Off' : 'On'; return { title: `${title} (${onOff})`, content: diagnosticsChecks.map(checkEnabledMapper).join('\n') || '', content: allChecks.map(checkEnabledMapper).join('\n') || '', }; }; Loading @@ -43,12 +51,23 @@ export class FeatureStateDiagnosticsRenderer implements DiagnosticsRenderer<[All return []; } // Get only the "Agent Platform is enabled in settings" check to merge into Agentic Chat and Flows // We filter out the authentication check and only include the platform-specific check const agentPlatformEnabledCheck = state[AGENT_PLATFORM].allChecks.filter( ch => STATE_CHECK_USER_READABLE_LABELS[ch.checkId] && ch.checkId !== 'authentication-required', ); return [ createFeatureStateDiagnosticsSection('GitLab Duo Code Suggestions', state[CODE_SUGGESTIONS]), createFeatureStateDiagnosticsSection('GitLab Duo Chat', state[CHAT]), createFeatureStateDiagnosticsSection('Terminal Context', state[CHAT_TERMINAL_CONTEXT]), createFeatureStateDiagnosticsSection('GitLab Agentic Chat', state[AGENTIC_CHAT]), createFeatureStateDiagnosticsSection('GitLab Flows', state[FLOWS]), createFeatureStateDiagnosticsSection( 'GitLab Agentic Chat', state[AGENTIC_CHAT], agentPlatformEnabledCheck, ), createFeatureStateDiagnosticsSection('GitLab Flows', state[FLOWS], agentPlatformEnabledCheck), ]; } }
src/common/state/settings_state_provider.test.ts +11 −0 Original line number Diff line number Diff line Loading @@ -5,8 +5,10 @@ import { import { DuoChatConfiguration, DuoCodeSuggestionsConfiguration, DuoAgentPlatformConfiguration, getDuoChatConfiguration, getDuoCodeSuggestionsConfiguration, getAgentPlatformConfiguration, getHttpAgentConfiguration, getSecurityScannerConfiguration, httpAgentConfiguration, Loading @@ -18,6 +20,7 @@ import { SettingsStateProvider } from './settings_state_provider'; jest.mock('../utils/extension_configuration', () => ({ getDuoCodeSuggestionsConfiguration: jest.fn(), getDuoChatConfiguration: jest.fn(), getAgentPlatformConfiguration: jest.fn(), getHttpAgentConfiguration: jest.fn(), getSecurityScannerConfiguration: jest.fn(), })); Loading @@ -39,6 +42,12 @@ describe('SettingsStateProvider', () => { duoChat: createFakePartial<DuoChatConfiguration>({ enabled: true, }), duoAgentPlatform: createFakePartial<DuoAgentPlatformConfiguration>({ enabled: true, connectionType: 'websocket', defaultNamespace: '', editFileDiffBehavior: 'foreground', }), http: createFakePartial<httpAgentConfiguration>({ ca: 'ca', cert: 'cert', Loading @@ -54,6 +63,7 @@ describe('SettingsStateProvider', () => { extensionConfiguration: mockConfigs.extension, duoCodeSuggestionsConfiguration: mockConfigs.duo, duoChatConfiguration: mockConfigs.duoChat, duoAgentPlatformConfiguration: mockConfigs.duoAgentPlatform, httpProxyConfiguration: mockConfigs.http, securityScannerConfiguration: mockConfigs.security, }; Loading @@ -67,6 +77,7 @@ describe('SettingsStateProvider', () => { beforeAll(() => { jest.mocked(getDuoCodeSuggestionsConfiguration).mockReturnValue(mockConfigs.duo); jest.mocked(getDuoChatConfiguration).mockReturnValue(mockConfigs.duoChat); jest.mocked(getAgentPlatformConfiguration).mockReturnValue(mockConfigs.duoAgentPlatform); jest.mocked(getHttpAgentConfiguration).mockReturnValue(mockConfigs.http); jest.mocked(getSecurityScannerConfiguration).mockReturnValue(mockConfigs.security); }); Loading
src/common/state/settings_state_provider.ts +4 −0 Original line number Diff line number Diff line Loading @@ -6,8 +6,10 @@ import { import { DuoChatConfiguration, DuoCodeSuggestionsConfiguration, DuoAgentPlatformConfiguration, getDuoChatConfiguration, getDuoCodeSuggestionsConfiguration, getAgentPlatformConfiguration, getHttpAgentConfiguration, getSecurityScannerConfiguration, httpAgentConfiguration, Loading @@ -19,6 +21,7 @@ export interface SettingsDetails { extensionConfiguration: ExtensionConfiguration; duoCodeSuggestionsConfiguration: DuoCodeSuggestionsConfiguration; duoChatConfiguration: DuoChatConfiguration; duoAgentPlatformConfiguration: DuoAgentPlatformConfiguration; httpProxyConfiguration: httpAgentConfiguration; securityScannerConfiguration: SecurityScannerConfiguration; } Loading @@ -44,6 +47,7 @@ export class SettingsStateProvider implements ExtensionStateProvider<SettingsDet extensionConfiguration: this.#configurationService.getConfiguration(), duoCodeSuggestionsConfiguration: getDuoCodeSuggestionsConfiguration(), duoChatConfiguration: getDuoChatConfiguration(), duoAgentPlatformConfiguration: getAgentPlatformConfiguration(), httpProxyConfiguration: getHttpAgentConfiguration(), securityScannerConfiguration: getSecurityScannerConfiguration(), }; Loading
src/common/test_utils/diagnostics_configuration.ts +7 −0 Original line number Diff line number Diff line Loading @@ -3,6 +3,7 @@ import { SettingsDetails } from '../state/settings_state_provider'; import { DuoChatConfiguration, DuoCodeSuggestionsConfiguration, DuoAgentPlatformConfiguration, httpAgentConfiguration, SecurityScannerConfiguration, } from '../utils/extension_configuration'; Loading Loading @@ -35,6 +36,12 @@ export const createMockSettingsDetails = (): SettingsDetails => ({ duoChatConfiguration: createFakePartial<DuoChatConfiguration>({ enabled: true, }), duoAgentPlatformConfiguration: createFakePartial<DuoAgentPlatformConfiguration>({ enabled: true, connectionType: 'websocket', defaultNamespace: '', editFileDiffBehavior: 'foreground', }), httpProxyConfiguration: createFakePartial<httpAgentConfiguration>({ ca: 'ca-cert', cert: 'cert-file', Loading