Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wait for VSCode Settings Import to finish before proceeding to next step #250

Merged
merged 10 commits into from
Jan 29, 2025
6 changes: 5 additions & 1 deletion .prettierignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
extensions/vscode/continue_rc_schema.json
**/.pearaiignore
CHANGELOG.md
CHANGELOG.md

# temporary for local dev, do not merge with this
*.tsx
*.ts
4 changes: 2 additions & 2 deletions core/protocol/ide.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ import type {
IdeSettings,
IndexTag,
Location,
PearAuth,
Problem,
Range,
RangeInFile,
Thread,
PearAuth,
} from "../index.js";

export type ToIdeFromWebviewOrCoreProtocol = {
Expand Down Expand Up @@ -91,7 +91,7 @@ export type ToIdeFromWebviewOrCoreProtocol = {

// new welcome page
markNewOnboardingComplete: [undefined, void];
importUserSettingsFromVSCode: [undefined, void];
importUserSettingsFromVSCode: [undefined, boolean];
pearWelcomeOpenFolder: [undefined, void];
pearInstallCommandLine: [undefined, void];
installVscodeExtension: [{ extensionId: string }, void];
Expand Down
31 changes: 18 additions & 13 deletions core/protocol/ideWebview.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import { AiderState } from "../../extensions/vscode/src/integrations/aider/types/aiderTypes.js";
import { ToolType, Memory, MemoryChange } from "../../extensions/vscode/src/util/integrationUtils.js";
import {
Memory,
MemoryChange,
ToolType,
} from "../../extensions/vscode/src/util/integrationUtils.js";
import type { RangeInFileWithContents } from "../commands/util.js";
import type { ContextSubmenuItem } from "../index.js";
import { ToIdeFromWebviewOrCoreProtocol } from "./ide.js";
Expand All @@ -19,17 +23,17 @@ export type ToIdeFromWebviewProtocol = ToIdeFromWebviewOrCoreProtocol & {
openUrl: [string, void];
applyToCurrentFile: [{ text: string }, void];
applyWithRelaceHorizontal: [{ contentToApply: string }, void];
acceptRelaceDiff: [{ originalFileUri: string, diffFileUri: string }, void];
rejectRelaceDiff: [{ originalFileUri: string, diffFileUri: string }, void];
createFile: [{ path: string}, void];
acceptRelaceDiff: [{ originalFileUri: string; diffFileUri: string }, void];
rejectRelaceDiff: [{ originalFileUri: string; diffFileUri: string }, void];
createFile: [{ path: string }, void];
showTutorial: [undefined, void];
showFile: [{ filepath: string }, void];
openConfigJson: [undefined, void];
highlightElement: [{elementSelectors: string[]}, void];
unhighlightElement: [{elementSelectors: string[]}, void];
highlightElement: [{ elementSelectors: string[] }, void];
unhighlightElement: [{ elementSelectors: string[] }, void];
perplexityMode: [undefined, void];
addPerplexityContext: [{text: string, language: string}, void]
addPerplexityContextinChat: [{ text: string, language: string }, void];
addPerplexityContext: [{ text: string; language: string }, void];
addPerplexityContextinChat: [{ text: string; language: string }, void];
aiderMode: [undefined, void];
aiderCtrlC: [undefined, void];
sendAiderProcessStateToGUI: [undefined, void];
Expand Down Expand Up @@ -60,7 +64,8 @@ export type ToIdeFromWebviewProtocol = ToIdeFromWebviewOrCoreProtocol & {
completeWelcome: [undefined, void];
openInventoryHome: [undefined, void];
getUrlTitle: [string, string];
pearAIinstallation: [{tools: ToolType[], installExtensions: boolean}, void];
pearAIinstallation: [{ tools: ToolType[] }, void];
importUserSettingsFromVSCode: [undefined, boolean];
"mem0/getMemories": [undefined, Memory[]];
"mem0/updateMemories": [{ changes: MemoryChange[] }, boolean];
};
Expand Down Expand Up @@ -93,7 +98,7 @@ export type ToWebviewFromIdeProtocol = ToWebviewFromIdeOrCoreProtocol & {
viewHistory: [undefined, void];
newSession: [undefined, void];
quickEdit: [undefined, void];
acceptedOrRejectedDiff: [undefined, void]
acceptedOrRejectedDiff: [undefined, void];
setTheme: [{ theme: any }, void];
setThemeType: [{ themeType: string }, void];
setColors: [{ [key: string]: string }, void];
Expand All @@ -102,8 +107,8 @@ export type ToWebviewFromIdeProtocol = ToWebviewFromIdeOrCoreProtocol & {
setupLocalModel: [undefined, void];
incrementFtc: [undefined, void];
openOnboarding: [undefined, void];
addPerplexityContext: [{text: string, language: string}, void]
addPerplexityContextinChat: [{ text: string, language: string }, void];
addPerplexityContext: [{ text: string; language: string }, void];
addPerplexityContextinChat: [{ text: string; language: string }, void];
navigateToCreator: [undefined, void];
navigateToSearch: [undefined, void];
navigateToMem0: [undefined, void];
Expand All @@ -112,5 +117,5 @@ export type ToWebviewFromIdeProtocol = ToWebviewFromIdeOrCoreProtocol & {
navigateToInventoryHome: [undefined, void];
getCurrentTab: [undefined, string];
setAiderProcessStateInGUI: [AiderState, void];
setRelaceDiffState: [{diffVisible: boolean}, void];
setRelaceDiffState: [{ diffVisible: boolean }, void];
};
6 changes: 6 additions & 0 deletions extensions/vscode/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,12 @@
"title": "Toggle PearAI Inventory",
"group": "PearAI"
},
{
"command": "pearai.startOnboarding",
"category": "PearAI Developer",
"title": "Start PearAI Onboarding",
"group": "PearAI"
},
{
"command": "pearai.developer.restFirstLaunch",
"category": "PearAI Developer",
Expand Down
19 changes: 8 additions & 11 deletions extensions/vscode/src/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,20 +22,17 @@ import {
quickPickStatusText,
setupStatusBar,
} from "./autocomplete/statusBar";
import { ContinueGUIWebviewViewProvider, PEAR_OVERLAY_VIEW_ID } from "./ContinueGUIWebviewViewProvider";
import { ContinueGUIWebviewViewProvider, PEAR_CONTINUE_VIEW_ID, PEAR_OVERLAY_VIEW_ID } from "./ContinueGUIWebviewViewProvider";
import { FIRST_LAUNCH_KEY, importUserSettingsFromVSCode, isFirstLaunch } from "./copySettings";
import { DiffManager } from "./diff/horizontal";
import { VerticalPerLineDiffManager } from "./diff/verticalPerLine/manager";
import { aiderCtrlC, aiderResetSession, installAider, sendAiderProcessStateToGUI, uninstallAider } from './integrations/aider/aiderUtil';
import { AiderState } from "./integrations/aider/types/aiderTypes";
import { QuickEdit, QuickEditShowParams } from "./quickEdit/QuickEditQuickPick";
import { Battery } from "./util/battery";
import type { VsCodeWebviewProtocol } from "./webviewProtocol";
import { getExtensionUri } from "./util/vscode";
import { aiderCtrlC, aiderResetSession, openAiderPanel, sendAiderProcessStateToGUI, installAider, uninstallAider } from './integrations/aider/aiderUtil';
import { handlePerplexityMode } from "./integrations/perplexity/perplexity";
import { PEAR_CONTINUE_VIEW_ID } from "./ContinueGUIWebviewViewProvider";
import { handleIntegrationShortcutKey } from "./util/integrationUtils";
import { FIRST_LAUNCH_KEY, importUserSettingsFromVSCode, isFirstLaunch } from "./copySettings";
import { attemptInstallExtension } from "./activation/activate";
import { AiderState } from "./integrations/aider/types/aiderTypes";
import { getExtensionUri } from "./util/vscode";
import type { VsCodeWebviewProtocol } from "./webviewProtocol";


let fullScreenPanel: vscode.WebviewPanel | undefined;
Expand Down Expand Up @@ -260,9 +257,9 @@ const commandsMap: (
if (!isFirstLaunch(extensionContext)) {
vscode.window.showInformationMessage("Welcome back! User settings import is skipped as this is not the first launch.");
console.dir("Extension launch detected as a subsequent launch. Skipping user settings import.");
return;
return true;
}
await importUserSettingsFromVSCode();
return await importUserSettingsFromVSCode();
},
"pearai.welcome.markNewOnboardingComplete": async () => {
await extensionContext.globalState.update(FIRST_LAUNCH_KEY, true);
Expand Down
41 changes: 19 additions & 22 deletions extensions/vscode/src/copySettings.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as vscode from "vscode";
import * as fs from 'fs';
import * as path from 'path';
import * as os from 'os';
import * as path from 'path';
import * as vscode from "vscode";

export const FIRST_LAUNCH_KEY = 'pearai.firstLaunch';
const pearAISettingsDir = path.join(os.homedir(), '.pearai');
Expand Down Expand Up @@ -46,11 +46,11 @@ async function copyVSCodeSettingsToPearAIDir() {
await fs.promises.mkdir(pearAIDevExtensionsDir, { recursive: true });

const itemsToCopy = ['settings.json', 'keybindings.json', 'snippets', 'sync', 'globalStorage/state.vscdb', 'globalStorage/state.vscdb.backup'];

for (const item of itemsToCopy) {
const source = path.join(vscodeSettingsDir, item);
const destination = path.join(pearAIDevSettingsDir, item);

try {
if (await fs.promises.access(source).then(() => true).catch(() => false)) {
const stats = await fs.promises.lstat(source);
Expand All @@ -67,7 +67,7 @@ async function copyVSCodeSettingsToPearAIDir() {

const baseExclusions = new Set([
'pearai.pearai',
'ms-python.vscode-pylance',
'ms-python.vscode-pylance',
'ms-python.python',
'codeium',
'github.copilot',
Expand All @@ -81,7 +81,7 @@ async function copyVSCodeSettingsToPearAIDir() {
baseExclusions.add('ms-vscode-remote.remote-ssh');
baseExclusions.add('ms-vscode-remote.remote-ssh-edit');
}

// Add platform specific exclusions
if (process.platform === 'darwin' && process.arch === 'x64') {
baseExclusions.add('ms-python.vscode-pylance');
Expand All @@ -96,7 +96,7 @@ async function copyVSCodeSettingsToPearAIDir() {
// Add Linux specific exclusions
// if (process.platform === 'linux') {
// }

await copyDirectoryRecursiveSync(vscodeExtensionsDir, pearAIDevExtensionsDir, Array.from(baseExclusions));
}

Expand All @@ -113,15 +113,15 @@ function getVSCodeSettingsDir() {

async function copyDirectoryRecursiveSync(source: string, destination: string, exclusions: string[] = []) {
await fs.promises.mkdir(destination, { recursive: true });

const items = await fs.promises.readdir(source);
for (const item of items) {
const sourcePath = path.join(source, item);
const destinationPath = path.join(destination, item);

const shouldExclude = exclusions.some(exclusion =>
sourcePath.toLowerCase().includes(exclusion.toLowerCase())

);

if (!shouldExclude) {
Expand All @@ -138,27 +138,24 @@ async function copyDirectoryRecursiveSync(source: string, destination: string, e

export async function importUserSettingsFromVSCode() {
try {
await new Promise(resolve => setTimeout(resolve, 3000));

vscode.window.showInformationMessage('Copying your current VSCode settings and extensions over to PearAI!');
await copyVSCodeSettingsToPearAIDir();

vscode.window.showInformationMessage(
'Your VSCode settings and extensions have been transferred over to PearAI! You may need to restart your editor for the changes to take effect.',
'Ok'
);
} catch (error) {
await Promise.all([
new Promise((resolve) => setTimeout(resolve, 1000)), // Take at least one second
copyVSCodeSettingsToPearAIDir(),
]);
return true;
} catch (error) {
vscode.window.showErrorMessage(`Failed to copy settings: ${error}`);
return false;
}
}
}

export async function markCreatorOnboardingCompleteFileBased() {
try {
await new Promise(resolve => setTimeout(resolve, 3000));

const flagFile = firstPearAICreatorLaunchFlag;
const productName = 'PearAI Creator';

const exists = await fs.promises.access(flagFile).then(() => true).catch(() => false);
if (!exists) {
await fs.promises.writeFile(flagFile, `This is the first launch flag file for ${productName}`);
Expand Down
32 changes: 17 additions & 15 deletions extensions/vscode/src/extension/VsCodeMessenger.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Note: This file has been modified significantly from its original contents. New commands have been added, and there has been renaming from Continue to PearAI. pearai-submodule is a fork of Continue (https://github.com/continuedev/continue).

import { ConfigHandler } from "core/config/ConfigHandler";
import PearAIServer from "core/llm/llms/PearAIServer";
import {
FromCoreProtocol,
FromWebviewProtocol,
Expand All @@ -18,22 +19,19 @@ import { getConfigJsonPath } from "core/util/paths";
import * as fs from "node:fs";
import * as path from "node:path";
import * as vscode from "vscode";
import { attemptInstallExtension, attemptUninstallExtension, isVSCodeExtensionInstalled } from "../activation/activate";
import { VerticalPerLineDiffManager } from "../diff/verticalPerLine/manager";
import { VsCodeIde } from "../ideProtocol";
import { checkAiderInstallation } from "../integrations/aider/aiderUtil";
import { getMem0Memories, updateMem0Memories } from "../integrations/mem0/mem0Service";
import { getFastApplyChangesWithRelace } from "../integrations/relace/relace";
import {
getControlPlaneSessionInfo,
WorkOsAuthProvider,
} from "../stubs/WorkOsAuthProvider";
import { extractCodeFromMarkdown, TOOL_COMMANDS, ToolType } from "../util/integrationUtils";
import { getExtensionUri } from "../util/vscode";
import { VsCodeWebviewProtocol } from "../webviewProtocol";
import { attemptInstallExtension, attemptUninstallExtension, isVSCodeExtensionInstalled } from "../activation/activate";
import { checkAiderInstallation } from "../integrations/aider/aiderUtil";
import { getMem0Memories, updateMem0Memories } from "../integrations/mem0/mem0Service";
import { TOOL_COMMANDS, ToolType, extractCodeFromMarkdown } from "../util/integrationUtils";
import PearAIServer from "core/llm/llms/PearAIServer";
import { getFastApplyChangesWithRelace } from "../integrations/relace/relace";
import { RelaceDiffManager } from "../integrations/relace/relaceDiffManager";
import { getMarkdownLanguageTagForFile } from "core/util";

/**
* A shared messenger class between Core and Webview
Expand Down Expand Up @@ -106,8 +104,15 @@ export class VsCodeMessenger {
this.onWebview("unlockOverlay", (msg) => {
vscode.commands.executeCommand("pearai.unlockOverlay");
});
this.onWebview("importUserSettingsFromVSCode", (msg) => {
vscode.commands.executeCommand("pearai.welcome.importUserSettingsFromVSCode");
this.onWebview("importUserSettingsFromVSCode", async (msg) => {
try {
return await vscode.commands.executeCommand(
"pearai.welcome.importUserSettingsFromVSCode",
);
} catch (error) {
console.log("importUserSettingsFromVSCode rejectionReason", error);
return false;
}
});
this.onWebview("installVscodeExtension", (msg) => {
attemptInstallExtension(msg.data.extensionId);
Expand All @@ -131,7 +136,7 @@ export class VsCodeMessenger {

const memories = await getMem0Memories(PearAIServer._getRepoId());
return memories;
});
});
this.onWebview("mem0/updateMemories", async (msg) => {
const response = await updateMem0Memories(PearAIServer._getRepoId(), msg.data.changes);
return response;
Expand Down Expand Up @@ -183,10 +188,7 @@ export class VsCodeMessenger {
vscode.commands.executeCommand("pearai.toggleInventoryHome");
});
this.onWebview("pearAIinstallation", (msg) => {
const { tools, installExtensions } = msg.data;
if (installExtensions) {
vscode.commands.executeCommand("pearai.welcome.importUserSettingsFromVSCode");
}
const { tools } = msg.data;
if (tools) {
tools.forEach((tool: ToolType) => {
const toolCommand = TOOL_COMMANDS[tool];
Expand Down
1 change: 0 additions & 1 deletion gui/src/pages/gui.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,6 @@ function GUI() {
useWebviewListener("restFirstLaunchInGUI", async () => {
setLocalStorage("showTutorialCard", true);
localStorage.removeItem("onboardingSelectedTools");
localStorage.removeItem("importUserSettingsFromVSCode");
dispatch(setShowInteractiveContinueTutorial(true));
});

Expand Down
7 changes: 2 additions & 5 deletions gui/src/pages/welcome/FinalStep.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,16 @@
"use client";

import { Button } from "@/components/ui/button";
import { useContext, useEffect } from "react";
import { IdeMessengerContext } from "@/context/IdeMessenger";
import { FolderOpen } from "lucide-react";
import { useNavigate } from "react-router-dom";
import { useContext, useEffect } from "react";

export default function FinalStep({ onNext }: { onNext: () => void }) {

const navigate = useNavigate();
const selectedTools = JSON.parse(localStorage.getItem('onboardingSelectedTools'));
const installExtensions = localStorage.getItem('importUserSettingsFromVSCode') === 'true';

const initiateInstallations = () => {
ideMessenger.post("pearAIinstallation", {tools: selectedTools, installExtensions: installExtensions})
ideMessenger.post("pearAIinstallation", {tools: selectedTools});
ideMessenger.post("markNewOnboardingComplete", undefined);
};

Expand Down
Loading
Loading