Skip to content

Commit 7c0bc13

Browse files
authored
[AXON-494] Implement auto-downloader of Rovo Dev binaries (#712)
1 parent b0aedf5 commit 7c0bc13

16 files changed

+558
-234
lines changed

package-lock.json

Lines changed: 19 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1376,6 +1376,7 @@
13761376
"@speed-highlight/core": "^1.2.7",
13771377
"@vscode/codicons": "^0.0.36",
13781378
"@vscode/webview-ui-toolkit": "^1.4.0",
1379+
"adm-zip": "^0.5.16",
13791380
"awesome-debounce-promise": "^2.1.0",
13801381
"axios": "1.9.0",
13811382
"axios-curlirize": "^2.0.0",
@@ -1441,6 +1442,7 @@
14411442
"@jest/globals": "^30.0.2",
14421443
"@playwright/test": "1.53.0",
14431444
"@testing-library/react": "^12.1.5",
1445+
"@types/adm-zip": "^0.5.7",
14441446
"@types/express": "^5.0.2",
14451447
"@types/git-url-parse": "^9.0.1",
14461448
"@types/jest": "^30.0.0",

src/container.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,11 @@ export class Container {
219219
}),
220220
);
221221
context.subscriptions.push(
222-
(this._rovodevWebviewProvider = new RovoDevWebviewProvider(context.extensionPath, context.globalState)),
222+
(this._rovodevWebviewProvider = new RovoDevWebviewProvider(
223+
context,
224+
context.extensionPath,
225+
context.globalState,
226+
)),
223227
);
224228
this.configureRovodevSettingsCommands(context);
225229
}

src/extension.ts

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ import {
2626
BB_PIPELINES_FILENAME,
2727
} from './pipelines/yaml/pipelinesYamlHelper';
2828
import { registerResources } from './resources';
29-
import { deactivateRovoDevProcessManager, initializeRovoDevProcessManager } from './rovo-dev/rovoDevProcessManager';
29+
import { deactivateRovoDevProcessManager } from './rovo-dev/rovoDevProcessManager';
3030
import { GitExtension } from './typings/git';
3131
import { Experiments, FeatureFlagClient, Features } from './util/featureFlags';
3232
import Performance from './util/perf';
@@ -113,13 +113,7 @@ export async function activate(context: ExtensionContext) {
113113
// icon to appear in the activity bar
114114
activateBitbucketFeatures();
115115
activateYamlFeatures(context);
116-
117-
if (!!process.env.ROVODEV_ENABLED) {
118-
initializeRovoDevProcessManager(context);
119-
}
120-
}
121-
122-
if (!!process.env.ROVODEV_BBY && !!process.env.ROVODEV_ENABLED) {
116+
} else if (!!process.env.ROVODEV_ENABLED) {
123117
commands.executeCommand('workbench.view.extension.atlascode-rovo-dev');
124118
}
125119

src/react/atlascode/rovo-dev/messaging/ChatStream.tsx

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,18 @@
11
import * as React from 'react';
2+
import { RovoDevInitState, State } from 'src/rovo-dev/rovoDevTypes';
23
import { RovoDevProviderMessage, RovoDevProviderMessageType } from 'src/rovo-dev/rovoDevWebviewProviderMessages';
34
import { ConnectionTimeout } from 'src/util/time';
45

56
import { useMessagingApi } from '../../messagingApi';
67
import { ErrorMessageItem, FollowUpActionFooter, OpenFileFunc } from '../common/common';
78
import { PullRequestChatItem, PullRequestForm } from '../create-pr/PullRequestForm';
89
import { RovoDevLanding } from '../rovoDevLanding';
9-
import { State } from '../rovoDevView';
1010
import { RovoDevViewResponse, RovoDevViewResponseType } from '../rovoDevViewMessages';
1111
import { CodePlanButton } from '../technical-plan/CodePlanButton';
1212
import { TechnicalPlanComponent } from '../technical-plan/TechnicalPlanComponent';
1313
import { ToolCallItem } from '../tools/ToolCallItem';
1414
import { ToolReturnParsedItem } from '../tools/ToolReturnItem';
15-
import {
16-
ChatMessage,
17-
DefaultMessage,
18-
MessageBlockDetails,
19-
parseToolReturnMessage,
20-
scrollToEnd,
21-
ToolReturnParseResult,
22-
} from '../utils';
15+
import { ChatMessage, DefaultMessage, MessageBlockDetails, parseToolReturnMessage, scrollToEnd } from '../utils';
2316
import { ChatMessageItem } from './ChatMessageItem';
2417
import { MessageDrawer } from './MessageDrawer';
2518

@@ -35,11 +28,12 @@ interface ChatStreamProps {
3528
messagingApi: ReturnType<
3629
typeof useMessagingApi<RovoDevViewResponse, RovoDevProviderMessage, RovoDevProviderMessage>
3730
>;
38-
modifiedFiles: ToolReturnParseResult[];
3931
pendingToolCall: string;
4032
deepPlanCreated: boolean;
4133
executeCodePlan: () => void;
4234
state: State;
35+
initState: RovoDevInitState;
36+
downloadProgress: [number, number];
4337
onChangesGitPushed: (msg: DefaultMessage, pullRequestCreated: boolean) => void;
4438
onCollapsiblePanelExpanded: () => void;
4539
}
@@ -53,8 +47,9 @@ export const ChatStream: React.FC<ChatStreamProps> = ({
5347
deepPlanCreated,
5448
executeCodePlan,
5549
state,
50+
initState,
51+
downloadProgress,
5652
messagingApi,
57-
modifiedFiles,
5853
onChangesGitPushed,
5954
onCollapsiblePanelExpanded,
6055
}) => {
@@ -249,7 +244,7 @@ export const ChatStream: React.FC<ChatStreamProps> = ({
249244

250245
{pendingToolCall && (
251246
<div style={{ marginBottom: '16px' }}>
252-
<ToolCallItem toolMessage={pendingToolCall} />
247+
<ToolCallItem toolMessage={pendingToolCall} state={initState} downloadProgress={downloadProgress} />
253248
</div>
254249
)}
255250

src/react/atlascode/rovo-dev/prompt-box/prompt-input/PromptInput.test.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { fireEvent, render, screen } from '@testing-library/react';
22
import React from 'react';
3+
import { State } from 'src/rovo-dev/rovoDevTypes';
34

4-
import { State } from '../../rovoDevView';
55
import { PromptInputBox } from './PromptInput';
66

77
describe('PromptInputBox', () => {

src/react/atlascode/rovo-dev/prompt-box/prompt-input/PromptInput.tsx

Lines changed: 69 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,17 @@ import { LoadingButton } from '@atlaskit/button';
22
import SendIcon from '@atlaskit/icon/core/arrow-up';
33
import StopIcon from '@atlaskit/icon/core/video-stop';
44
import React from 'react';
5+
import { State } from 'src/rovo-dev/rovoDevTypes';
56

6-
import { AiGenerativeTextSummaryIcon, CloseIconDeepPlan, State } from '../../rovoDevView';
7+
import { AiGenerativeTextSummaryIcon, CloseIconDeepPlan } from '../../rovoDevView';
78
import {
89
rovoDevDeepPlanStylesSelector,
910
rovoDevPromptButtonStyles,
1011
rovoDevTextareaStyles,
1112
} from '../../rovoDevViewStyles';
1213

1314
interface PromptInputBoxProps {
15+
disabled?: boolean;
1416
state: State;
1517
promptText: string;
1618
onPromptTextChange: (text: string) => void;
@@ -21,7 +23,22 @@ interface PromptInputBoxProps {
2123
sendButtonDisabled?: boolean;
2224
onAddContext: () => void;
2325
}
26+
27+
const TextAreaMessages: Record<State, string> = {
28+
[State.Disabled]: 'Rovo Dev is currently disabled. Please, refer to the error message in chat',
29+
[State.WaitingForPrompt]: 'Type in a question',
30+
[State.NoWorkspaceOpen]: 'Please, open a folder to start a chat session with Rovo Dev',
31+
[State.GeneratingResponse]: 'Generating response...',
32+
[State.CancellingResponse]: 'Cancelling the response...',
33+
[State.ExecutingPlan]: 'Executing the code plan...',
34+
};
35+
36+
const getTextAreaPlaceholder = (state: State) => {
37+
return TextAreaMessages[state];
38+
};
39+
2440
export const PromptInputBox: React.FC<PromptInputBoxProps> = ({
41+
disabled,
2542
state,
2643
promptText,
2744
onPromptTextChange,
@@ -32,13 +49,6 @@ export const PromptInputBox: React.FC<PromptInputBoxProps> = ({
3249
sendButtonDisabled = false,
3350
onAddContext,
3451
}) => {
35-
const TextAreaMessages: Record<State, string> = {
36-
[State.WaitingForPrompt]: 'Type in a question',
37-
[State.GeneratingResponse]: 'Generating response...',
38-
[State.CancellingResponse]: 'Cancelling the response...',
39-
[State.ExecutingPlan]: 'Executing the code plan...',
40-
};
41-
4252
const handleKeyDown = React.useCallback(
4353
(event: React.KeyboardEvent<HTMLTextAreaElement>) => {
4454
if (event.key === 'Enter' && !event.shiftKey && state === State.WaitingForPrompt) {
@@ -48,18 +58,16 @@ export const PromptInputBox: React.FC<PromptInputBoxProps> = ({
4858
},
4959
[state, onSend, promptText],
5060
);
51-
const getTextAreaPlaceholder = () => {
52-
return TextAreaMessages[state] || 'Type in a question';
53-
};
5461

5562
return (
5663
<>
5764
<textarea
5865
style={{ ...{ fieldSizing: 'content' }, ...rovoDevTextareaStyles }}
59-
placeholder={getTextAreaPlaceholder()}
66+
placeholder={getTextAreaPlaceholder(state)}
6067
onChange={(element) => onPromptTextChange(element.target.value)}
6168
onKeyDown={handleKeyDown}
6269
value={promptText}
70+
disabled={disabled}
6371
/>
6472
<div
6573
style={{
@@ -71,54 +79,61 @@ export const PromptInputBox: React.FC<PromptInputBoxProps> = ({
7179
}}
7280
>
7381
{/* Left-side Add Context Button */}
74-
<LoadingButton
75-
style={{
76-
...rovoDevPromptButtonStyles,
77-
}}
78-
spacing="compact"
79-
label="Add context"
80-
iconBefore={<i className="codicon codicon-add" />}
81-
onClick={() => onAddContext()}
82-
/>
83-
<div style={{ display: 'flex', gap: 8 }}>
84-
<LoadingButton
85-
style={{
86-
...rovoDevDeepPlanStylesSelector(isDeepPlanEnabled, state !== State.WaitingForPrompt),
87-
}}
88-
spacing="compact"
89-
label="Enable deep plan"
90-
iconBefore={<AiGenerativeTextSummaryIcon />}
91-
iconAfter={isDeepPlanEnabled ? <CloseIconDeepPlan /> : undefined}
92-
isDisabled={state !== State.WaitingForPrompt}
93-
onClick={() => onDeepPlanToggled()}
94-
>
95-
{isDeepPlanEnabled ? 'Deep plan enabled' : ''}
96-
</LoadingButton>
97-
{state === State.WaitingForPrompt && (
82+
{!disabled && (
83+
<>
9884
<LoadingButton
9985
style={{
10086
...rovoDevPromptButtonStyles,
101-
color: 'var(--vscode-button-foreground) !important',
102-
backgroundColor: 'var(--vscode-button-background)',
10387
}}
10488
spacing="compact"
105-
label="Send prompt"
106-
iconBefore={<SendIcon label="Send prompt" />}
107-
isDisabled={sendButtonDisabled}
108-
onClick={() => onSend(promptText)}
109-
/>
110-
)}
111-
{state !== State.WaitingForPrompt && (
112-
<LoadingButton
113-
style={rovoDevPromptButtonStyles}
114-
spacing="compact"
115-
label="Stop"
116-
iconBefore={<StopIcon label="Stop" />}
117-
isDisabled={state === State.CancellingResponse}
118-
onClick={() => onCancel()}
89+
label="Add context"
90+
iconBefore={<i className="codicon codicon-add" />}
91+
onClick={() => onAddContext()}
11992
/>
120-
)}
121-
</div>
93+
<div style={{ display: 'flex', gap: 8 }}>
94+
<LoadingButton
95+
style={{
96+
...rovoDevDeepPlanStylesSelector(
97+
isDeepPlanEnabled,
98+
state !== State.WaitingForPrompt,
99+
),
100+
}}
101+
spacing="compact"
102+
label="Enable deep plan"
103+
iconBefore={<AiGenerativeTextSummaryIcon />}
104+
iconAfter={isDeepPlanEnabled ? <CloseIconDeepPlan /> : undefined}
105+
isDisabled={state !== State.WaitingForPrompt}
106+
onClick={() => onDeepPlanToggled()}
107+
>
108+
{isDeepPlanEnabled ? 'Deep plan enabled' : ''}
109+
</LoadingButton>
110+
{state === State.WaitingForPrompt && (
111+
<LoadingButton
112+
style={{
113+
...rovoDevPromptButtonStyles,
114+
color: 'var(--vscode-button-foreground) !important',
115+
backgroundColor: 'var(--vscode-button-background)',
116+
}}
117+
spacing="compact"
118+
label="Send prompt"
119+
iconBefore={<SendIcon label="Send prompt" />}
120+
isDisabled={sendButtonDisabled}
121+
onClick={() => onSend(promptText)}
122+
/>
123+
)}
124+
{state !== State.WaitingForPrompt && (
125+
<LoadingButton
126+
style={rovoDevPromptButtonStyles}
127+
spacing="compact"
128+
label="Stop"
129+
iconBefore={<StopIcon label="Stop" />}
130+
isDisabled={state === State.CancellingResponse}
131+
onClick={() => onCancel()}
132+
/>
133+
)}
134+
</div>
135+
</>
136+
)}
122137
</div>
123138
</>
124139
);

0 commit comments

Comments
 (0)