added cline provider + making sure welcome page closes

This commit is contained in:
pashpashpash
2025-01-28 11:45:03 -08:00
parent 6e65b869ae
commit 1b59a33880
5 changed files with 136 additions and 0 deletions
+3
View File
@@ -13,6 +13,7 @@ import { ApiStream } from "./transform/stream"
import { DeepSeekHandler } from "./providers/deepseek"
import { MistralHandler } from "./providers/mistral"
import { VsCodeLmHandler } from "./providers/vscode-lm"
import { ClineHandler } from "./providers/cline"
export interface ApiHandler {
createMessage(systemPrompt: string, messages: Anthropic.Messages.MessageParam[]): ApiStream
@@ -50,6 +51,8 @@ export function buildApiHandler(configuration: ApiConfiguration): ApiHandler {
return new MistralHandler(options)
case "vscode-lm":
return new VsCodeLmHandler(options)
case "cline":
return new ClineHandler(options)
default:
return new AnthropicHandler(options)
}
+103
View File
@@ -0,0 +1,103 @@
import { Anthropic } from "@anthropic-ai/sdk"
import { Stream as AnthropicStream } from "@anthropic-ai/sdk/streaming"
import { ApiHandler } from "../"
import { ApiHandlerOptions, ModelInfo } from "../../shared/api"
import { ApiStream } from "../transform/stream"
export class ClineHandler implements ApiHandler {
private options: ApiHandlerOptions
private client: Anthropic
constructor(options: ApiHandlerOptions) {
this.options = options
this.client = new Anthropic({
apiKey: this.options.clineApiKey || "",
baseURL: "https://api.cline.bot/v1",
defaultHeaders: {
"X-Firebase-Token": this.options.authToken || "",
},
})
}
async *createMessage(systemPrompt: string, messages: Anthropic.Messages.MessageParam[]): ApiStream {
const model = this.getModel()
const stream = await this.client.messages.create({
model: model.id,
max_tokens: model.info.maxTokens || 8192,
temperature: 0,
system: [{ text: systemPrompt, type: "text" }],
messages,
stream: true,
})
for await (const chunk of stream) {
switch (chunk.type) {
case "message_start":
const usage = chunk.message.usage as any
const result: any = {
type: "usage",
inputTokens: usage.input_tokens || 0,
outputTokens: usage.output_tokens || 0,
}
if (usage.cache_creation_input_tokens) {
result.cacheWriteTokens = usage.cache_creation_input_tokens
}
if (usage.cache_read_input_tokens) {
result.cacheReadTokens = usage.cache_read_input_tokens
}
yield result
break
case "message_delta":
yield {
type: "usage",
inputTokens: 0,
outputTokens: chunk.usage.output_tokens || 0,
}
break
case "content_block_start":
switch (chunk.content_block.type) {
case "text":
if (chunk.index > 0) {
yield {
type: "text",
text: "\n",
}
}
yield {
type: "text",
text: chunk.content_block.text,
}
break
}
break
case "content_block_delta":
switch (chunk.delta.type) {
case "text_delta":
yield {
type: "text",
text: chunk.delta.text,
}
break
}
break
}
}
}
getModel() {
return {
id: "claude-3-5-sonnet",
info: {
maxTokens: 8192,
contextWindow: 200_000,
supportsImages: true,
supportsComputerUse: true,
supportsPromptCache: true,
inputPrice: 3.0,
outputPrice: 15.0,
cacheWritesPrice: 3.75,
cacheReadsPrice: 0.3,
},
}
}
}
+24
View File
@@ -139,6 +139,10 @@ export class ClineProvider implements vscode.WebviewViewProvider {
async handleSignOut() {
try {
await this.authManager.signOut()
await this.storeSecret("authToken", undefined)
await this.storeSecret("clineApiKey", undefined)
await this.updateGlobalState("apiProvider", "openrouter")
await this.postStateToWebview()
vscode.window.showInformationMessage("Successfully logged out of Cline")
} catch (error) {
vscode.window.showErrorMessage("Logout failed")
@@ -849,6 +853,19 @@ export class ClineProvider implements vscode.WebviewViewProvider {
const clineProvider: ApiProvider = "cline"
await this.updateGlobalState("apiProvider", clineProvider)
// Update API configuration with the new provider and auth token
const { apiConfiguration } = await this.getState()
const updatedConfig = {
...apiConfiguration,
apiProvider: clineProvider,
clineApiKey: apiKey,
authToken: token,
}
if (this.cline) {
this.cline.api = buildApiHandler(updatedConfig)
}
await this.postStateToWebview()
vscode.window.showInformationMessage("Successfully logged in to Cline")
} catch (error) {
@@ -1236,6 +1253,7 @@ export class ClineProvider implements vscode.WebviewViewProvider {
apiModelId,
apiKey,
openRouterApiKey,
clineApiKey,
awsAccessKey,
awsSecretKey,
awsSessionToken,
@@ -1267,11 +1285,13 @@ export class ClineProvider implements vscode.WebviewViewProvider {
vsCodeLmModelSelector,
localeLanguage,
userInfo,
authToken,
] = await Promise.all([
this.getGlobalState("apiProvider") as Promise<ApiProvider | undefined>,
this.getGlobalState("apiModelId") as Promise<string | undefined>,
this.getSecret("apiKey") as Promise<string | undefined>,
this.getSecret("openRouterApiKey") as Promise<string | undefined>,
this.getSecret("clineApiKey") as Promise<string | undefined>,
this.getSecret("awsAccessKey") as Promise<string | undefined>,
this.getSecret("awsSecretKey") as Promise<string | undefined>,
this.getSecret("awsSessionToken") as Promise<string | undefined>,
@@ -1303,6 +1323,7 @@ export class ClineProvider implements vscode.WebviewViewProvider {
this.getGlobalState("vsCodeLmModelSelector") as Promise<vscode.LanguageModelChatSelector | undefined>,
this.getGlobalState("localeLanguage") as Promise<string | undefined>,
this.getGlobalState("userInfo") as Promise<UserInfo | undefined>,
this.getSecret("authToken") as Promise<string | undefined>,
])
let apiProvider: ApiProvider
@@ -1325,6 +1346,7 @@ export class ClineProvider implements vscode.WebviewViewProvider {
apiModelId,
apiKey,
openRouterApiKey,
clineApiKey,
awsAccessKey,
awsSecretKey,
awsSessionToken,
@@ -1348,6 +1370,7 @@ export class ClineProvider implements vscode.WebviewViewProvider {
openRouterModelId,
openRouterModelInfo,
vsCodeLmModelSelector,
authToken,
},
lastShownAnnouncementId,
customInstructions,
@@ -1434,6 +1457,7 @@ export class ClineProvider implements vscode.WebviewViewProvider {
"deepSeekApiKey",
"mistralApiKey",
"authToken",
"clineApiKey",
]
for (const key of secretKeys) {
await this.storeSecret(key, undefined)
+1
View File
@@ -17,6 +17,7 @@ export interface ApiHandlerOptions {
apiModelId?: string
apiKey?: string // anthropic
clineApiKey?: string
authToken?: string // firebase auth token for cline provider
anthropicBaseUrl?: string
openRouterApiKey?: string
openRouterModelId?: string
+5
View File
@@ -43,6 +43,11 @@ export function validateApiConfiguration(apiConfiguration?: ApiConfiguration): s
return "You must provide a valid API key or choose a different provider."
}
break
case "cline":
if (!apiConfiguration.clineApiKey) {
return "You must provide a valid API key or choose a different provider."
}
break
case "openai":
if (!apiConfiguration.openAiBaseUrl || !apiConfiguration.openAiApiKey || !apiConfiguration.openAiModelId) {
return "You must provide a valid base URL, API key, and model ID."