Skip to content

Commit 3bebabd

Browse files
Improves AI model picker flow (#4171)
* Updates AI provider/model selection flow Improves command naming and UX Updates storage key removals on provider reset * Refactors AI provider management - Centralizes provider descriptors and configurations - Improves provider key management and authentication flows - Enhances AI model picker UI with back button - Adds support for resetting AI confirmations --------- Co-authored-by: Eric Amodio <[email protected]>
1 parent a3b7294 commit 3bebabd

28 files changed

+684
-239
lines changed

contributions.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4570,7 +4570,7 @@
45704570
}
45714571
},
45724572
"gitlens.switchAIModel": {
4573-
"label": "Switch AI Model",
4573+
"label": "Switch AI Provider/Model",
45744574
"commandPalette": "gitlens:enabled && gitlens:gk:organization:ai:enabled"
45754575
},
45764576
"gitlens.switchMode": {

docs/telemetry-events.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1484,7 +1484,7 @@ void
14841484
'repoPrivacy': 'private' | 'public' | 'local',
14851485
'repository.visibility': 'private' | 'public' | 'local',
14861486
// Provided for compatibility with other GK surfaces
1487-
'source': 'account' | 'subscription' | 'graph' | 'patchDetails' | 'settings' | 'timeline' | 'home' | 'view' | 'code-suggest' | 'associateIssueWithBranch' | 'cloud-patches' | 'commandPalette' | 'deeplink' | 'inspect' | 'inspect-overview' | 'integrations' | 'launchpad' | 'launchpad-indicator' | 'launchpad-view' | 'notification' | 'prompt' | 'quick-wizard' | 'remoteProvider' | 'startWork' | 'trial-indicator' | 'scm-input' | 'walkthrough' | 'whatsnew' | 'worktrees'
1487+
'source': 'account' | 'subscription' | 'graph' | 'patchDetails' | 'settings' | 'timeline' | 'home' | 'view' | 'code-suggest' | 'ai' | 'ai:picker' | 'associateIssueWithBranch' | 'cloud-patches' | 'commandPalette' | 'deeplink' | 'inspect' | 'inspect-overview' | 'integrations' | 'launchpad' | 'launchpad-indicator' | 'launchpad-view' | 'notification' | 'prompt' | 'quick-wizard' | 'remoteProvider' | 'startWork' | 'trial-indicator' | 'scm-input' | 'walkthrough' | 'whatsnew' | 'worktrees'
14881488
}
14891489
```
14901490

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7705,7 +7705,7 @@
77057705
},
77067706
{
77077707
"command": "gitlens.switchAIModel",
7708-
"title": "Switch AI Model",
7708+
"title": "Switch AI Provider/Model",
77097709
"category": "GitLens"
77107710
},
77117711
{

src/commands/resets.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { GlCommandBase } from './commandBase';
1010

1111
const resetTypes = [
1212
'ai',
13+
'ai:confirmations',
1314
'avatars',
1415
'integrations',
1516
'previews',
@@ -35,6 +36,11 @@ export class ResetCommand extends GlCommandBase {
3536
detail: 'Clears any locally stored AI keys',
3637
item: 'ai',
3738
},
39+
{
40+
label: 'AI Confirmations...',
41+
detail: 'Clears any accepted AI confirmations',
42+
item: 'ai:confirmations',
43+
},
3844
{
3945
label: 'Avatars...',
4046
detail: 'Clears the stored avatar cache',
@@ -111,6 +117,10 @@ export class ResetCommand extends GlCommandBase {
111117
confirmationMessage = 'Are you sure you want to reset all of the stored AI keys?';
112118
confirm.title = 'Reset AI Keys';
113119
break;
120+
case 'ai:confirmations':
121+
confirmationMessage = 'Are you sure you want to reset all AI confirmations?';
122+
confirm.title = 'Reset AI Confirmations';
123+
break;
114124
case 'avatars':
115125
confirmationMessage = 'Are you sure you want to reset the avatar cache?';
116126
confirm.title = 'Reset Avatars';
@@ -172,6 +182,10 @@ export class ResetCommand extends GlCommandBase {
172182
await this.container.ai.reset(true);
173183
break;
174184

185+
case 'ai:confirmations':
186+
this.container.ai.resetConfirmations();
187+
break;
188+
175189
case 'avatars':
176190
resetAvatarCache('all');
177191
break;

src/constants.ai.ts

Lines changed: 66 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import type { AIProviderDescriptor } from './plus/ai/models/model';
2+
13
export type AIProviders =
24
| 'anthropic'
35
| 'deepseek'
@@ -9,7 +11,70 @@ export type AIProviders =
911
| 'vscode'
1012
| 'xai';
1113
export type AIPrimaryProviders = Extract<AIProviders, 'gitkraken' | 'vscode'>;
12-
export const primaryAIProviders = ['gitkraken', 'vscode'] as const satisfies readonly AIPrimaryProviders[];
1314

1415
export type AIProviderAndModel = `${string}:${string}`;
1516
export type SupportedAIModels = `${Exclude<AIProviders, AIPrimaryProviders>}:${string}` | AIPrimaryProviders;
17+
18+
export const gitKrakenProviderDescriptor: AIProviderDescriptor<'gitkraken'> = {
19+
id: 'gitkraken',
20+
name: 'GitKraken AI (Preview)',
21+
primary: true,
22+
requiresAccount: true,
23+
requiresUserKey: false,
24+
} as const;
25+
export const vscodeProviderDescriptor: AIProviderDescriptor<'vscode'> = {
26+
id: 'vscode',
27+
name: 'Copilot',
28+
primary: true,
29+
requiresAccount: false,
30+
requiresUserKey: false,
31+
} as const;
32+
export const openAIProviderDescriptor: AIProviderDescriptor<'openai'> = {
33+
id: 'openai',
34+
name: 'OpenAI',
35+
primary: false,
36+
requiresAccount: true,
37+
requiresUserKey: true,
38+
} as const;
39+
export const anthropicProviderDescriptor: AIProviderDescriptor<'anthropic'> = {
40+
id: 'anthropic',
41+
name: 'Anthropic',
42+
primary: false,
43+
requiresAccount: true,
44+
requiresUserKey: true,
45+
} as const;
46+
export const geminiProviderDescriptor: AIProviderDescriptor<'gemini'> = {
47+
id: 'gemini',
48+
name: 'Google',
49+
primary: false,
50+
requiresAccount: true,
51+
requiresUserKey: true,
52+
} as const;
53+
export const deepSeekProviderDescriptor: AIProviderDescriptor<'deepseek'> = {
54+
id: 'deepseek',
55+
name: 'DeepSeek',
56+
primary: false,
57+
requiresAccount: true,
58+
requiresUserKey: true,
59+
} as const;
60+
export const xAIProviderDescriptor: AIProviderDescriptor<'xai'> = {
61+
id: 'xai',
62+
name: 'xAI',
63+
primary: false,
64+
requiresAccount: true,
65+
requiresUserKey: true,
66+
} as const;
67+
export const githubProviderDescriptor: AIProviderDescriptor<'github'> = {
68+
id: 'github',
69+
name: 'GitHub Models',
70+
primary: false,
71+
requiresAccount: true,
72+
requiresUserKey: true,
73+
} as const;
74+
export const huggingFaceProviderDescriptor: AIProviderDescriptor<'huggingface'> = {
75+
id: 'huggingface',
76+
name: 'Hugging Face',
77+
primary: false,
78+
requiresAccount: true,
79+
requiresUserKey: true,
80+
} as const;

src/constants.storage.ts

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ export const enum SyncedStorageKeys {
2525
}
2626

2727
export type DeprecatedGlobalStorage = {
28-
/** @deprecated use `confirm:ai:tos:${AIProviders}` */
28+
/** @deprecated use `confirm:ai:tos` */
2929
'confirm:sendToOpenAI': boolean;
3030
/** @deprecated */
3131
'home:actions:completed': ('dismissed:welcome' | 'opened:scm')[];
@@ -54,10 +54,14 @@ export type DeprecatedGlobalStorage = {
5454
} & {
5555
/** @deprecated */
5656
[key in `disallow:connection:${string}`]: any;
57+
} & {
58+
/** @deprecated use `confirm:ai:tos` */
59+
[key in `confirm:ai:tos:${AIProviders}`]: boolean;
5760
};
5861

5962
export type GlobalStorage = {
6063
avatars: [string, StoredAvatar][];
64+
'confirm:ai:tos': boolean;
6165
repoVisibility: [string, StoredRepoVisibilityInfo][];
6266
'deepLinks:pending': StoredDeepLinkContext;
6367
pendingWhatsNewOnFocus: boolean;
@@ -82,8 +86,6 @@ export type GlobalStorage = {
8286
'views:scm:grouped:welcome:dismissed': boolean;
8387
'integrations:configured': StoredIntegrationConfigurations;
8488
} & { [key in `plus:preview:${FeaturePreviews}:usages`]: StoredFeaturePreviewUsagePeriod[] } & {
85-
[key in `confirm:ai:tos:${AIProviders}`]: boolean;
86-
} & {
8789
[key in `provider:authentication:skip:${string}`]: boolean;
8890
} & { [key in `gk:${string}:checkin`]: Stored<StoredGKCheckInResponse> } & {
8991
[key in `gk:${string}:organizations`]: Stored<StoredOrganization[]>;
@@ -122,17 +124,21 @@ export interface StoredPromo {
122124
}
123125

124126
export type DeprecatedWorkspaceStorage = {
125-
/** @deprecated use `confirm:ai:tos:${AIProviders}` */
127+
/** @deprecated use `confirm:ai:tos` */
126128
'confirm:sendToOpenAI': boolean;
127129
/** @deprecated */
128130
'graph:banners:dismissed': Record<string, boolean>;
129131
/** @deprecated */
130132
'views:searchAndCompare:keepResults': boolean;
133+
} & {
134+
/** @deprecated use `confirm:ai:tos` */
135+
[key in `confirm:ai:tos:${AIProviders}`]: boolean;
131136
};
132137

133138
export type WorkspaceStorage = {
134139
assumeRepositoriesOnStartup?: boolean;
135140
'branch:comparisons': StoredBranchComparisons;
141+
'confirm:ai:tos': boolean;
136142
'gitComandPalette:usage': StoredRecentUsage;
137143
gitPath: string;
138144
'graph:columns': Record<string, StoredGraphColumn>;
@@ -145,7 +151,7 @@ export type WorkspaceStorage = {
145151
'views:repositories:autoRefresh': boolean;
146152
'views:searchAndCompare:pinned': StoredSearchAndCompareItems;
147153
'views:scm:grouped:selected': GroupableTreeViewTypes;
148-
} & { [key in `confirm:ai:tos:${AIProviders}`]: boolean } & {
154+
} & {
149155
[key in `connected:${Integration['key']}`]: boolean;
150156
};
151157

src/constants.telemetry.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -926,6 +926,8 @@ export type TrackingContext = 'graph' | 'launchpad' | 'visual_file_history' | 'w
926926

927927
export type Sources =
928928
| 'account'
929+
| 'ai'
930+
| 'ai:picker'
929931
| 'associateIssueWithBranch'
930932
| 'code-suggest'
931933
| 'cloud-patches'

0 commit comments

Comments
 (0)