Skip to content

Commit c9623e3

Browse files
[AXON-1488] chore: refactor command usage in rovodev (#1302)
1 parent 1691732 commit c9623e3

File tree

9 files changed

+104
-55
lines changed

9 files changed

+104
-55
lines changed

src/commandContext.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@ export enum CommandContext {
1111
JiraLoginTree = 'atlascode:jiraLoginTreeEnabled',
1212
IsJiraAuthenticated = 'atlascode:isJiraAuthenticated',
1313
IsBBAuthenticated = 'atlascode:isBBAuthenticated',
14-
RovoDevEnabled = 'atlascode:rovoDevEnabled',
15-
RovoDevTerminalEnabled = 'atlascode:rovoDevTerminalEnabled',
1614
BbyEnvironmentActive = 'atlascode:bbyEnvironmentActive',
1715
DebugMode = 'atlascode:debugMode',
1816
UseNewAuthFlow = 'atlascode:useNewAuthFlow',

src/commands.ts

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import { ConfigSection, ConfigSubSection, ConfigV3Section, ConfigV3SubSection }
2727
import { Logger } from './logger';
2828
import { runQuickAuth } from './onboarding/quickFlow';
2929
import { AuthenticationType } from './onboarding/quickFlow/authentication/types';
30+
import { RovodevCommands } from './rovo-dev/api/componentApi';
3031
import { RovoDevProcessManager } from './rovo-dev/rovoDevProcessManager';
3132
import { RovoDevContextItem } from './rovo-dev/rovoDevTypes';
3233
import { openRovoDevConfigFile } from './rovo-dev/rovoDevUtils';
@@ -489,7 +490,7 @@ const buildContext = (editor?: TextEditor, vscodeContext?: ExtensionContext): Ro
489490

490491
export function registerRovoDevCommands(vscodeContext: ExtensionContext) {
491492
vscodeContext.subscriptions.push(
492-
commands.registerCommand(Commands.RovodevAskInteractive, async () => {
493+
commands.registerCommand(RovodevCommands.RovodevAskInteractive, async () => {
493494
const context = buildContext(window.activeTextEditor, vscodeContext);
494495

495496
const prompt = await window.showInputBox({
@@ -502,17 +503,17 @@ export function registerRovoDevCommands(vscodeContext: ExtensionContext) {
502503
}
503504
Container.rovodevWebviewProvider.invokeRovoDevAskCommand(prompt, context);
504505
}),
505-
commands.registerCommand(Commands.RovodevAsk, (prompt: string, context?: RovoDevContextItem[]) => {
506+
commands.registerCommand(RovodevCommands.RovodevAsk, (prompt: string, context?: RovoDevContextItem[]) => {
506507
Container.rovodevWebviewProvider.invokeRovoDevAskCommand(prompt, context);
507508
}),
508-
commands.registerCommand(Commands.RovodevNewSession, () => {
509+
commands.registerCommand(RovodevCommands.RovodevNewSession, () => {
509510
Container.rovodevWebviewProvider.executeNewSession();
510511
}),
511-
commands.registerCommand(Commands.RovodevShowTerminal, () => RovoDevProcessManager.showTerminal()),
512-
commands.registerCommand(Commands.RovodevShareFeedback, () =>
512+
commands.registerCommand(RovodevCommands.RovodevShowTerminal, () => RovoDevProcessManager.showTerminal()),
513+
commands.registerCommand(RovodevCommands.RovodevShareFeedback, () =>
513514
Container.rovodevWebviewProvider.executeTriggerFeedback(),
514515
),
515-
commands.registerCommand(Commands.RovodevAddToContext, async () => {
516+
commands.registerCommand(RovodevCommands.RovodevAddToContext, async () => {
516517
const context = buildContext(window.activeTextEditor, vscodeContext);
517518
if (!context || context.length === 0) {
518519
// Do nothing, this should only have effect in editor context
@@ -523,13 +524,22 @@ export function registerRovoDevCommands(vscodeContext: ExtensionContext) {
523524
Container.rovodevWebviewProvider.addToContext(item);
524525
});
525526
}),
526-
commands.registerCommand(Commands.OpenRovoDevConfig, async () => await openRovoDevConfigFile('config.yml')),
527-
commands.registerCommand(Commands.OpenRovoDevMcpJson, async () => await openRovoDevConfigFile('mcp.json')),
528527
commands.registerCommand(
529-
Commands.OpenRovoDevGlobalMemory,
528+
RovodevCommands.OpenRovoDevConfig,
529+
async () => await openRovoDevConfigFile('config.yml'),
530+
),
531+
commands.registerCommand(
532+
RovodevCommands.OpenRovoDevMcpJson,
533+
async () => await openRovoDevConfigFile('mcp.json'),
534+
),
535+
commands.registerCommand(
536+
RovodevCommands.OpenRovoDevGlobalMemory,
530537
async () => await openRovoDevConfigFile('.agent.md'),
531538
),
532-
commands.registerCommand(Commands.OpenRovoDevLogFile, async () => await openRovoDevConfigFile('rovodev.log')),
539+
commands.registerCommand(
540+
RovodevCommands.OpenRovoDevLogFile,
541+
async () => await openRovoDevConfigFile('rovodev.log'),
542+
),
533543
);
534544
}
535545

src/constants.ts

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -83,19 +83,9 @@ export const enum Commands {
8383
DisableHelpExplorer = 'atlascode.disableHelpExplorer',
8484
CreateNewJql = 'atlascode.jira.createNewJql',
8585
ToDoIssue = 'atlascode.jira.todoIssue',
86-
RovodevAsk = 'atlascode.rovodev.askRovoDev',
87-
RovodevAskInteractive = 'atlascode.rovodev.askInteractive',
88-
RovodevAddToContext = 'atlascode.rovodev.addToContext',
89-
RovodevNewSession = 'atlascode.rovodev.newChatSession',
90-
RovodevShowTerminal = 'atlascode.rovodev.showTerminal',
91-
RovodevShareFeedback = 'atlascode.rovodev.shareFeedback',
9286
InProgressIssue = 'atlascode.jira.inProgressIssue',
9387
DoneIssue = 'atlascode.jira.doneIssue',
9488
ShowOnboardingFlow = 'atlascode.showOnboardingFlow',
95-
OpenRovoDevConfig = 'atlascode.openRovoDevConfig',
96-
OpenRovoDevMcpJson = 'atlascode.openRovoDevMcpJson',
97-
OpenRovoDevGlobalMemory = 'atlascode.openRovoDevGlobalMemory',
98-
OpenRovoDevLogFile = 'atlascode.openRovoDevLogFile',
9989
OpenNativeSettings = 'atlascode.openNativeSettings',
10090
QuickAuth = 'atlascode.rovodev.quickAuth',
10191
JiraLogin = 'atlascode.jira.login',

src/container.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import { Logger } from './logger';
3434
import OnboardingProvider from './onboarding/onboardingProvider';
3535
import { registerQuickAuthCommand } from './onboarding/quickFlow';
3636
import { Pipeline } from './pipelines/model';
37+
import { RovodevCommandContext } from './rovo-dev/api/componentApi';
3738
import { RovoDevCodeActionProvider } from './rovo-dev/rovoDevCodeActionProvider';
3839
import { RovoDevProcessManager } from './rovo-dev/rovoDevProcessManager';
3940
import { RovoDevWebviewProvider } from './rovo-dev/rovoDevWebviewProvider';
@@ -350,7 +351,7 @@ export class Container {
350351
context.subscriptions.push(this._rovodevDisposable);
351352

352353
// this enables the Rovo Dev activity bar
353-
await setCommandContext(CommandContext.RovoDevEnabled, true);
354+
await setCommandContext(RovodevCommandContext.RovoDevEnabled, true);
354355

355356
// only in Boysenberry, we auto-focus the Rovo Dev view
356357
if (this.isBoysenberryMode) {
@@ -397,7 +398,7 @@ export class Container {
397398
this._rovodevDisposable.dispose();
398399
this._rovodevDisposable = undefined;
399400

400-
await setCommandContext(CommandContext.RovoDevEnabled, false);
401+
await setCommandContext(RovodevCommandContext.RovoDevEnabled, false);
401402
await RovoDevProcessManager.deactivateRovoDevProcessManager();
402403
} catch (error) {
403404
RovoDevLogger.error(error, 'Disabling Rovo Dev');

src/rovo-dev/api/componentApi.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/**
2+
* Commmands supported by the rovodev component
3+
*/
4+
export const RovodevCommands = {
5+
RovodevAsk: 'atlascode.rovodev.askRovoDev',
6+
RovodevAskInteractive: 'atlascode.rovodev.askInteractive',
7+
RovodevAddToContext: 'atlascode.rovodev.addToContext',
8+
RovodevNewSession: 'atlascode.rovodev.newChatSession',
9+
RovodevShowTerminal: 'atlascode.rovodev.showTerminal',
10+
RovodevShareFeedback: 'atlascode.rovodev.shareFeedback',
11+
OpenRovoDevConfig: 'atlascode.openRovoDevConfig',
12+
OpenRovoDevMcpJson: 'atlascode.openRovoDevMcpJson',
13+
OpenRovoDevGlobalMemory: 'atlascode.openRovoDevGlobalMemory',
14+
OpenRovoDevLogFile: 'atlascode.openRovoDevLogFile',
15+
} as const;
16+
17+
/**
18+
* Command context releavant to the rovodev component
19+
*/
20+
export const RovodevCommandContext = {
21+
RovoDevEnabled: 'atlascode:rovoDevEnabled',
22+
RovoDevTerminalEnabled: 'atlascode:rovoDevTerminalEnabled',
23+
} as const;
24+
25+
// Type safety in case we need to refer to these elsewhere
26+
export type RovodevCommand = (typeof RovodevCommands)[keyof typeof RovodevCommands];
27+
export type RovodevCommandContextItem = (typeof RovodevCommandContext)[keyof typeof RovodevCommandContext];

src/rovo-dev/api/extensionApi.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
import { isMinimalIssue, MinimalIssue, readSearchResults } from '@atlassianlabs/jira-pi-common-models';
22
import { ValidBasicAuthSiteData } from 'src/atlclients/clientManager';
3+
import { showIssueForURL } from 'src/commands/jira/showIssue';
4+
import { Commands } from 'src/constants';
35
import { Container } from 'src/container';
46
import { SearchJiraHelper } from 'src/views/jira/searchJiraHelper';
7+
import { commands, Uri } from 'vscode';
58

69
import { AuthInfo, DetailedSiteInfo, ProductJira } from './extensionApiTypes';
710

@@ -13,6 +16,10 @@ export class JiraApi {
1316
return Container.siteManager.getSitesAvailable(ProductJira);
1417
};
1518

19+
public showIssue = async (issueURL: string): Promise<void> => {
20+
await showIssueForURL(issueURL);
21+
};
22+
1623
public fetchWorkItems = async (site: DetailedSiteInfo): Promise<MinimalIssue<DetailedSiteInfo>[]> => {
1724
// Fetch from cache first
1825
let assignedIssuesForSite = this.fetchWorkItemsFromCache(site);
@@ -122,5 +129,27 @@ export class ExtensionApi {
122129
},
123130
};
124131

132+
commands = {
133+
openFolder: async (): Promise<void> => {
134+
await commands.executeCommand(Commands.WorkbenchOpenFolder);
135+
},
136+
focusRovodevView: async (): Promise<void> => {
137+
await commands.executeCommand('atlascode.views.rovoDev.webView.focus');
138+
},
139+
showUserAuthentication: async ({ openApiTokenLogin }: { openApiTokenLogin: boolean }) => {
140+
if (openApiTokenLogin) {
141+
await commands.executeCommand(Commands.JiraAPITokenLogin);
142+
} else {
143+
await commands.executeCommand(Commands.ShowJiraAuth);
144+
}
145+
},
146+
showDiff: async (args: { left: Uri; right: Uri; title: string }) => {
147+
await commands.executeCommand('vscode.diff', args.left, args.right, args.title);
148+
},
149+
setCommandContext: async (key: string, value: any) => {
150+
await commands.executeCommand('setContext', key, value);
151+
},
152+
};
153+
125154
public readonly jira = new JiraApi();
126155
}

src/rovo-dev/rovoDevCodeActionProvider.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import path from 'path';
2-
import { Commands } from 'src/constants';
32
import * as vscode from 'vscode';
43

4+
import { RovodevCommands } from './api/componentApi';
55
import { ExtensionApi } from './api/extensionApi';
66

77
export class RovoDevCodeActionProvider implements vscode.CodeActionProvider {
@@ -35,7 +35,7 @@ export class RovoDevCodeActionProvider implements vscode.CodeActionProvider {
3535
{
3636
title: 'Rovo Dev: Add to Context',
3737
command: {
38-
command: Commands.RovodevAddToContext,
38+
command: RovodevCommands.RovodevAddToContext,
3939
title: 'Add to Rovo Dev Context',
4040
},
4141
},
@@ -58,7 +58,7 @@ export class RovoDevCodeActionProvider implements vscode.CodeActionProvider {
5858
: prompt;
5959

6060
action.command = {
61-
command: Commands.RovodevAsk,
61+
command: RovodevCommands.RovodevAsk,
6262
title: 'Ask Rovo Dev',
6363
arguments: [
6464
finalPrompt,

src/rovo-dev/rovoDevWebviewProvider.test.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,13 @@ jest.mock('./api/extensionApi', () => ({
5050
getSites: jest.fn(() => []),
5151
fetchWorkItems: jest.fn(() => Promise.resolve([])),
5252
},
53+
commands: {
54+
openFolder: jest.fn(),
55+
focusRovodevView: jest.fn(),
56+
showUserAuthentication: jest.fn(),
57+
showDiff: jest.fn(),
58+
setCommandContext: jest.fn(),
59+
},
5360
})),
5461
}));
5562

@@ -165,13 +172,6 @@ jest.mock('./util/waitFor', () => ({
165172
safeWaitFor: jest.fn(),
166173
}));
167174

168-
jest.mock('../../src/commandContext', () => ({
169-
setCommandContext: jest.fn(),
170-
CommandContext: {
171-
RovoDevTerminalEnabled: 'rovoDevTerminalEnabled',
172-
},
173-
}));
174-
175175
describe('RovoDevWebviewProvider - Real Implementation Tests', () => {
176176
let provider: RovoDevWebviewProvider;
177177
let mockContext: ExtensionContext;

src/rovo-dev/rovoDevWebviewProvider.ts

Lines changed: 15 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,12 @@
11
import { MinimalIssue } from '@atlassianlabs/jira-pi-common-models';
22
import * as fs from 'fs';
33
import path from 'path';
4-
import { CommandContext, setCommandContext } from 'src/commandContext';
5-
import { showIssueForURL } from 'src/commands/jira/showIssue';
64
import { configuration } from 'src/config/configuration';
75
import { getFsPromise } from 'src/rovo-dev/util/fsPromises';
86
import { safeWaitFor } from 'src/rovo-dev/util/waitFor';
97
import { v4 } from 'uuid';
108
import {
119
CancellationToken,
12-
commands,
1310
ConfigurationChangeEvent,
1411
Disposable,
1512
env,
@@ -26,9 +23,9 @@ import {
2623
workspace,
2724
} from 'vscode';
2825

29-
import { Commands } from '../constants';
3026
import { GitErrorCodes } from '../typings/git';
3127
import { getHtmlForView } from '../webview/common/getHtmlForView';
28+
import { RovodevCommandContext } from './api/componentApi';
3229
import { DetailedSiteInfo, ExtensionApi } from './api/extensionApi';
3330
import { RovoDevApiClient, RovoDevHealthcheckResponse } from './client';
3431
import { RovoDevChatContextProvider } from './rovoDevChatContextProvider';
@@ -435,19 +432,17 @@ export class RovoDevWebviewProvider extends Disposable implements WebviewViewPro
435432
break;
436433

437434
case RovoDevViewResponseType.LaunchJiraAuth:
438-
if (e.openApiTokenLogin) {
439-
await commands.executeCommand(Commands.JiraAPITokenLogin);
440-
} else {
441-
await commands.executeCommand(Commands.ShowJiraAuth);
442-
}
435+
await this.extensionApi.commands.showUserAuthentication({
436+
openApiTokenLogin: !!e.openApiTokenLogin,
437+
});
443438
break;
444439

445440
case RovoDevViewResponseType.OpenFolder:
446-
await commands.executeCommand(Commands.WorkbenchOpenFolder);
441+
await this.extensionApi.commands.openFolder();
447442
break;
448443

449444
case RovoDevViewResponseType.OpenJira:
450-
await showIssueForURL(e.url);
445+
await this.extensionApi.jira.showIssue(e.url);
451446
break;
452447

453448
case RovoDevViewResponseType.McpConsentChoiceSubmit:
@@ -693,12 +688,11 @@ export class RovoDevWebviewProvider extends Disposable implements WebviewViewPro
693688
const resolvedPath = this.makeRelativePathAbsolute(filePath);
694689

695690
if (cachedFilePath && fs.existsSync(cachedFilePath)) {
696-
commands.executeCommand(
697-
'vscode.diff',
698-
Uri.file(cachedFilePath),
699-
Uri.file(resolvedPath),
700-
`${filePath} (Rovo Dev)`,
701-
);
691+
await this.extensionApi.commands.showDiff({
692+
left: Uri.file(cachedFilePath),
693+
right: Uri.file(resolvedPath),
694+
title: `${filePath} (Rovo Dev)`,
695+
});
702696
this._dwellTracker?.startDwellTimer();
703697
} else {
704698
let range: Range | undefined;
@@ -889,7 +883,7 @@ export class RovoDevWebviewProvider extends Disposable implements WebviewViewPro
889883

890884
public async invokeRovoDevAskCommand(prompt: string, context?: RovoDevContextItem[]): Promise<void> {
891885
// Always focus on the specific vscode view, even if disabled (so user can see the login prompt)
892-
commands.executeCommand('atlascode.views.rovoDev.webView.focus');
886+
await this.extensionApi.commands.focusRovodevView();
893887

894888
// Wait for the webview to initialize, up to 5 seconds
895889
const initialized = await safeWaitFor({
@@ -933,7 +927,7 @@ export class RovoDevWebviewProvider extends Disposable implements WebviewViewPro
933927
*/
934928
public async setPromptTextWithFocus(text: string, contextItem?: RovoDevContextItem): Promise<void> {
935929
// Focus and wait for webview to be ready to receive messages
936-
await commands.executeCommand('atlascode.views.rovoDev.webView.focus');
930+
await this.extensionApi.commands.focusRovodevView();
937931

938932
const webview = await safeWaitFor({
939933
condition: (value) => !!value,
@@ -1048,8 +1042,8 @@ export class RovoDevWebviewProvider extends Disposable implements WebviewViewPro
10481042
this.refreshDebugPanel();
10491043

10501044
// enable the 'show terminal' button only when in debugging
1051-
setCommandContext(
1052-
CommandContext.RovoDevTerminalEnabled,
1045+
this.extensionApi.commands.setCommandContext(
1046+
RovodevCommandContext.RovoDevTerminalEnabled,
10531047
!this.isBoysenberry && this.extensionApi.metadata.isDebugging(),
10541048
);
10551049

0 commit comments

Comments
 (0)