Skip to content

Commit

Permalink
fix(auto-edit): fix the cody status bar with new suggestion mode (#6691)
Browse files Browse the repository at this point in the history
## Context 
Cody Status bar for `autocomplete` is broken right now with the
introduction of new suggestion modes.
<img width="777" alt="image"
src="https://github.com/user-attachments/assets/9c4dac2b-766a-49c1-8c02-83c5c9a67c56"
/>

- The PR adds a enum in the quick pick for selecting the suggestion
model between `autocomplete`/`off`/`auto-edit` (if applicable).
- `Auto-edit` is only shown if the user is eligible for the feature. See
in the demo for the free account, we don't show this option.
- Closes
https://linear.app/sourcegraph/issue/CODY-4713/status-bar-autocomplete-switch-doesnt-work

## Test plan
- Switch between different modes in the toggle bar.
- Added a demo below


https://github.com/user-attachments/assets/a7cbb810-04b0-449e-90d3-8d8aa8211ff5
  • Loading branch information
hitesh-1997 authored Jan 29, 2025
1 parent 1599db7 commit 0fe2fff
Show file tree
Hide file tree
Showing 2 changed files with 163 additions and 32 deletions.
7 changes: 0 additions & 7 deletions vscode/src/autoedits/create-autoedits-provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,13 +127,6 @@ export function isUserEligibleForAutoeditsFeature(
authStatus: AuthStatus,
productSubscription: UserProductSubscription | null
): AutoeditsUserEligibilityInfo {
console.log({
autoeditsFeatureFlagEnabled,
isTesting: process.env.CODY_TESTING === 'true',
isRunningInsideAgent: isRunningInsideAgent(),
isFreeUser: isFreeUser(authStatus, productSubscription),
})

// Always enable auto-edit when testing
if (process.env.CODY_TESTING === 'true') {
return { isUserEligible: true }
Expand Down
188 changes: 163 additions & 25 deletions vscode/src/services/StatusBar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,32 @@ import * as vscode from 'vscode'
import {
type AuthStatus,
type ClientConfiguration,
CodyAutoSuggestionMode,
CodyIDE,
FeatureFlag,
InvisibleStatusBarTag,
type IsIgnored,
Mutable,
type ResolvedConfiguration,
type UserProductSubscription,
assertUnreachable,
authStatus,
combineLatest,
contextFiltersProvider,
currentUserProductSubscription,
distinctUntilChanged,
featureFlagProvider,
firstValueFrom,
fromVSCodeEvent,
logError,
promise,
promiseFactoryToObservable,
resolvedConfig,
shareReplay,
} from '@sourcegraph/cody-shared'

import { type Subscription, map } from 'observable-fns'
import type { LiteralUnion, ReadonlyDeep } from 'type-fest'
import { isUserEligibleForAutoeditsFeature } from '../autoedits/create-autoedits-provider'
import { getGhostHintEnablement } from '../commands/GhostHintDecorator'
import { getReleaseNotesURLByIDE } from '../release'
import { version } from '../version'
Expand Down Expand Up @@ -82,7 +88,9 @@ export class CodyStatusBar implements vscode.Disposable {
resolvedConfig,
this.errors.changes,
this.loaders.changes,
this.ignoreStatus
this.ignoreStatus,
featureFlagProvider.evaluatedFeatureFlag(FeatureFlag.CodyAutoEditExperimentEnabledFeatureFlag),
promiseFactoryToObservable(async () => await currentUserProductSubscription())
).pipe(
map((combined): StatusBarState | undefined => {
return {
Expand Down Expand Up @@ -258,7 +266,9 @@ export class CodyStatusBar implements vscode.Disposable {
config: ResolvedConfiguration,
errors: ReadonlySet<StatusBarError>,
loaders: ReadonlySet<StatusBarLoader>,
ignoreStatus: IsIgnored
ignoreStatus: IsIgnored,
autoeditsFeatureFlagEnabled: boolean,
userProductSubscription: UserProductSubscription | null
): Partial<StatusBarState> & Pick<StatusBarState, 'interact' | 'tooltip'> {
const tags = new Set<InvisibleStatusBarTag>()

Expand Down Expand Up @@ -319,6 +329,9 @@ export class CodyStatusBar implements vscode.Disposable {
config,
errors,
isIgnored: ignoreStatus,
autoeditsFeatureFlagEnabled,
userProductSubscription,
authStatus,
}),
}
}
Expand Down Expand Up @@ -356,6 +369,9 @@ export class CodyStatusBar implements vscode.Disposable {
config,
errors,
isIgnored: ignoreStatus,
autoeditsFeatureFlagEnabled,
userProductSubscription,
authStatus,
}),
}
}
Expand All @@ -371,6 +387,9 @@ export class CodyStatusBar implements vscode.Disposable {
config,
errors,
isIgnored: ignoreStatus,
autoeditsFeatureFlagEnabled,
userProductSubscription,
authStatus,
}),
}
}
Expand All @@ -381,6 +400,9 @@ export class CodyStatusBar implements vscode.Disposable {
config,
errors,
isIgnored: ignoreStatus,
autoeditsFeatureFlagEnabled,
userProductSubscription,
authStatus,
}),
}
}
Expand All @@ -406,9 +428,17 @@ function interactDefault({
config,
errors,
isIgnored,
}: { config: ResolvedConfiguration; errors: ReadonlySet<StatusBarError>; isIgnored: IsIgnored }): (
abort: AbortSignal
) => Promise<void> {
autoeditsFeatureFlagEnabled,
userProductSubscription,
authStatus,
}: {
config: ResolvedConfiguration
errors: ReadonlySet<StatusBarError>
isIgnored: IsIgnored
autoeditsFeatureFlagEnabled: boolean
userProductSubscription: UserProductSubscription | null
authStatus: AuthStatus
}): (abort: AbortSignal) => Promise<void> {
return async (abort: AbortSignal) => {
const [interactionDone] = promise<void>()
// this QuickPick could probably be made reactive but that's a bit overkill.
Expand Down Expand Up @@ -436,6 +466,13 @@ function interactDefault({
config.configuration,
vscode.workspace.getConfiguration()
)
const createFeatureEnumChoice = featureCodySuggestionEnumBuilder(
vscode.workspace.getConfiguration()
)

const currentSuggestionMode = await getCurrentCodySuggestionMode(
vscode.workspace.getConfiguration()
)

quickPick.items = [
// These description should stay in sync with the settings in package.json
Expand All @@ -460,25 +497,6 @@ function interactDefault({
},
]
: []),
{ label: 'enable/disable features', kind: vscode.QuickPickItemKind.Separator },
await createFeatureToggle(
'Code Autocomplete',
undefined,
'Enable Cody-powered code autocompletions',
'cody.autocomplete.enabled',
c => c.autocomplete,
false,
[
{
iconPath: new vscode.ThemeIcon('settings-more-action'),
tooltip: 'Autocomplete Settings',
onClick: () =>
vscode.commands.executeCommand('workbench.action.openSettings', {
query: '@ext:sourcegraph.cody-ai autocomplete',
}),
} as vscode.QuickInputButton,
]
),
await createFeatureToggle(
'Code Actions',
undefined,
Expand All @@ -503,6 +521,13 @@ function interactDefault({
return enablement.Document || enablement.EditOrChat || enablement.Generate
}
),
{ label: currentSuggestionMode, kind: vscode.QuickPickItemKind.Separator },
await createFeatureEnumChoice(
'Code Suggestion Settings',
autoeditsFeatureFlagEnabled,
userProductSubscription,
authStatus
),
{ label: 'settings', kind: vscode.QuickPickItemKind.Separator },
{
label: '$(gear) Cody Extension Settings',
Expand Down Expand Up @@ -571,6 +596,100 @@ function interactDefault({
}
}

function featureCodySuggestionEnumBuilder(workspaceConfig: vscode.WorkspaceConfiguration) {
return async (
name: string,
autoeditsFeatureFlagEnabled: boolean,
userProductSubscription: UserProductSubscription | null,
authStatus: AuthStatus
): Promise<StatusBarItem> => {
const currentSuggestionMode = await getCurrentCodySuggestionMode(workspaceConfig)
const { isUserEligible } = isUserEligibleForAutoeditsFeature(
autoeditsFeatureFlagEnabled,
authStatus,
userProductSubscription
)

// Build the set of modes to display
const suggestionModes = [
{
label: CodyStatusBarSuggestionModeLabels.Autocomplete,
detail: 'Show code completions for the rest of the line or block',
value: CodyAutoSuggestionMode.Autocomplete,
},
...(isUserEligible
? [
{
label: CodyStatusBarSuggestionModeLabels.AutoEdit,
detail: 'Show suggested code changes around the cursor based on file changes',
value: CodyAutoSuggestionMode.Autoedit,
},
]
: []),
{
label: CodyStatusBarSuggestionModeLabels.Disabled,
detail: 'No code suggestions',
value: CodyAutoSuggestionMode.Off,
},
]

// Sort the modes so that the current mode is first
suggestionModes.sort((a, b) =>
a.value === currentSuggestionMode ? -1 : b.value === currentSuggestionMode ? 1 : 0
)

const autocompleteSettings = [
{ label: 'autocomplete settings', kind: vscode.QuickPickItemKind.Separator },
{
label: '$(gear) Open Autocomplete Settings',
},
]

return {
label: `$(code) ${name}`,
async onSelect() {
const quickPick = vscode.window.createQuickPick()
quickPick.title = 'Code Suggestion Settings'
quickPick.placeholder = 'Choose an option'
quickPick.items = [
{ label: 'current mode', kind: vscode.QuickPickItemKind.Separator },
...suggestionModes.map(mode => ({
label: mode.label,
detail: mode.detail,
})),
...(currentSuggestionMode === CodyAutoSuggestionMode.Autocomplete
? autocompleteSettings
: []),
]

quickPick.onDidAccept(async () => {
const selected = quickPick.selectedItems[0]
if (!selected) {
quickPick.hide()
return
}
const chosenMode = suggestionModes.find(mode => mode.label === selected.label)
if (chosenMode) {
await workspaceConfig.update(
getCodySuggestionModeKey(),
chosenMode.value,
vscode.ConfigurationTarget.Global
)
vscode.window.showInformationMessage(`${name} is set to “${chosenMode.label}”.`)
} else if (selected.label.includes('Open Autocomplete Settings')) {
await vscode.commands.executeCommand(
'workbench.action.openSettings',
'@ext:sourcegraph.cody-ai cody.autocomplete'
)
}
quickPick.hide()
})
quickPick.show()
},
}
}
}

function featureToggleBuilder(
config: ReadonlyDeep<ClientConfiguration>,
workspaceConfig: vscode.WorkspaceConfiguration
Expand Down Expand Up @@ -608,6 +727,19 @@ function featureToggleBuilder(
}
}

async function getCurrentCodySuggestionMode(
workspaceConfig: vscode.WorkspaceConfiguration
): Promise<string> {
const suggestionModeKey = getCodySuggestionModeKey()
const currentSuggestionMode =
(await workspaceConfig.get<string>(suggestionModeKey)) ?? CodyAutoSuggestionMode.Autocomplete
return currentSuggestionMode
}

function getCodySuggestionModeKey(): string {
return 'cody.suggestions.mode'
}

function ignoreReason(isIgnore: IsIgnored): string | null {
switch (isIgnore) {
case false:
Expand Down Expand Up @@ -660,6 +792,12 @@ interface StatusBarLoader {
kind: 'startup' | 'feature'
}

enum CodyStatusBarSuggestionModeLabels {
Autocomplete = 'Autocomplete',
AutoEdit = 'Auto-edit (experimental)',
Disabled = 'Disabled',
}

type StatusBarErrorType = 'auth' | 'RateLimitError' | 'AutoCompleteDisabledByAdmin' | 'Networking'

interface StatusBarItem extends vscode.QuickPickItem {
Expand Down

0 comments on commit 0fe2fff

Please sign in to comment.