Skip to content
Open
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
21 changes: 21 additions & 0 deletions src/webviews/copilotOnRails/extension/autopilot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ const MAX_REQUESTS_KEY = 'maxRequests';

/** Workspace request budget used for scaffolding runs. */
export const WORKSPACE_MAX_REQUESTS = 9999;
const PERMISSIONS_SECTION = 'chat.permissions';
const PERMISSIONS_KEY = 'default';

/**
* Maximum wall-clock duration an autopilot run may keep global auto-approve on.
Expand All @@ -36,6 +38,7 @@ export const AUTOPILOT_QUERY_MARKER = '[AUTOPILOT MODE]';
/** globalState keys used to survive window reloads mid-run. */
const STATE_ACTIVE = 'azureResourceGroups.autopilot.active';
const STATE_PRIOR_VALUE = 'azureResourceGroups.autopilot.priorAutoApprove';
const STATE_PRIOR_PERMISSION_LEVEL = 'azureResourceGroups.autopilot.priorPermissionLevel';
/** Epoch ms after which an active run is considered stale and auto-restored. */
const STATE_DEADLINE = 'azureResourceGroups.autopilot.deadline';

Expand Down Expand Up @@ -82,6 +85,17 @@ export async function raiseWorkspaceMaxRequests(): Promise<void> {
}
}

function getPermissionLevelValue(): unknown {
const config = vscode.workspace.getConfiguration(PERMISSIONS_SECTION);
const inspected = config.inspect(PERMISSIONS_KEY);
return inspected?.globalValue;
}

async function setPermissionLevelValue(value: unknown): Promise<void> {
const config = vscode.workspace.getConfiguration(PERMISSIONS_SECTION);
await config.update(PERMISSIONS_KEY, value, vscode.ConfigurationTarget.Global);
}

function showStatusBarItem(): void {
if (!statusBarItem) {
statusBarItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left, 100);
Expand Down Expand Up @@ -160,13 +174,15 @@ export async function enableAutopilot(context: vscode.ExtensionContext): Promise
// Don't clobber a previously-saved prior value if autopilot is already on.
if (context.globalState.get<boolean>(STATE_ACTIVE) !== true) {
await context.globalState.update(STATE_PRIOR_VALUE, getAutoApproveValue() ?? null);
await context.globalState.update(STATE_PRIOR_PERMISSION_LEVEL, getPermissionLevelValue() ?? null);
}
const deadline = Date.now() + MAX_RUN_DURATION_MS;
await context.globalState.update(STATE_ACTIVE, true);
await context.globalState.update(STATE_DEADLINE, deadline);

await setAutoApproveValue(true);
await raiseWorkspaceMaxRequests();
await setPermissionLevelValue('autopilot');
armAutopilot(deadline);
}

Expand All @@ -186,8 +202,13 @@ export async function disableAutopilot(): Promise<void> {
const prior = context.globalState.get<unknown>(STATE_PRIOR_VALUE);
// `null` means there was no explicit global value, so clear it.
await setAutoApproveValue(prior === null ? undefined : prior);

const priorPermission = context.globalState.get<unknown>(STATE_PRIOR_PERMISSION_LEVEL);
await setPermissionLevelValue(priorPermission === null ? undefined : priorPermission);

await context.globalState.update(STATE_ACTIVE, false);
await context.globalState.update(STATE_PRIOR_VALUE, undefined);
await context.globalState.update(STATE_PRIOR_PERMISSION_LEVEL, undefined);
await context.globalState.update(STATE_DEADLINE, undefined);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

import * as vscode from "vscode";
import { type LocalDevNextStepsViewConfiguration } from "../views/utils/viewConfigTypes";
import { disableAutopilot } from "./autopilot";
import { LocalDevNextStepsViewController } from "./controllers/LocalDevNextStepsViewController";
import { closeLoadingView } from "./openLoadingView";

Expand All @@ -18,6 +19,8 @@ let controller: LocalDevNextStepsViewController | undefined;
* whether `api-test-collections/` contains any files in the workspace.
*/
export async function openLocalDevNextStepsView(hasApiTests?: boolean): Promise<void> {
await disableAutopilot();

let apiTestsDetected = !!hasApiTests;
if (!apiTestsDetected) {
const results = await vscode.workspace.findFiles('api-test-collections/**/*', undefined, 1);
Expand Down
6 changes: 4 additions & 2 deletions src/webviews/copilotOnRails/views/LocalPlanView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -190,8 +190,10 @@ export const LocalPlanView = (): JSX.Element => {
);

const isAlreadyApproved = useMemo(() => {
const s = plan?.status?.trim().toLowerCase();
return s === "approved";
const s = plan?.status?.trim().toLowerCase().replace(/[*_~`]/g, '');
if (!s) { return false; }
const unapprovedStatuses = new Set(['planning', 'unknown', 'draft', 'awaiting approval', 'new']);
return !unapprovedStatuses.has(s);
}, [plan?.status]);

useEffect(() => {
Expand Down
Loading