Skip to content

Commit 714418a

Browse files
authored
Merge pull request #2 from trypear/set-apiconfig-cmd-2
Added PearAI config
2 parents dba9f34 + a422ca4 commit 714418a

13 files changed

Lines changed: 183 additions & 43 deletions

File tree

package-lock.json

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

package.json

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
{
2-
"name": "roo-cline",
3-
"displayName": "Roo Code (prev. Roo Cline)",
4-
"description": "A VS Code plugin that enhances coding with AI-powered automation, multi-model support, and experimental features.",
5-
"publisher": "RooVeterinaryInc",
2+
"name": "pearai-roo-cline",
3+
"displayName": "PearAI Roo Code / Cline",
4+
"description": "PearAI's integration of Roo Code / Cline, a coding agent.",
5+
"publisher": "PearAI",
66
"version": "3.3.6",
77
"icon": "assets/icons/rocket.png",
88
"galleryBanner": {
@@ -13,7 +13,7 @@
1313
"vscode": "^1.84.0"
1414
},
1515
"author": {
16-
"name": "Roo Vet"
16+
"name": "PearAI"
1717
},
1818
"repository": {
1919
"type": "git",

src/api/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import { DeepSeekHandler } from "./providers/deepseek"
1414
import { MistralHandler } from "./providers/mistral"
1515
import { VsCodeLmHandler } from "./providers/vscode-lm"
1616
import { ApiStream } from "./transform/stream"
17+
import { PearAiHandler } from "./providers/pearai"
1718
import { UnboundHandler } from "./providers/unbound"
1819

1920
export interface SingleCompletionHandler {
@@ -54,6 +55,8 @@ export function buildApiHandler(configuration: ApiConfiguration): ApiHandler {
5455
return new VsCodeLmHandler(options)
5556
case "mistral":
5657
return new MistralHandler(options)
58+
case "pearai":
59+
return new PearAiHandler(options)
5760
case "unbound":
5861
return new UnboundHandler(options)
5962
default:

src/api/providers/anthropic.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,10 @@ export class AnthropicHandler implements ApiHandler, SingleCompletionHandler {
8383
case "claude-3-opus-20240229":
8484
case "claude-3-haiku-20240307":
8585
return {
86-
headers: { "anthropic-beta": "prompt-caching-2024-07-31" },
86+
headers: {
87+
"anthropic-beta": "prompt-caching-2024-07-31",
88+
"authorization": `Bearer ${this.options.apiKey}`,
89+
},
8790
}
8891
default:
8992
return undefined

src/api/providers/pearai.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { OpenAiHandler } from "./openai"
2+
import * as vscode from "vscode"
3+
import { ApiHandlerOptions, PEARAI_URL } from "../../shared/api"
4+
import { AnthropicHandler } from "./anthropic"
5+
6+
export class PearAiHandler extends AnthropicHandler {
7+
constructor(options: ApiHandlerOptions) {
8+
if (!options.pearaiApiKey) {
9+
vscode.window.showErrorMessage("PearAI API key not found.", "Login to PearAI").then(async (selection) => {
10+
if (selection === "Login to PearAI") {
11+
const extensionUrl = `${vscode.env.uriScheme}://pearai.pearai/auth`
12+
const callbackUri = await vscode.env.asExternalUri(vscode.Uri.parse(extensionUrl))
13+
14+
vscode.env.openExternal(
15+
await vscode.env.asExternalUri(
16+
vscode.Uri.parse(
17+
`https://trypear.ai/signin?callback=${callbackUri.toString()}`, // Change to localhost if running locally
18+
),
19+
),
20+
)
21+
}
22+
})
23+
throw new Error("PearAI API key not found. Please login to PearAI.")
24+
}
25+
super({
26+
...options,
27+
apiKey: options.pearaiApiKey,
28+
anthropicBaseUrl: PEARAI_URL,
29+
})
30+
}
31+
}

src/core/webview/ClineProvider.ts

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import { getTheme } from "../../integrations/theme/getTheme"
1414
import { getDiffStrategy } from "../diff/DiffStrategy"
1515
import WorkspaceTracker from "../../integrations/workspace/WorkspaceTracker"
1616
import { McpHub } from "../../services/mcp/McpHub"
17-
import { ApiConfiguration, ApiProvider, ModelInfo } from "../../shared/api"
17+
import { ApiConfiguration, ApiProvider, ModelInfo, PEARAI_URL } from "../../shared/api"
1818
import { findLast } from "../../shared/array"
1919
import { ApiConfigMeta, ExtensionMessage } from "../../shared/ExtensionMessage"
2020
import { HistoryItem } from "../../shared/HistoryItem"
@@ -63,6 +63,8 @@ type SecretKey =
6363
| "openAiNativeApiKey"
6464
| "deepSeekApiKey"
6565
| "mistralApiKey"
66+
| "pearai-token"
67+
| "pearai-refresh" // Array of custom modes
6668
| "unboundApiKey"
6769
type GlobalStateKey =
6870
| "apiProvider"
@@ -98,6 +100,10 @@ type GlobalStateKey =
98100
| "openRouterModelId"
99101
| "openRouterModelInfo"
100102
| "openRouterBaseUrl"
103+
| "pearaiModelId"
104+
| "pearaiModelInfo"
105+
| "pearaiBaseUrl"
106+
| "pearaiApiKey"
101107
| "openRouterUseMiddleOutTransform"
102108
| "allowedCommands"
103109
| "soundEnabled"
@@ -1373,6 +1379,19 @@ export class ClineProvider implements vscode.WebviewViewProvider {
13731379
await this.updateGlobalState("mode", defaultModeSlug)
13741380
await this.postStateToWebview()
13751381
}
1382+
break
1383+
case "openPearAiAuth":
1384+
const extensionUrl = `${vscode.env.uriScheme}://pearai.pearai/auth`
1385+
const callbackUri = await vscode.env.asExternalUri(vscode.Uri.parse(extensionUrl))
1386+
1387+
await vscode.env.openExternal(
1388+
await vscode.env.asExternalUri(
1389+
vscode.Uri.parse(
1390+
`https://trypear.ai/signin?callback=${callbackUri.toString()}`, // Change to localhost if running locally
1391+
),
1392+
),
1393+
)
1394+
break
13761395
}
13771396
},
13781397
null,
@@ -1422,7 +1441,7 @@ export class ClineProvider implements vscode.WebviewViewProvider {
14221441
// Update mode's default config
14231442
const { mode } = await this.getState()
14241443
if (mode) {
1425-
const currentApiConfigName = await this.getGlobalState("currentApiConfigName")
1444+
const currentApiConfigName = (await this.getGlobalState("currentApiConfigName")) ?? "default"
14261445
const listApiConfig = await this.configManager.listConfig()
14271446
const config = listApiConfig?.find((c) => c.name === currentApiConfigName)
14281447
if (config?.id) {
@@ -1468,6 +1487,9 @@ export class ClineProvider implements vscode.WebviewViewProvider {
14681487
openRouterUseMiddleOutTransform,
14691488
vsCodeLmModelSelector,
14701489
mistralApiKey,
1490+
pearaiBaseUrl,
1491+
pearaiModelId,
1492+
pearaiModelInfo,
14711493
unboundApiKey,
14721494
unboundModelId,
14731495
} = apiConfiguration
@@ -1508,6 +1530,9 @@ export class ClineProvider implements vscode.WebviewViewProvider {
15081530
await this.updateGlobalState("openRouterUseMiddleOutTransform", openRouterUseMiddleOutTransform)
15091531
await this.updateGlobalState("vsCodeLmModelSelector", vsCodeLmModelSelector)
15101532
await this.storeSecret("mistralApiKey", mistralApiKey)
1533+
await this.updateGlobalState("pearaiBaseUrl", PEARAI_URL)
1534+
await this.updateGlobalState("pearaiModelId", pearaiModelId)
1535+
await this.updateGlobalState("pearaiModelInfo", pearaiModelInfo)
15111536
await this.storeSecret("unboundApiKey", unboundApiKey)
15121537
await this.updateGlobalState("unboundModelId", unboundModelId)
15131538
if (this.cline) {
@@ -2140,6 +2165,11 @@ export class ClineProvider implements vscode.WebviewViewProvider {
21402165
openAiNativeApiKey,
21412166
deepSeekApiKey,
21422167
mistralApiKey,
2168+
pearaiApiKey,
2169+
pearaiRefreshKey,
2170+
pearaiBaseUrl,
2171+
pearaiModelId,
2172+
pearaiModelInfo,
21432173
azureApiVersion,
21442174
openAiStreamingEnabled,
21452175
openRouterModelId,
@@ -2213,6 +2243,11 @@ export class ClineProvider implements vscode.WebviewViewProvider {
22132243
this.getSecret("openAiNativeApiKey") as Promise<string | undefined>,
22142244
this.getSecret("deepSeekApiKey") as Promise<string | undefined>,
22152245
this.getSecret("mistralApiKey") as Promise<string | undefined>,
2246+
this.getSecret("pearai-token") as Promise<string | undefined>,
2247+
this.getSecret("pearai-refresh") as Promise<string | undefined>,
2248+
this.getGlobalState("pearaiBaseUrl") as Promise<string | undefined>,
2249+
this.getGlobalState("pearaiModelId") as Promise<string | undefined>,
2250+
this.getGlobalState("pearaiModelInfo") as Promise<ModelInfo | undefined>,
22162251
this.getGlobalState("azureApiVersion") as Promise<string | undefined>,
22172252
this.getGlobalState("openAiStreamingEnabled") as Promise<boolean | undefined>,
22182253
this.getGlobalState("openRouterModelId") as Promise<string | undefined>,
@@ -2303,6 +2338,10 @@ export class ClineProvider implements vscode.WebviewViewProvider {
23032338
openAiNativeApiKey,
23042339
deepSeekApiKey,
23052340
mistralApiKey,
2341+
pearaiApiKey,
2342+
pearaiBaseUrl,
2343+
pearaiModelId,
2344+
pearaiModelInfo,
23062345
azureApiVersion,
23072346
openAiStreamingEnabled,
23082347
openRouterModelId,

src/extension.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,24 @@ export function activate(context: vscode.ExtensionContext) {
5353
}),
5454
)
5555

56+
context.subscriptions.push(
57+
vscode.commands.registerCommand("pearai-roo-cline.pearaiLogin", async (data) => {
58+
console.dir("Logged in to PearAI:")
59+
console.dir(data)
60+
context.secrets.store("pearai-token", data.accessToken)
61+
context.secrets.store("pearai-refresh", data.refreshToken)
62+
vscode.commands.executeCommand("roo-cline.plusButtonClicked")
63+
}),
64+
)
65+
66+
context.subscriptions.push(
67+
vscode.commands.registerCommand("pearai-roo-cline.pearaiLogout", async () => {
68+
console.dir("Logged out of PearAI:")
69+
context.secrets.delete("pearai-token")
70+
context.secrets.delete("pearai-refresh")
71+
}),
72+
)
73+
5674
context.subscriptions.push(
5775
vscode.commands.registerCommand("roo-cline.mcpButtonClicked", () => {
5876
sidebarProvider.postMessageToWebview({ type: "action", action: "mcpButtonClicked" })

src/shared/WebviewMessage.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ export interface WebviewMessage {
8282
| "deleteCustomMode"
8383
| "setopenAiCustomModelInfo"
8484
| "openCustomModesSettings"
85+
| "openPearAiAuth"
8586
text?: string
8687
disabled?: boolean
8788
askResponse?: ClineAskResponse

src/shared/api.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ export type ApiProvider =
1414
| "deepseek"
1515
| "vscode-lm"
1616
| "mistral"
17+
| "pearai"
1718
| "unbound"
1819

1920
export interface ApiHandlerOptions {
@@ -58,6 +59,10 @@ export interface ApiHandlerOptions {
5859
deepSeekBaseUrl?: string
5960
deepSeekApiKey?: string
6061
includeMaxTokens?: boolean
62+
pearaiApiKey?: string
63+
pearaiBaseUrl?: string
64+
pearaiModelId?: string
65+
pearaiModelInfo?: ModelInfo
6166
unboundApiKey?: string
6267
unboundModelId?: string
6368
}
@@ -615,3 +620,9 @@ export const unboundModels = {
615620
"deepseek/deepseek-reasoner": deepSeekModels["deepseek-reasoner"],
616621
"mistral/codestral-latest": mistralModels["codestral-latest"],
617622
} as const satisfies Record<string, ModelInfo>
623+
624+
// CHANGE AS NEEDED FOR TESTING
625+
// PROD:
626+
// export const PEARAI_URL = "https://stingray-app-gb2an.ondigitalocean.app/pearai-server-api2/integrations/cline"
627+
// DEV:
628+
export const PEARAI_URL = "http://localhost:8000/integrations/cline"

src/shared/checkExistApiConfig.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ export function checkExistKey(config: ApiConfiguration | undefined) {
1616
config.deepSeekApiKey,
1717
config.mistralApiKey,
1818
config.vsCodeLmModelSelector,
19+
config.pearaiBaseUrl,
1920
].some((key) => key !== undefined)
2021
: false
2122
}

0 commit comments

Comments
 (0)