swapped cline provider to use openai flavor requests

This commit is contained in:
pashpashpash
2025-01-29 15:55:08 -08:00
parent 199bdedbed
commit 82f0620ab7
3 changed files with 50 additions and 59 deletions
+27 -58
View File
@@ -1,18 +1,19 @@
import { Anthropic } from "@anthropic-ai/sdk"
import { Stream as AnthropicStream } from "@anthropic-ai/sdk/streaming"
import OpenAI from "openai"
import { ApiHandler } from "../"
import { ApiHandlerOptions, ModelInfo } from "../../shared/api"
import { ApiStream } from "../transform/stream"
import { convertToOpenAiMessages } from "../transform/openai-format"
export class ClineHandler implements ApiHandler {
private options: ApiHandlerOptions
private client: Anthropic
private client: OpenAI
constructor(options: ApiHandlerOptions) {
this.options = options
this.client = new Anthropic({
apiKey: this.options.clineApiKey || "",
this.client = new OpenAI({
baseURL: "https://api.cline.bot/v1",
apiKey: this.options.clineApiKey || "",
defaultHeaders: {
"X-Firebase-Token": this.options.authToken || "",
},
@@ -21,72 +22,40 @@ export class ClineHandler implements ApiHandler {
async *createMessage(systemPrompt: string, messages: Anthropic.Messages.MessageParam[]): ApiStream {
const model = this.getModel()
const stream = await this.client.messages.create({
const openAiMessages: OpenAI.Chat.ChatCompletionMessageParam[] = [
{ role: "system", content: systemPrompt },
...convertToOpenAiMessages(messages),
]
const stream = await this.client.chat.completions.create({
model: model.id,
max_tokens: model.info.maxTokens || 8192,
messages: openAiMessages,
temperature: 0,
system: [{ text: systemPrompt, type: "text" }],
messages,
stream: true,
stream_options: { include_usage: 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
const delta = chunk.choices[0]?.delta
if (delta?.content) {
yield {
type: "text",
text: delta.content,
}
}
if (chunk.usage) {
yield {
type: "usage",
inputTokens: chunk.usage.prompt_tokens || 0,
outputTokens: chunk.usage.completion_tokens || 0,
}
}
}
}
getModel() {
return {
id: "claude-3-5-sonnet",
id: "anthropic/claude-3.5-sonnet:beta",
info: {
maxTokens: 8192,
contextWindow: 200_000,
+19
View File
@@ -232,6 +232,25 @@ export const vertexModels = {
},
} as const satisfies Record<string, ModelInfo>
// Cline
export type ClineModelId = keyof typeof clineModels
export const clineDefaultModelId: ClineModelId = "anthropic/claude-3.5-sonnet:beta"
export const clineModels = {
"anthropic/claude-3.5-sonnet:beta": {
maxTokens: 8192,
contextWindow: 200_000,
supportsImages: true,
supportsComputerUse: true,
supportsPromptCache: true,
inputPrice: 3.0,
outputPrice: 15.0,
cacheWritesPrice: 3.75,
cacheReadsPrice: 0.3,
description:
"Claude 3.5 Sonnet delivers better-than-Opus capabilities, faster-than-Sonnet speeds, at the same Sonnet prices.",
},
} as const satisfies Record<string, ModelInfo>
export const openAiModelInfoSaneDefaults: ModelInfo = {
maxTokens: -1,
contextWindow: 128_000,
@@ -19,6 +19,8 @@ import {
azureOpenAiDefaultApiVersion,
bedrockDefaultModelId,
bedrockModels,
clineDefaultModelId,
clineModels,
deepSeekDefaultModelId,
deepSeekModels,
geminiDefaultModelId,
@@ -810,6 +812,7 @@ const ApiOptions = ({ showModelOptions, apiErrorMessage, modelIdErrorMessage, is
<label htmlFor="model-id">
<span style={{ fontWeight: 500 }}>{t("model")}</span>
</label>
{selectedProvider === "cline" && createDropdown(clineModels)}
{selectedProvider === "anthropic" && createDropdown(anthropicModels)}
{selectedProvider === "bedrock" && createDropdown(bedrockModels)}
{selectedProvider === "vertex" && createDropdown(vertexModels)}
@@ -1004,7 +1007,7 @@ export function normalizeApiConfiguration(apiConfiguration?: ApiConfiguration):
}
switch (provider) {
case "cline":
return getProviderData(anthropicModels, anthropicDefaultModelId)
return getProviderData(clineModels, clineDefaultModelId)
case "anthropic":
return getProviderData(anthropicModels, anthropicDefaultModelId)
case "bedrock":