Skip to content

Commit b391e08

Browse files
committed
Explain work in progress (wip)
1 parent 4a2a6c7 commit b391e08

File tree

5 files changed

+100
-0
lines changed

5 files changed

+100
-0
lines changed

contributions.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,10 @@
4949
]
5050
}
5151
},
52+
"gitlens.ai.explainWip": {
53+
"label": "Explain Working Changes (Preview)...",
54+
"commandPalette": "gitlens:enabled && !gitlens:readonly && !gitlens:untrusted && gitlens:gk:organization:ai:enabled"
55+
},
5256
"gitlens.ai.generateChangelog": {
5357
"label": "Generate Changelog (Preview)...",
5458
"commandPalette": "gitlens:enabled && !gitlens:untrusted && gitlens:gk:organization:ai:enabled"

package.json

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6064,6 +6064,11 @@
60646064
"title": "Explain Stash (Preview)...",
60656065
"category": "GitLens"
60666066
},
6067+
{
6068+
"command": "gitlens.ai.explainWip",
6069+
"title": "Explain Working Changes (Preview)...",
6070+
"category": "GitLens"
6071+
},
60676072
{
60686073
"command": "gitlens.ai.generateChangelog",
60696074
"title": "Generate Changelog (Preview)...",
@@ -10388,6 +10393,10 @@
1038810393
"command": "gitlens.ai.explainStash",
1038910394
"when": "gitlens:enabled && !gitlens:readonly && !gitlens:untrusted && gitlens:gk:organization:ai:enabled"
1039010395
},
10396+
{
10397+
"command": "gitlens.ai.explainWip",
10398+
"when": "gitlens:enabled && !gitlens:readonly && !gitlens:untrusted && gitlens:gk:organization:ai:enabled"
10399+
},
1039110400
{
1039210401
"command": "gitlens.ai.generateChangelog",
1039310402
"when": "gitlens:enabled && !gitlens:untrusted && gitlens:gk:organization:ai:enabled"

src/commands.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import './commands/diffWithWorking';
2323
import './commands/externalDiff';
2424
import './commands/explainCommit';
2525
import './commands/explainStash';
26+
import './commands/explainWip';
2627
import './commands/generateChangelog';
2728
import './commands/generateCommitMessage';
2829
import './commands/ghpr/openOrCreateWorktree';

src/commands/explainWip.ts

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
import type { TextEditor, Uri } from 'vscode';
2+
import { ProgressLocation } from 'vscode';
3+
import type { Container } from '../container';
4+
import { GitUri } from '../git/gitUri';
5+
import { uncommitted, uncommittedStaged } from '../git/models/revision';
6+
import { showGenericErrorMessage } from '../messages';
7+
import type { AIExplainSource } from '../plus/ai/aiProviderService';
8+
import { getBestRepositoryOrShowPicker } from '../quickpicks/repositoryPicker';
9+
import { command } from '../system/-webview/command';
10+
import { showMarkdownPreview } from '../system/-webview/markdown';
11+
import { Logger } from '../system/logger';
12+
import { GlCommandBase } from './commandBase';
13+
import { getCommandUri } from './commandBase.utils';
14+
import type { CommandContext } from './commandContext';
15+
16+
export interface ExplainWipCommandArgs {
17+
repoPath?: string | Uri;
18+
staged?: boolean;
19+
source?: AIExplainSource;
20+
}
21+
22+
@command()
23+
export class ExplainWipCommand extends GlCommandBase {
24+
constructor(private readonly container: Container) {
25+
super('gitlens.ai.explainWip');
26+
}
27+
28+
protected override preExecute(context: CommandContext, args?: ExplainWipCommandArgs): Promise<void> {
29+
return this.execute(context.editor, context.uri, args);
30+
}
31+
32+
async execute(editor?: TextEditor, uri?: Uri, args?: ExplainWipCommandArgs): Promise<void> {
33+
args = { ...args };
34+
uri = getCommandUri(uri, editor);
35+
36+
const gitUri = uri != null ? await GitUri.fromUri(uri) : undefined;
37+
38+
const repository = await getBestRepositoryOrShowPicker(
39+
gitUri,
40+
editor,
41+
'Explain Working Changes',
42+
'Choose which repository to explain working changes from',
43+
);
44+
if (repository == null) return;
45+
46+
try {
47+
// Get the diff of working changes
48+
const diffService = repository.git.diff();
49+
if (diffService?.getDiff === undefined) {
50+
void showGenericErrorMessage('Unable to get diff service');
51+
return;
52+
}
53+
54+
const diff = await diffService.getDiff(args?.staged ? uncommittedStaged : uncommitted);
55+
if (!diff?.contents) {
56+
void showGenericErrorMessage('No working changes found to explain');
57+
return;
58+
}
59+
60+
// Call the AI service to explain the changes
61+
const result = await this.container.ai.explainChanges(
62+
{
63+
diff: diff.contents,
64+
message: args?.staged ? 'Staged working changes' : 'Unstaged working changes',
65+
},
66+
args.source ?? { source: 'commandPalette', type: 'wip' },
67+
{
68+
progress: { location: ProgressLocation.Notification, title: 'Explaining working changes...' },
69+
},
70+
);
71+
72+
// Display the result
73+
let content = `# ${args?.staged ? 'Staged' : 'Unstaged'} Working Changes\n`;
74+
if (result != null) {
75+
content += `> Generated by ${result.model.name}\n\n----\n\n${result?.parsed.summary}\n\n${result?.parsed.body}`;
76+
} else {
77+
content += `> No changes found to explain.`;
78+
}
79+
void showMarkdownPreview(content);
80+
} catch (ex) {
81+
Logger.error(ex, 'ExplainWipCommand', 'execute');
82+
void showGenericErrorMessage('Unable to explain working changes');
83+
}
84+
}
85+
}

src/constants.commands.generated.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -615,6 +615,7 @@ export type ContributedPaletteCommands =
615615
| 'gitlens.addAuthors'
616616
| 'gitlens.ai.explainCommit'
617617
| 'gitlens.ai.explainStash'
618+
| 'gitlens.ai.explainWip'
618619
| 'gitlens.ai.generateChangelog'
619620
| 'gitlens.ai.generateCommitMessage'
620621
| 'gitlens.applyPatchFromClipboard'

0 commit comments

Comments
 (0)