Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 13 additions & 13 deletions contributions.json
Original file line number Diff line number Diff line change
Expand Up @@ -233,70 +233,70 @@
}
},
"gitlens.ai.generateCommits": {
"label": "Generate Commits with AI (Experimental)...",
"label": "Generate Commits with AI (Preview)...",
"icon": "$(sparkle)",
"commandPalette": "gitlens:enabled && !gitlens:untrusted && gitlens:gk:organization:ai:enabled && config.gitlens.ai.experimental.generateCommits.enabled"
"commandPalette": "gitlens:enabled && !gitlens:untrusted && gitlens:gk:organization:ai:enabled"
},
"gitlens.ai.generateCommits:graph": {
"label": "Generate Commits with AI (Experimental)",
"label": "Generate Commits with AI (Preview)",
"icon": "$(sparkle)",
"menus": {
"webview/context": [
{
"when": "webviewItem == gitlens:wip && !listMultiSelection && !gitlens:readonly && !gitlens:untrusted && gitlens:gk:organization:ai:enabled && config.gitlens.ai.experimental.generateCommits.enabled",
"when": "webviewItem == gitlens:wip && !listMultiSelection && !gitlens:readonly && !gitlens:untrusted && gitlens:gk:organization:ai:enabled",
"group": "1_gitlens",
"order": 2
}
]
}
},
"gitlens.ai.generateCommits:views": {
"label": "Generate Commits with AI (Experimental)",
"label": "Generate Commits with AI (Preview)",
"icon": "$(sparkle)",
"menus": {
"view/item/context": [
{
"when": "viewItem =~ /gitlens:(worktree\\b(?=.*?\\b\\+working\\b)|uncommitted)\\b/ && !listMultiSelection && !gitlens:readonly && !gitlens:untrusted && gitlens:gk:organization:ai:enabled && config.gitlens.ai.experimental.generateCommits.enabled",
"when": "viewItem =~ /gitlens:(worktree\\b(?=.*?\\b\\+working\\b)|uncommitted)\\b/ && !listMultiSelection && !gitlens:readonly && !gitlens:untrusted && gitlens:gk:organization:ai:enabled",
"group": "3_gitlens_ai",
"order": 1
}
]
}
},
"gitlens.ai.generateRebase": {
"label": "Rebase with AI (Experimental)...",
"label": "Rebase with AI (Preview)...",
"icon": "$(sparkle)",
"commandPalette": "gitlens:enabled && !gitlens:untrusted && gitlens:gk:organization:ai:enabled && config.gitlens.ai.experimental.generateRebase.enabled"
"commandPalette": "gitlens:enabled && !gitlens:untrusted && gitlens:gk:organization:ai:enabled"
},
"gitlens.ai.rebaseOntoCommit:graph": {
"label": "AI Rebase Current Branch onto Commit...",
"label": "AI Rebase Current Branch onto Commit (Preview)...",
"icon": "$(sparkle)",
"enablement": "!operationInProgress",
"menus": {
"webview/context": [
{
"when": "webviewItem =~ /gitlens:commit\\b/ && !listMultiSelection && !gitlens:readonly && !gitlens:untrusted && !gitlens:hasVirtualFolders && gitlens:gk:organization:ai:enabled && config.gitlens.ai.experimental.generateRebase.enabled",
"when": "webviewItem =~ /gitlens:commit\\b/ && !listMultiSelection && !gitlens:readonly && !gitlens:untrusted && !gitlens:hasVirtualFolders && gitlens:gk:organization:ai:enabled",
"group": "1_gitlens_actions",
"order": 6
}
]
}
},
"gitlens.ai.rebaseOntoCommit:views": {
"label": "AI Rebase Current Branch onto Commit...",
"label": "AI Rebase Current Branch onto Commit (Preview)...",
"icon": "$(sparkle)",
"enablement": "!operationInProgress",
"menus": {
"gitlens/commit/file/commit": [
{
"when": "viewItem =~ /gitlens:file\\b(?=.*?\\b\\+committed\\b)(?=.*?\\b\\+current\\b)/ && !gitlens:readonly && !gitlens:untrusted && !gitlens:hasVirtualFolders && gitlens:gk:organization:ai:enabled && config.gitlens.ai.experimental.generateRebase.enabled",
"when": "viewItem =~ /gitlens:file\\b(?=.*?\\b\\+committed\\b)(?=.*?\\b\\+current\\b)/ && !gitlens:readonly && !gitlens:untrusted && !gitlens:hasVirtualFolders && gitlens:gk:organization:ai:enabled",
"group": "1_gitlens_actions",
"order": 6
}
],
"view/item/context": [
{
"when": "viewItem =~ /gitlens:commit\\b(?!.*?\\b\\+rebase\\b)/ && !listMultiSelection && !gitlens:readonly && !gitlens:untrusted && !gitlens:hasVirtualFolders && gitlens:gk:organization:ai:enabled && config.gitlens.ai.experimental.generateRebase.enabled",
"when": "viewItem =~ /gitlens:commit\\b(?!.*?\\b\\+rebase\\b)/ && !listMultiSelection && !gitlens:readonly && !gitlens:untrusted && !gitlens:hasVirtualFolders && gitlens:gk:organization:ai:enabled",
"group": "1_gitlens_actions",
"order": 6
}
Expand Down
46 changes: 13 additions & 33 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4261,26 +4261,6 @@
"preview"
]
},
"gitlens.ai.experimental.generateCommits.enabled": {
"type": "boolean",
"default": false,
"markdownDescription": "Specifies whether to enable GitLens' experimental AI Commit Generation features",
"scope": "window",
"order": 1,
"tags": [
"experimental"
]
},
"gitlens.ai.experimental.generateRebase.enabled": {
"type": "boolean",
"default": false,
"markdownDescription": "Specifies whether to enable GitLens' experimental AI Rebase features",
"scope": "window",
"order": 1,
"tags": [
"experimental"
]
},
"gitlens.ai.generateStashMessage.customInstructions": {
"type": "string",
"default": null,
Expand Down Expand Up @@ -6247,35 +6227,35 @@
},
{
"command": "gitlens.ai.generateCommits",
"title": "Generate Commits with AI (Experimental)...",
"title": "Generate Commits with AI (Preview)...",
"category": "GitLens",
"icon": "$(sparkle)"
},
{
"command": "gitlens.ai.generateCommits:graph",
"title": "Generate Commits with AI (Experimental)",
"title": "Generate Commits with AI (Preview)",
"icon": "$(sparkle)"
},
{
"command": "gitlens.ai.generateCommits:views",
"title": "Generate Commits with AI (Experimental)",
"title": "Generate Commits with AI (Preview)",
"icon": "$(sparkle)"
},
{
"command": "gitlens.ai.generateRebase",
"title": "Rebase with AI (Experimental)...",
"title": "Rebase with AI (Preview)...",
"category": "GitLens",
"icon": "$(sparkle)"
},
{
"command": "gitlens.ai.rebaseOntoCommit:graph",
"title": "AI Rebase Current Branch onto Commit...",
"title": "AI Rebase Current Branch onto Commit (Preview)...",
"icon": "$(sparkle)",
"enablement": "!operationInProgress"
},
{
"command": "gitlens.ai.rebaseOntoCommit:views",
"title": "AI Rebase Current Branch onto Commit...",
"title": "AI Rebase Current Branch onto Commit (Preview)...",
"icon": "$(sparkle)",
"enablement": "!operationInProgress"
},
Expand Down Expand Up @@ -10766,7 +10746,7 @@
},
{
"command": "gitlens.ai.generateCommits",
"when": "gitlens:enabled && !gitlens:untrusted && gitlens:gk:organization:ai:enabled && config.gitlens.ai.experimental.generateCommits.enabled"
"when": "gitlens:enabled && !gitlens:untrusted && gitlens:gk:organization:ai:enabled"
},
{
"command": "gitlens.ai.generateCommits:graph",
Expand All @@ -10778,7 +10758,7 @@
},
{
"command": "gitlens.ai.generateRebase",
"when": "gitlens:enabled && !gitlens:untrusted && gitlens:gk:organization:ai:enabled && config.gitlens.ai.experimental.generateRebase.enabled"
"when": "gitlens:enabled && !gitlens:untrusted && gitlens:gk:organization:ai:enabled"
},
{
"command": "gitlens.ai.rebaseOntoCommit:graph",
Expand Down Expand Up @@ -14403,7 +14383,7 @@
},
{
"command": "gitlens.ai.rebaseOntoCommit:views",
"when": "viewItem =~ /gitlens:file\\b(?=.*?\\b\\+committed\\b)(?=.*?\\b\\+current\\b)/ && !gitlens:readonly && !gitlens:untrusted && !gitlens:hasVirtualFolders && gitlens:gk:organization:ai:enabled && config.gitlens.ai.experimental.generateRebase.enabled",
"when": "viewItem =~ /gitlens:file\\b(?=.*?\\b\\+committed\\b)(?=.*?\\b\\+current\\b)/ && !gitlens:readonly && !gitlens:untrusted && !gitlens:hasVirtualFolders && gitlens:gk:organization:ai:enabled",
"group": "1_gitlens_actions@6"
},
{
Expand Down Expand Up @@ -17097,7 +17077,7 @@
},
{
"command": "gitlens.ai.rebaseOntoCommit:views",
"when": "viewItem =~ /gitlens:commit\\b(?!.*?\\b\\+rebase\\b)/ && !listMultiSelection && !gitlens:readonly && !gitlens:untrusted && !gitlens:hasVirtualFolders && gitlens:gk:organization:ai:enabled && config.gitlens.ai.experimental.generateRebase.enabled",
"when": "viewItem =~ /gitlens:commit\\b(?!.*?\\b\\+rebase\\b)/ && !listMultiSelection && !gitlens:readonly && !gitlens:untrusted && !gitlens:hasVirtualFolders && gitlens:gk:organization:ai:enabled",
"group": "1_gitlens_actions@6"
},
{
Expand Down Expand Up @@ -18380,7 +18360,7 @@
},
{
"command": "gitlens.ai.generateCommits:views",
"when": "viewItem =~ /gitlens:(worktree\\b(?=.*?\\b\\+working\\b)|uncommitted)\\b/ && !listMultiSelection && !gitlens:readonly && !gitlens:untrusted && gitlens:gk:organization:ai:enabled && config.gitlens.ai.experimental.generateCommits.enabled",
"when": "viewItem =~ /gitlens:(worktree\\b(?=.*?\\b\\+working\\b)|uncommitted)\\b/ && !listMultiSelection && !gitlens:readonly && !gitlens:untrusted && gitlens:gk:organization:ai:enabled",
"group": "3_gitlens_ai@1"
},
{
Expand Down Expand Up @@ -22728,7 +22708,7 @@
},
{
"command": "gitlens.ai.rebaseOntoCommit:graph",
"when": "webviewItem =~ /gitlens:commit\\b/ && !listMultiSelection && !gitlens:readonly && !gitlens:untrusted && !gitlens:hasVirtualFolders && gitlens:gk:organization:ai:enabled && config.gitlens.ai.experimental.generateRebase.enabled",
"when": "webviewItem =~ /gitlens:commit\\b/ && !listMultiSelection && !gitlens:readonly && !gitlens:untrusted && !gitlens:hasVirtualFolders && gitlens:gk:organization:ai:enabled",
"group": "1_gitlens_actions@6"
},
{
Expand Down Expand Up @@ -22988,7 +22968,7 @@
},
{
"command": "gitlens.ai.generateCommits:graph",
"when": "webviewItem == gitlens:wip && !listMultiSelection && !gitlens:readonly && !gitlens:untrusted && gitlens:gk:organization:ai:enabled && config.gitlens.ai.experimental.generateCommits.enabled",
"when": "webviewItem == gitlens:wip && !listMultiSelection && !gitlens:readonly && !gitlens:untrusted && gitlens:gk:organization:ai:enabled",
"group": "1_gitlens@2"
},
{
Expand Down
13 changes: 11 additions & 2 deletions src/commands/generateRebase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,11 @@ export class GenerateCommitsCommand extends GlCommandBase {
createReference(uncommitted, svc.path, { refType: 'revision' }),
createReference('HEAD', svc.path, { refType: 'revision' }),
args?.source ?? { source: 'commandPalette' },
{ title: 'Generate Commits', progress: { location: ProgressLocation.Notification } },
{
title: 'Generate Commits',
progress: { location: ProgressLocation.Notification },
generateCommits: true,
},
);
} catch (ex) {
Logger.error(ex, 'GenerateCommitsCommand', 'execute');
Expand Down Expand Up @@ -165,7 +169,12 @@ export async function generateRebase(
head: GitReference,
base: GitReference,
source: Source,
options?: { title?: string; cancellation?: CancellationToken; progress?: ProgressOptions },
options?: {
title?: string;
cancellation?: CancellationToken;
progress?: ProgressOptions;
generateCommits?: boolean;
},
): Promise<void> {
const { title, ...aiOptions } = options ?? {};

Expand Down
8 changes: 0 additions & 8 deletions src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -217,14 +217,6 @@ interface AIConfig {
readonly explainChanges: {
readonly customInstructions: string;
};
readonly experimental: {
readonly generateCommits: {
readonly enabled: boolean;
};
readonly generateRebase: {
readonly enabled: boolean;
};
};
readonly generateChangelog: {
readonly customInstructions: string;
};
Expand Down
2 changes: 2 additions & 0 deletions src/constants.storage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ export type DeprecatedGlobalStorage = {

export type GlobalStorage = {
avatars: [string, StoredAvatar][];
'confirm:ai:generateCommits': boolean;
'confirm:ai:generateRebase': boolean;
'confirm:ai:tos': boolean;
repoVisibility: [string, StoredRepoVisibilityInfo][];
pendingWhatsNewOnFocus: boolean;
Expand Down
40 changes: 37 additions & 3 deletions src/plus/ai/aiProviderService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -871,6 +871,7 @@ export class AIProviderService implements Disposable {
context?: string;
generating?: Deferred<AIModel>;
progress?: ProgressOptions;
generateCommits?: boolean;
},
): Promise<AIRebaseResult | undefined> {
const result: Mutable<AIRebaseResult> = {
Expand All @@ -880,12 +881,43 @@ export class AIProviderService implements Disposable {
commits: [],
} as unknown as AIRebaseResult;

const confirmed = this.container.storage.get(
options?.generateCommits ? 'confirm:ai:generateCommits' : 'confirm:ai:generateRebase',
false,
);
if (!confirmed) {
const accept: MessageItem = { title: 'Continue' };
const cancel: MessageItem = { title: 'Cancel', isCloseAffordance: true };

const result = await window.showInformationMessage(
`This will ${
options?.generateCommits
? 'stash all of your changes and commit directly to your current branch'
: 'create a new branch at the chosen commit and commit directly to that branch'
}.`,
{ modal: true },
accept,
cancel,
);

if (result === cancel) {
return undefined;
} else if (result === accept) {
await this.container.storage.store(
options?.generateCommits ? 'confirm:ai:generateCommits' : 'confirm:ai:generateRebase',
true,
);
}
}

const rq = await this.sendRequest(
'generate-rebase',
async (model, reporting, cancellation, maxInputTokens, retries) => {
const diff = await repo.git.diff.getDiff?.(headRef, baseRef, { notation: '...' });
if (!diff?.contents) {
throw new AINoRequestDataError('No changes found to generate a rebase from.');
throw new AINoRequestDataError(
`No changes found to generate ${options?.generateCommits ? 'commits' : 'a rebase'} from.`,
);
}
if (cancellation.isCancellationRequested) throw new CancellationError();

Expand Down Expand Up @@ -937,7 +969,7 @@ export class AIProviderService implements Disposable {
const messages: AIChatMessage[] = [{ role: 'user', content: prompt }];
return messages;
},
m => `Generating rebase with ${m.name}...`,
m => `Generating ${options?.generateCommits ? 'commits' : 'rebase'} with ${m.name}...`,
source,
m => ({
key: 'ai/generate',
Expand All @@ -959,7 +991,7 @@ export class AIProviderService implements Disposable {
result.commits = JSON.parse(content) as AIRebaseResult['commits'];
} catch {
debugger;
throw new Error('Unable to parse rebase result');
throw new Error(`Unable to parse ${options?.generateCommits ? 'commits' : 'rebase'} result`);
}

return {
Expand Down Expand Up @@ -1408,6 +1440,8 @@ export class AIProviderService implements Disposable {
resetConfirmations(): void {
void this.container.storage.deleteWithPrefix(`confirm:ai:tos`);
void this.container.storage.deleteWorkspaceWithPrefix(`confirm:ai:tos`);
void this.container.storage.deleteWithPrefix(`confirm:ai:generateCommits`);
void this.container.storage.deleteWithPrefix(`confirm:ai:generateRebase`);
}

resetProviderKey(provider: AIProviders, silent?: boolean): void {
Expand Down
1 change: 0 additions & 1 deletion src/webviews/apps/home/stateProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,6 @@ export class HomeStateProvider implements StateProvider<State> {
this._state.previewEnabled = msg.params.previewEnabled;
this._state.previewCollapsed = msg.params.previewCollapsed;
this._state.aiEnabled = msg.params.aiEnabled;
this._state.aiGenerateCommitsEnabled = msg.params.aiGenerateCommitsEnabled;
this._state.timestamp = Date.now();

this.provider.setValue(this._state, true);
Expand Down
16 changes: 7 additions & 9 deletions src/webviews/apps/plus/home/components/active-work.ts
Original file line number Diff line number Diff line change
Expand Up @@ -269,15 +269,13 @@ export class GlActiveBranchCard extends GlBranchCardBase {
const actions = [];
if (aiEnabled) {
if (hasWip) {
if (this._homeState.aiGenerateCommitsEnabled) {
actions.push(
html`<menu-item
?disabled=${isFetching}
href=${this.createCommandLink('gitlens.ai.generateCommits:home')}
>Generate Commits with AI (Experimental)</menu-item
>`,
);
}
actions.push(
html`<menu-item
?disabled=${isFetching}
href=${this.createCommandLink('gitlens.ai.generateCommits:home')}
>Generate Commits with AI (Preview)</menu-item
>`,
);
actions.push(
html`<menu-item ?disabled=${isFetching} href=${this.createCommandLink('gitlens.ai.explainWip:home')}
>Explain Working Changes (Preview)</menu-item
Expand Down
Loading