From 9619796bc2a8392f1fa657a7091abbd29e130efd Mon Sep 17 00:00:00 2001 From: Himanshu Date: Tue, 28 Jan 2025 22:23:10 +0530 Subject: [PATCH 01/11] add pearai provider --- .gitignore | 2 + src/api/index.ts | 3 + src/api/providers/pearai.ts | 19 ++++++ src/core/webview/ClineProvider.ts | 25 ++++++++ src/shared/api.ts | 5 ++ .../src/components/settings/ApiOptions.tsx | 62 ++++++++++++++++++- 6 files changed, 114 insertions(+), 2 deletions(-) create mode 100644 src/api/providers/pearai.ts diff --git a/.gitignore b/.gitignore index b508d9dc6ee..72e8f2f26f0 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,5 @@ roo-cline-*.vsix # Test environment .test_env .vscode-test/ +.aider* +.env diff --git a/src/api/index.ts b/src/api/index.ts index 641c50d719b..704cb97d831 100644 --- a/src/api/index.ts +++ b/src/api/index.ts @@ -14,6 +14,7 @@ import { DeepSeekHandler } from "./providers/deepseek" import { MistralHandler } from "./providers/mistral" import { VsCodeLmHandler } from "./providers/vscode-lm" import { ApiStream } from "./transform/stream" +import { PearAiHandler } from "./providers/pearai" export interface SingleCompletionHandler { completePrompt(prompt: string): Promise @@ -53,6 +54,8 @@ export function buildApiHandler(configuration: ApiConfiguration): ApiHandler { return new VsCodeLmHandler(options) case "mistral": return new MistralHandler(options) + case "pearai": + return new PearAiHandler(options) default: return new AnthropicHandler(options) } diff --git a/src/api/providers/pearai.ts b/src/api/providers/pearai.ts new file mode 100644 index 00000000000..6b39106eb2e --- /dev/null +++ b/src/api/providers/pearai.ts @@ -0,0 +1,19 @@ +import { OpenAiHandler } from "./openai" +import { ApiHandlerOptions } from "../../shared/api" + +export class PearAiHandler extends OpenAiHandler { + constructor(options: ApiHandlerOptions) { + if (!options.pearaiApiKey) { + throw new Error("PearAI API key is required. Please provide it in the settings.") + } + super({ + ...options, + // Map PearAI specific options to OpenAI options for compatibility + openAiApiKey: options.pearaiApiKey, + openAiBaseUrl: + options.pearaiBaseUrl ?? + "https://stingray-app-gb2an.ondigitalocean.app/pearai-server-api2/integrations/cline", + openAiStreamingEnabled: true, + }) + } +} diff --git a/src/core/webview/ClineProvider.ts b/src/core/webview/ClineProvider.ts index d2db67ff4b9..b423bdb3820 100644 --- a/src/core/webview/ClineProvider.ts +++ b/src/core/webview/ClineProvider.ts @@ -63,6 +63,7 @@ type SecretKey = | "openAiNativeApiKey" | "deepSeekApiKey" | "mistralApiKey" + | "pearaiApiKey" type GlobalStateKey = | "apiProvider" | "apiModelId" @@ -97,6 +98,10 @@ type GlobalStateKey = | "openRouterModelId" | "openRouterModelInfo" | "openRouterBaseUrl" + | "pearaiModelId" + | "pearaiModelInfo" + | "pearaiBaseUrl" + | "pearaiApiKey" | "openRouterUseMiddleOutTransform" | "allowedCommands" | "soundEnabled" @@ -1363,6 +1368,10 @@ export class ClineProvider implements vscode.WebviewViewProvider { openRouterUseMiddleOutTransform, vsCodeLmModelSelector, mistralApiKey, + pearaiApiKey, + pearaiBaseUrl, + pearaiModelId, + pearaiModelInfo, } = apiConfiguration await this.updateGlobalState("apiProvider", apiProvider) await this.updateGlobalState("apiModelId", apiModelId) @@ -1401,6 +1410,10 @@ export class ClineProvider implements vscode.WebviewViewProvider { await this.updateGlobalState("openRouterUseMiddleOutTransform", openRouterUseMiddleOutTransform) await this.updateGlobalState("vsCodeLmModelSelector", vsCodeLmModelSelector) await this.storeSecret("mistralApiKey", mistralApiKey) + await this.updateGlobalState("pearaiModelId", pearaiModelId) + await this.updateGlobalState("pearaiModelInfo", pearaiModelInfo) + await this.storeSecret("pearaiApiKey", pearaiApiKey) + await this.updateGlobalState("pearaiBaseUrl", pearaiBaseUrl) if (this.cline) { this.cline.api = buildApiHandler(apiConfiguration) } @@ -2019,6 +2032,10 @@ export class ClineProvider implements vscode.WebviewViewProvider { openAiNativeApiKey, deepSeekApiKey, mistralApiKey, + pearaiApiKey, + pearaiBaseUrl, + pearaiModelId, + pearaiModelInfo, azureApiVersion, openAiStreamingEnabled, openRouterModelId, @@ -2089,6 +2106,10 @@ export class ClineProvider implements vscode.WebviewViewProvider { this.getSecret("openAiNativeApiKey") as Promise, this.getSecret("deepSeekApiKey") as Promise, this.getSecret("mistralApiKey") as Promise, + this.getSecret("pearaiApiKey") as Promise, + this.getGlobalState("pearaiBaseUrl") as Promise, + this.getGlobalState("pearaiModelId") as Promise, + this.getGlobalState("pearaiModelInfo") as Promise, this.getGlobalState("azureApiVersion") as Promise, this.getGlobalState("openAiStreamingEnabled") as Promise, this.getGlobalState("openRouterModelId") as Promise, @@ -2176,6 +2197,10 @@ export class ClineProvider implements vscode.WebviewViewProvider { openAiNativeApiKey, deepSeekApiKey, mistralApiKey, + pearaiApiKey, + pearaiBaseUrl, + pearaiModelId, + pearaiModelInfo, azureApiVersion, openAiStreamingEnabled, openRouterModelId, diff --git a/src/shared/api.ts b/src/shared/api.ts index 950b94b051d..81617d39503 100644 --- a/src/shared/api.ts +++ b/src/shared/api.ts @@ -14,6 +14,7 @@ export type ApiProvider = | "deepseek" | "vscode-lm" | "mistral" + | "pearai" export interface ApiHandlerOptions { apiModelId?: string @@ -57,6 +58,10 @@ export interface ApiHandlerOptions { deepSeekBaseUrl?: string deepSeekApiKey?: string includeMaxTokens?: boolean + pearaiApiKey?: string + pearaiBaseUrl?: string + pearaiModelId?: string + pearaiModelInfo?: ModelInfo } export type ApiConfiguration = ApiHandlerOptions & { diff --git a/webview-ui/src/components/settings/ApiOptions.tsx b/webview-ui/src/components/settings/ApiOptions.tsx index 1be00c74e14..73551bcfb75 100644 --- a/webview-ui/src/components/settings/ApiOptions.tsx +++ b/webview-ui/src/components/settings/ApiOptions.tsx @@ -1,6 +1,12 @@ import { Checkbox, Dropdown, Pane } from "vscrui" import type { DropdownOption } from "vscrui" -import { VSCodeLink, VSCodeRadio, VSCodeRadioGroup, VSCodeTextField } from "@vscode/webview-ui-toolkit/react" +import { + VSCodeButton, + VSCodeLink, + VSCodeRadio, + VSCodeRadioGroup, + VSCodeTextField, +} from "@vscode/webview-ui-toolkit/react" import { Fragment, memo, useCallback, useEffect, useMemo, useState } from "react" import { useEvent, useInterval } from "react-use" import { @@ -39,6 +45,8 @@ import OpenRouterModelPicker, { import OpenAiModelPicker from "./OpenAiModelPicker" import GlamaModelPicker from "./GlamaModelPicker" +const PEARAI_DEFAULT_URL = "https://stingray-app-gb2an.ondigitalocean.app/pearai-server-api2/integrations/cline" + interface ApiOptionsProps { apiErrorMessage?: string modelIdErrorMessage?: string @@ -52,6 +60,7 @@ const ApiOptions = ({ apiErrorMessage, modelIdErrorMessage }: ApiOptionsProps) = const [anthropicBaseUrlSelected, setAnthropicBaseUrlSelected] = useState(!!apiConfiguration?.anthropicBaseUrl) const [azureApiVersionSelected, setAzureApiVersionSelected] = useState(!!apiConfiguration?.azureApiVersion) const [openRouterBaseUrlSelected, setOpenRouterBaseUrlSelected] = useState(!!apiConfiguration?.openRouterBaseUrl) + const [pearaiBaseUrlSelected, setPearaiBaseUrlSelected] = useState(!!apiConfiguration?.pearaiBaseUrl) const [isDescriptionExpanded, setIsDescriptionExpanded] = useState(false) const { selectedProvider, selectedModelId, selectedModelInfo } = useMemo(() => { @@ -134,6 +143,7 @@ const ApiOptions = ({ apiErrorMessage, modelIdErrorMessage }: ApiOptionsProps) = }} style={{ minWidth: 130, position: "relative", zIndex: OPENROUTER_MODEL_PICKER_Z_INDEX + 1 }} options={[ + { value: "pearai", label: "PearAI" }, { value: "openrouter", label: "OpenRouter" }, { value: "anthropic", label: "Anthropic" }, { value: "gemini", label: "Google Gemini" }, @@ -151,6 +161,47 @@ const ApiOptions = ({ apiErrorMessage, modelIdErrorMessage }: ApiOptionsProps) = /> + {selectedProvider === "pearai" && ( +
+ + PearAI API Key + + + Base URL + + {apiConfiguration?.pearaiBaseUrl && apiConfiguration.pearaiBaseUrl !== PEARAI_DEFAULT_URL && ( + { + handleInputChange("pearaiBaseUrl")({ + target: { + value: PEARAI_DEFAULT_URL, + }, + }) + }}> + Reset to default URL + + )} +

+ This key is stored locally and only used to make API requests from this extension. +

+
+ )} + {selectedProvider === "anthropic" && (
)} @@ -1607,7 +1583,7 @@ export function normalizeApiConfiguration(apiConfiguration?: ApiConfiguration) { case "pearai": return { selectedProvider: provider, - selectedModelId: apiConfiguration?.pearaiModelId || "", + selectedModelId: apiConfiguration?.pearaiModelId || "pearai_model", selectedModelInfo: apiConfiguration?.pearaiModelInfo || openAiModelInfoSaneDefaults, } default: From 7e0acff9334d169f08e2be47fec16f4a7965c8b1 Mon Sep 17 00:00:00 2001 From: nang-dev Date: Tue, 28 Jan 2025 17:52:12 -0500 Subject: [PATCH 03/11] Added pearai api config --- src/shared/checkExistApiConfig.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/shared/checkExistApiConfig.ts b/src/shared/checkExistApiConfig.ts index 8cb8055cc84..2b850e7db39 100644 --- a/src/shared/checkExistApiConfig.ts +++ b/src/shared/checkExistApiConfig.ts @@ -4,6 +4,7 @@ export function checkExistKey(config: ApiConfiguration | undefined) { return config ? [ config.apiKey, + config.pearaiApiKey, config.glamaApiKey, config.openRouterApiKey, config.awsRegion, From fe68b50ec3a8b1153a4a8c234d221a3437ff71cd Mon Sep 17 00:00:00 2001 From: nang-dev Date: Tue, 28 Jan 2025 18:25:01 -0500 Subject: [PATCH 04/11] Added pearai welcome default --- src/core/webview/ClineProvider.ts | 2 +- .../src/components/welcome/WelcomeView.tsx | 29 +++++++------------ 2 files changed, 11 insertions(+), 20 deletions(-) diff --git a/src/core/webview/ClineProvider.ts b/src/core/webview/ClineProvider.ts index 647db94f620..a5bb874fa11 100644 --- a/src/core/webview/ClineProvider.ts +++ b/src/core/webview/ClineProvider.ts @@ -1327,7 +1327,7 @@ export class ClineProvider implements vscode.WebviewViewProvider { // Update mode's default config const { mode } = await this.getState() if (mode) { - const currentApiConfigName = await this.getGlobalState("currentApiConfigName") + const currentApiConfigName = (await this.getGlobalState("currentApiConfigName")) ?? "default" const listApiConfig = await this.configManager.listConfig() const config = listApiConfig?.find((c) => c.name === currentApiConfigName) if (config?.id) { diff --git a/webview-ui/src/components/welcome/WelcomeView.tsx b/webview-ui/src/components/welcome/WelcomeView.tsx index 3e3bbd7cd17..1af25a14c8d 100644 --- a/webview-ui/src/components/welcome/WelcomeView.tsx +++ b/webview-ui/src/components/welcome/WelcomeView.tsx @@ -1,28 +1,22 @@ import { VSCodeButton } from "@vscode/webview-ui-toolkit/react" -import { useEffect, useState } from "react" import { useExtensionState } from "../../context/ExtensionStateContext" -import { validateApiConfiguration } from "../../utils/validate" import { vscode } from "../../utils/vscode" -import ApiOptions from "../settings/ApiOptions" const WelcomeView = () => { - const { apiConfiguration } = useExtensionState() - - const [apiErrorMessage, setApiErrorMessage] = useState(undefined) - - const disableLetsGoButton = apiErrorMessage != null - const handleSubmit = () => { - vscode.postMessage({ type: "apiConfiguration", apiConfiguration }) + vscode.postMessage({ + type: "apiConfiguration", + apiConfiguration: { + apiProvider: "pearai", + pearaiApiKey: "temp", // TODO: Change this to use api-key + pearaiBaseUrl: "http://localhost:8000/integrations/cline", + }, + }) } - useEffect(() => { - setApiErrorMessage(validateApiConfiguration(apiConfiguration)) - }, [apiConfiguration]) - return (
-

Hi, I'm Roo!

+

Welcome to PearAI's Coding Agent (Powered by Roo Code / Cline)!

I can do all kinds of tasks thanks to the latest breakthroughs in agentic coding capabilities and access to tools that let me create & edit files, explore complex projects, use the browser, and execute @@ -30,11 +24,8 @@ const WelcomeView = () => { my own capabilities.

- To get started, this extension needs an API provider. -
- - + Let's go!
From eba3d14b7ea39f007f660968b09100c8ffc25d4f Mon Sep 17 00:00:00 2001 From: nang-dev Date: Tue, 28 Jan 2025 20:22:36 -0500 Subject: [PATCH 05/11] Added pearai with anthropic --- src/api/providers/pearai.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/api/providers/pearai.ts b/src/api/providers/pearai.ts index 09b9bed4720..0931f7fe265 100644 --- a/src/api/providers/pearai.ts +++ b/src/api/providers/pearai.ts @@ -1,7 +1,8 @@ import { OpenAiHandler } from "./openai" import { ApiHandlerOptions, PEARAI_URL } from "../../shared/api" +import { AnthropicHandler } from "./anthropic" -export class PearAiHandler extends OpenAiHandler { +export class PearAiHandler extends AnthropicHandler { constructor(options: ApiHandlerOptions) { if (!options.pearaiApiKey) { throw new Error("PearAI API key not found. Please login to PearAI.") From fada5e2a930c05dbbf4890092c01667bbe0a7d4f Mon Sep 17 00:00:00 2001 From: Nang Date: Wed, 29 Jan 2025 11:43:58 -0500 Subject: [PATCH 06/11] Added working anthropic server --- src/api/providers/anthropic.ts | 5 ++++- src/api/providers/pearai.ts | 6 ++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/api/providers/anthropic.ts b/src/api/providers/anthropic.ts index e65b82ddef5..ac976cad956 100644 --- a/src/api/providers/anthropic.ts +++ b/src/api/providers/anthropic.ts @@ -83,7 +83,10 @@ export class AnthropicHandler implements ApiHandler, SingleCompletionHandler { case "claude-3-opus-20240229": case "claude-3-haiku-20240307": return { - headers: { "anthropic-beta": "prompt-caching-2024-07-31" }, + headers: { + "anthropic-beta": "prompt-caching-2024-07-31", + "authorization": `Bearer ${this.options.apiKey}`, + }, } default: return undefined diff --git a/src/api/providers/pearai.ts b/src/api/providers/pearai.ts index 0931f7fe265..9fe9e48ff85 100644 --- a/src/api/providers/pearai.ts +++ b/src/api/providers/pearai.ts @@ -9,10 +9,8 @@ export class PearAiHandler extends AnthropicHandler { } super({ ...options, - // Map PearAI specific options to OpenAI options for compatibility - openAiApiKey: options.pearaiApiKey, - openAiBaseUrl: PEARAI_URL, - openAiStreamingEnabled: true, + apiKey: options.pearaiApiKey, + anthropicBaseUrl: PEARAI_URL, }) } } From b00d1ea504dcc6ae9d6e07a0b10bec143987b6ab Mon Sep 17 00:00:00 2001 From: nang-dev Date: Thu, 30 Jan 2025 20:50:42 -0500 Subject: [PATCH 07/11] Added login logout p2p call working --- package-lock.json | 4 +- package.json | 10 ++--- src/core/webview/ClineProvider.ts | 27 +++++++----- src/extension.ts | 17 +++++++ src/shared/ExtensionMessage.ts | 1 + src/shared/WebviewMessage.ts | 1 + src/shared/checkExistApiConfig.ts | 2 +- .../src/components/settings/ApiOptions.tsx | 44 ++++++++++++------- .../src/components/welcome/WelcomeView.tsx | 14 ++---- 9 files changed, 77 insertions(+), 43 deletions(-) diff --git a/package-lock.json b/package-lock.json index bb49b3942db..3cb6e115cda 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,11 +1,11 @@ { - "name": "roo-cline", + "name": "pearai-roo-cline", "version": "3.3.4", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "roo-cline", + "name": "pearai-roo-cline", "version": "3.3.4", "dependencies": { "@anthropic-ai/bedrock-sdk": "^0.10.2", diff --git a/package.json b/package.json index 6b87a6d5077..f3b9db2bba3 100644 --- a/package.json +++ b/package.json @@ -1,8 +1,8 @@ { - "name": "roo-cline", - "displayName": "Roo Code (prev. Roo Cline)", - "description": "A VS Code plugin that enhances coding with AI-powered automation, multi-model support, and experimental features.", - "publisher": "RooVeterinaryInc", + "name": "pearai-roo-cline", + "displayName": "PearAI Roo Code / Cline", + "description": "PearAI's integration of Roo Code / Cline, a coding agent.", + "publisher": "PearAI", "version": "3.3.4", "icon": "assets/icons/rocket.png", "galleryBanner": { @@ -13,7 +13,7 @@ "vscode": "^1.84.0" }, "author": { - "name": "Roo Vet" + "name": "PearAI" }, "repository": { "type": "git", diff --git a/src/core/webview/ClineProvider.ts b/src/core/webview/ClineProvider.ts index a5bb874fa11..f6ac11cf32b 100644 --- a/src/core/webview/ClineProvider.ts +++ b/src/core/webview/ClineProvider.ts @@ -45,9 +45,6 @@ import { CustomSupportPrompts, supportPrompt } from "../../shared/support-prompt import { ACTION_NAMES } from "../CodeActionProvider" -// Todo: Remove -const PEARAI_TOKEN = "temp" - /* https://github.com/microsoft/vscode-webview-ui-toolkit-samples/blob/main/default/weather-webview/src/providers/WeatherViewProvider.ts @@ -66,7 +63,8 @@ type SecretKey = | "openAiNativeApiKey" | "deepSeekApiKey" | "mistralApiKey" - | "pearaiApiKey" + | "pearai-token" + | "pearai-refresh" // Array of custom modes type GlobalStateKey = | "apiProvider" | "apiModelId" @@ -130,8 +128,6 @@ type GlobalStateKey = | "experiments" // Map of experiment IDs to their enabled state | "autoApprovalEnabled" | "customModes" - | "pearai-token" - | "pearai-refresh" // Array of custom modes export const GlobalFileNames = { apiConversationHistory: "api_conversation_history.json", @@ -1278,6 +1274,19 @@ export class ClineProvider implements vscode.WebviewViewProvider { await this.updateGlobalState("mode", defaultModeSlug) await this.postStateToWebview() } + break + case "openPearAiAuth": + const extensionUrl = `${vscode.env.uriScheme}://pearai.pearai/auth` + const callbackUri = await vscode.env.asExternalUri(vscode.Uri.parse(extensionUrl)) + + await vscode.env.openExternal( + await vscode.env.asExternalUri( + vscode.Uri.parse( + `https://trypear.ai/signin?callback=${callbackUri.toString()}`, // Change to localhost if running locally + ), + ), + ) + break } }, null, @@ -1373,7 +1382,6 @@ export class ClineProvider implements vscode.WebviewViewProvider { openRouterUseMiddleOutTransform, vsCodeLmModelSelector, mistralApiKey, - pearaiApiKey, pearaiBaseUrl, pearaiModelId, pearaiModelInfo, @@ -1415,7 +1423,6 @@ export class ClineProvider implements vscode.WebviewViewProvider { await this.updateGlobalState("openRouterUseMiddleOutTransform", openRouterUseMiddleOutTransform) await this.updateGlobalState("vsCodeLmModelSelector", vsCodeLmModelSelector) await this.storeSecret("mistralApiKey", mistralApiKey) - await this.updateGlobalState("pearai-token", PEARAI_TOKEN) await this.updateGlobalState("pearaiBaseUrl", PEARAI_URL) await this.updateGlobalState("pearaiModelId", pearaiModelId) await this.updateGlobalState("pearaiModelInfo", pearaiModelInfo) @@ -2112,8 +2119,8 @@ export class ClineProvider implements vscode.WebviewViewProvider { this.getSecret("openAiNativeApiKey") as Promise, this.getSecret("deepSeekApiKey") as Promise, this.getSecret("mistralApiKey") as Promise, - this.getGlobalState("pearai-token") as Promise, - this.getGlobalState("pearai-refresh") as Promise, + this.getSecret("pearai-token") as Promise, + this.getSecret("pearai-refresh") as Promise, this.getGlobalState("pearaiBaseUrl") as Promise, this.getGlobalState("pearaiModelId") as Promise, this.getGlobalState("pearaiModelInfo") as Promise, diff --git a/src/extension.ts b/src/extension.ts index 332759a3811..7fcef7ae986 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -52,6 +52,23 @@ export function activate(context: vscode.ExtensionContext) { }), ) + context.subscriptions.push( + vscode.commands.registerCommand("pearai-roo-cline.pearaiLogin", async (data) => { + console.dir("Logged in to PearAI:") + console.dir(data) + context.secrets.store("pearai-token", data.accessToken) + context.secrets.store("pearai-refresh", data.refreshToken) + }), + ) + + context.subscriptions.push( + vscode.commands.registerCommand("pearai-roo-cline.pearAILogout", async () => { + console.dir("Logged out of PearAI:") + context.secrets.delete("pearai-token") + context.secrets.delete("pearai-refresh") + }), + ) + context.subscriptions.push( vscode.commands.registerCommand("roo-cline.mcpButtonClicked", () => { sidebarProvider.postMessageToWebview({ type: "action", action: "mcpButtonClicked" }) diff --git a/src/shared/ExtensionMessage.ts b/src/shared/ExtensionMessage.ts index 4cd6370697c..d7df6667a46 100644 --- a/src/shared/ExtensionMessage.ts +++ b/src/shared/ExtensionMessage.ts @@ -50,6 +50,7 @@ export interface ExtensionMessage { | "historyButtonClicked" | "promptsButtonClicked" | "didBecomeVisible" + | "updatePearAIAuth" invoke?: "sendMessage" | "primaryButtonClick" | "secondaryButtonClick" state?: ExtensionState images?: string[] diff --git a/src/shared/WebviewMessage.ts b/src/shared/WebviewMessage.ts index 357a237caf2..d0d8e81c698 100644 --- a/src/shared/WebviewMessage.ts +++ b/src/shared/WebviewMessage.ts @@ -81,6 +81,7 @@ export interface WebviewMessage { | "deleteCustomMode" | "setopenAiCustomModelInfo" | "openCustomModesSettings" + | "openPearAiAuth" text?: string disabled?: boolean askResponse?: ClineAskResponse diff --git a/src/shared/checkExistApiConfig.ts b/src/shared/checkExistApiConfig.ts index 2b850e7db39..f225eb22d8e 100644 --- a/src/shared/checkExistApiConfig.ts +++ b/src/shared/checkExistApiConfig.ts @@ -4,7 +4,6 @@ export function checkExistKey(config: ApiConfiguration | undefined) { return config ? [ config.apiKey, - config.pearaiApiKey, config.glamaApiKey, config.openRouterApiKey, config.awsRegion, @@ -17,6 +16,7 @@ export function checkExistKey(config: ApiConfiguration | undefined) { config.deepSeekApiKey, config.mistralApiKey, config.vsCodeLmModelSelector, + config.pearaiBaseUrl, ].some((key) => key !== undefined) : false } diff --git a/webview-ui/src/components/settings/ApiOptions.tsx b/webview-ui/src/components/settings/ApiOptions.tsx index ca7087ca92c..1f80fc8a23a 100644 --- a/webview-ui/src/components/settings/ApiOptions.tsx +++ b/webview-ui/src/components/settings/ApiOptions.tsx @@ -32,7 +32,6 @@ import { openRouterDefaultModelInfo, vertexDefaultModelId, vertexModels, - PEARAI_URL, } from "../../../../src/shared/api" import { ExtensionMessage } from "../../../../src/shared/ExtensionMessage" import { useExtensionState } from "../../context/ExtensionStateContext" @@ -161,20 +160,35 @@ const ApiOptions = ({ apiErrorMessage, modelIdErrorMessage }: ApiOptionsProps) = {selectedProvider === "pearai" && (
- - PearAI API Key - -

+ {!apiConfiguration?.pearaiApiKey ? ( + <> + { + vscode.postMessage({ + type: "openPearAiAuth", + }) + }}> + Login to PearAI + +

+ Connect your PearAI account to use servers. +

+ + ) : ( +

+ User already logged in to PearAI. Click 'Done' to proceed! +

+ )}
)} diff --git a/webview-ui/src/components/welcome/WelcomeView.tsx b/webview-ui/src/components/welcome/WelcomeView.tsx index 1af25a14c8d..4ff6c1d8152 100644 --- a/webview-ui/src/components/welcome/WelcomeView.tsx +++ b/webview-ui/src/components/welcome/WelcomeView.tsx @@ -1,6 +1,6 @@ import { VSCodeButton } from "@vscode/webview-ui-toolkit/react" -import { useExtensionState } from "../../context/ExtensionStateContext" import { vscode } from "../../utils/vscode" +import { PEARAI_URL } from "../../../../src/shared/api" const WelcomeView = () => { const handleSubmit = () => { @@ -8,8 +8,7 @@ const WelcomeView = () => { type: "apiConfiguration", apiConfiguration: { apiProvider: "pearai", - pearaiApiKey: "temp", // TODO: Change this to use api-key - pearaiBaseUrl: "http://localhost:8000/integrations/cline", + pearaiBaseUrl: `${PEARAI_URL}/integrations/cline`, }, }) } @@ -17,16 +16,11 @@ const WelcomeView = () => { return (

Welcome to PearAI's Coding Agent (Powered by Roo Code / Cline)!

-

- I can do all kinds of tasks thanks to the latest breakthroughs in agentic coding capabilities and access - to tools that let me create & edit files, explore complex projects, use the browser, and execute - terminal commands (with your permission, of course). I can even use MCP to create new tools and extend - my own capabilities. -

+

Ask me to code new features or fix bugs!

- Let's go! + Proceed
From b015df36e5b575a1420273f0b7b9fc8a142b2435 Mon Sep 17 00:00:00 2001 From: nang-dev Date: Thu, 30 Jan 2025 22:39:38 -0500 Subject: [PATCH 08/11] Fixed capitalization --- src/extension.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/extension.ts b/src/extension.ts index 7fcef7ae986..635cf7b777a 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -62,7 +62,7 @@ export function activate(context: vscode.ExtensionContext) { ) context.subscriptions.push( - vscode.commands.registerCommand("pearai-roo-cline.pearAILogout", async () => { + vscode.commands.registerCommand("pearai-roo-cline.pearaiLogout", async () => { console.dir("Logged out of PearAI:") context.secrets.delete("pearai-token") context.secrets.delete("pearai-refresh") From a1f8937b9509d16773b1a049947a11b41951febb Mon Sep 17 00:00:00 2001 From: nang-dev Date: Fri, 31 Jan 2025 14:51:53 -0500 Subject: [PATCH 09/11] Plus button working after login --- src/extension.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/extension.ts b/src/extension.ts index 635cf7b777a..4de3ff400e5 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -58,6 +58,7 @@ export function activate(context: vscode.ExtensionContext) { console.dir(data) context.secrets.store("pearai-token", data.accessToken) context.secrets.store("pearai-refresh", data.refreshToken) + vscode.commands.executeCommand("roo-cline.plusButtonClicked") }), ) From 7594550219e9edf3a842f09b63a292365fc84ac9 Mon Sep 17 00:00:00 2001 From: nang-dev Date: Fri, 31 Jan 2025 16:55:26 -0500 Subject: [PATCH 10/11] Added client side error --- src/api/providers/pearai.ts | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/api/providers/pearai.ts b/src/api/providers/pearai.ts index 9fe9e48ff85..ba79fb2149e 100644 --- a/src/api/providers/pearai.ts +++ b/src/api/providers/pearai.ts @@ -1,10 +1,25 @@ import { OpenAiHandler } from "./openai" +import * as vscode from "vscode" import { ApiHandlerOptions, PEARAI_URL } from "../../shared/api" import { AnthropicHandler } from "./anthropic" export class PearAiHandler extends AnthropicHandler { constructor(options: ApiHandlerOptions) { if (!options.pearaiApiKey) { + vscode.window.showErrorMessage("PearAI API key not found.", "Login to PearAI").then(async (selection) => { + if (selection === "Login to PearAI") { + const extensionUrl = `${vscode.env.uriScheme}://pearai.pearai/auth` + const callbackUri = await vscode.env.asExternalUri(vscode.Uri.parse(extensionUrl)) + + vscode.env.openExternal( + await vscode.env.asExternalUri( + vscode.Uri.parse( + `https://trypear.ai/signin?callback=${callbackUri.toString()}`, // Change to localhost if running locally + ), + ), + ) + } + }) throw new Error("PearAI API key not found. Please login to PearAI.") } super({ From 833c1b11a56a50433f77a59b49430493e8bde6fe Mon Sep 17 00:00:00 2001 From: nang-dev Date: Fri, 31 Jan 2025 17:43:22 -0500 Subject: [PATCH 11/11] Added wording tweak --- webview-ui/src/components/chat/ChatView.tsx | 9 +++------ webview-ui/src/components/welcome/WelcomeView.tsx | 9 ++++++--- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/webview-ui/src/components/chat/ChatView.tsx b/webview-ui/src/components/chat/ChatView.tsx index b5d90c80f99..ffdc3448ce4 100644 --- a/webview-ui/src/components/chat/ChatView.tsx +++ b/webview-ui/src/components/chat/ChatView.tsx @@ -935,13 +935,10 @@ const ChatView = ({ isHidden, showAnnouncement, hideAnnouncement, showHistoryVie }}> {showAnnouncement && }
-

What can I do for you?

+

PearAI Coding Agent (Powered by Roo Code / Cline)

- Thanks to the latest breakthroughs in agentic coding capabilities, I can handle complex - software development tasks step-by-step. With tools that let me create & edit files, explore - complex projects, use the browser, and execute terminal commands (after you grant - permission), I can assist you in ways that go beyond code completion or tech support. I can - even use MCP to create new tools and extend my own capabilities. + Ask me to create a new feature, fix a bug, anything else. I can create & edit files, explore + complex projects, use the browser, and execute terminal commands!

{taskHistory.length > 0 && } diff --git a/webview-ui/src/components/welcome/WelcomeView.tsx b/webview-ui/src/components/welcome/WelcomeView.tsx index 4ff6c1d8152..362e6e8081a 100644 --- a/webview-ui/src/components/welcome/WelcomeView.tsx +++ b/webview-ui/src/components/welcome/WelcomeView.tsx @@ -15,12 +15,15 @@ const WelcomeView = () => { return (
-

Welcome to PearAI's Coding Agent (Powered by Roo Code / Cline)!

-

Ask me to code new features or fix bugs!

+

Welcome to PearAI Coding Agent (Powered by Roo Code / Cline)!

+

+ Ask me to create a new feature, fix a bug, anything else. I can create & edit files, explore complex + projects, use the browser, and execute terminal commands! +

- Proceed + Next