mirror of
https://github.com/pacnpal/Roo-Code.git
synced 2025-12-21 21:01:06 -05:00
Add Kodu provider
This commit is contained in:
@@ -3,7 +3,7 @@ import { ApiConfiguration, ApiModelId, ModelInfo } from "../shared/api"
|
||||
import { AnthropicHandler } from "./anthropic"
|
||||
import { AwsBedrockHandler } from "./bedrock"
|
||||
import { OpenRouterHandler } from "./openrouter"
|
||||
import { MaestroHandler } from "./maestro"
|
||||
import { KoduHandler } from "./kodu"
|
||||
|
||||
export interface ApiHandler {
|
||||
createMessage(
|
||||
@@ -33,8 +33,8 @@ export function buildApiHandler(configuration: ApiConfiguration): ApiHandler {
|
||||
return new OpenRouterHandler(options)
|
||||
case "bedrock":
|
||||
return new AwsBedrockHandler(options)
|
||||
case "maestro":
|
||||
return new MaestroHandler(options)
|
||||
case "kodu":
|
||||
return new KoduHandler(options)
|
||||
default:
|
||||
return new AnthropicHandler(options)
|
||||
}
|
||||
|
||||
125
src/api/kodu.ts
Normal file
125
src/api/kodu.ts
Normal file
@@ -0,0 +1,125 @@
|
||||
import { Anthropic } from "@anthropic-ai/sdk"
|
||||
import { ApiHandler, withoutImageData } from "."
|
||||
import { ApiHandlerOptions, koduDefaultModelId, KoduModelId, koduModels, ModelInfo } from "../shared/api"
|
||||
import axios from "axios"
|
||||
import * as vscode from "vscode"
|
||||
|
||||
const KODU_BASE_URL = "https://claude-dev.com"
|
||||
|
||||
export function didClickKoduSignIn() {
|
||||
const loginUrl = `${KODU_BASE_URL}/auth/login?redirectTo=${vscode.env.uriScheme}://saoudrizwan.claude-dev&ext=1`
|
||||
vscode.env.openExternal(vscode.Uri.parse(loginUrl))
|
||||
}
|
||||
|
||||
export function didClickKoduAddCredits() {
|
||||
const addCreditsUrl = `${KODU_BASE_URL}/user/addCredits?redirectTo=${vscode.env.uriScheme}://saoudrizwan.claude-dev&ext=1`
|
||||
vscode.env.openExternal(vscode.Uri.parse(addCreditsUrl))
|
||||
}
|
||||
|
||||
export async function fetchKoduCredits({ apiKey }: { apiKey: string }) {
|
||||
const response = await axios.get(`${KODU_BASE_URL}/api/credits`, {
|
||||
headers: {
|
||||
"x-api-key": apiKey,
|
||||
},
|
||||
})
|
||||
return (response.data.credits as number) || 0
|
||||
}
|
||||
|
||||
export class KoduHandler implements ApiHandler {
|
||||
private options: ApiHandlerOptions
|
||||
|
||||
constructor(options: ApiHandlerOptions) {
|
||||
this.options = options
|
||||
}
|
||||
|
||||
async createMessage(
|
||||
systemPrompt: string,
|
||||
messages: Anthropic.Messages.MessageParam[],
|
||||
tools: Anthropic.Messages.Tool[]
|
||||
): Promise<Anthropic.Messages.Message> {
|
||||
const modelId = this.getModel().id
|
||||
let requestBody: Anthropic.Beta.PromptCaching.Messages.MessageCreateParamsNonStreaming
|
||||
switch (modelId) {
|
||||
case "claude-3-5-sonnet-20240620":
|
||||
case "claude-3-haiku-20240307":
|
||||
const userMsgIndices = messages.reduce(
|
||||
(acc, msg, index) => (msg.role === "user" ? [...acc, index] : acc),
|
||||
[] as number[]
|
||||
)
|
||||
const lastUserMsgIndex = userMsgIndices[userMsgIndices.length - 1] ?? -1
|
||||
const secondLastMsgUserIndex = userMsgIndices[userMsgIndices.length - 2] ?? -1
|
||||
requestBody = {
|
||||
model: modelId,
|
||||
max_tokens: this.getModel().info.maxTokens,
|
||||
system: [{ text: systemPrompt, type: "text", cache_control: { type: "ephemeral" } }],
|
||||
messages: messages.map((message, index) => {
|
||||
if (index === lastUserMsgIndex || index === secondLastMsgUserIndex) {
|
||||
return {
|
||||
...message,
|
||||
content:
|
||||
typeof message.content === "string"
|
||||
? [
|
||||
{
|
||||
type: "text",
|
||||
text: message.content,
|
||||
cache_control: { type: "ephemeral" },
|
||||
},
|
||||
]
|
||||
: message.content.map((content, contentIndex) =>
|
||||
contentIndex === message.content.length - 1
|
||||
? { ...content, cache_control: { type: "ephemeral" } }
|
||||
: content
|
||||
),
|
||||
}
|
||||
}
|
||||
return message
|
||||
}),
|
||||
tools,
|
||||
tool_choice: { type: "auto" },
|
||||
}
|
||||
break
|
||||
default:
|
||||
requestBody = {
|
||||
model: modelId,
|
||||
max_tokens: this.getModel().info.maxTokens,
|
||||
system: [{ text: systemPrompt, type: "text" }],
|
||||
messages,
|
||||
tools,
|
||||
tool_choice: { type: "auto" },
|
||||
}
|
||||
}
|
||||
const response = await axios.post(`${KODU_BASE_URL}/api/inference`, requestBody, {
|
||||
headers: {
|
||||
"x-api-key": this.options.koduApiKey,
|
||||
},
|
||||
})
|
||||
return response.data
|
||||
}
|
||||
|
||||
createUserReadableRequest(
|
||||
userContent: Array<
|
||||
| Anthropic.TextBlockParam
|
||||
| Anthropic.ImageBlockParam
|
||||
| Anthropic.ToolUseBlockParam
|
||||
| Anthropic.ToolResultBlockParam
|
||||
>
|
||||
): any {
|
||||
return {
|
||||
model: this.getModel().id,
|
||||
max_tokens: this.getModel().info.maxTokens,
|
||||
system: "(see SYSTEM_PROMPT in src/ClaudeDev.ts)",
|
||||
messages: [{ conversation_history: "..." }, { role: "user", content: withoutImageData(userContent) }],
|
||||
tools: "(see tools in src/ClaudeDev.ts)",
|
||||
tool_choice: { type: "auto" },
|
||||
}
|
||||
}
|
||||
|
||||
getModel(): { id: KoduModelId; info: ModelInfo } {
|
||||
const modelId = this.options.apiModelId
|
||||
if (modelId && modelId in koduModels) {
|
||||
const id = modelId as KoduModelId
|
||||
return { id, info: koduModels[id] }
|
||||
}
|
||||
return { id: koduDefaultModelId, info: koduModels[koduDefaultModelId] }
|
||||
}
|
||||
}
|
||||
@@ -1,114 +0,0 @@
|
||||
import { Anthropic } from "@anthropic-ai/sdk"
|
||||
import { ApiHandler, withoutImageData } from "."
|
||||
import { ApiHandlerOptions, maestroDefaultModelId, MaestroModelId, maestroModels, ModelInfo } from "../shared/api"
|
||||
|
||||
export class MaestroHandler implements ApiHandler {
|
||||
private options: ApiHandlerOptions
|
||||
private client: Anthropic
|
||||
|
||||
constructor(options: ApiHandlerOptions) {
|
||||
this.options = options
|
||||
this.client = new Anthropic({ apiKey: this.options.apiKey })
|
||||
}
|
||||
|
||||
async createMessage(
|
||||
systemPrompt: string,
|
||||
messages: Anthropic.Messages.MessageParam[],
|
||||
tools: Anthropic.Messages.Tool[]
|
||||
): Promise<Anthropic.Messages.Message> {
|
||||
const modelId = this.getModel().id
|
||||
switch (modelId) {
|
||||
case "claude-3-5-sonnet-20240620":
|
||||
case "claude-3-haiku-20240307":
|
||||
const userMsgIndices = messages.reduce(
|
||||
(acc, msg, index) => (msg.role === "user" ? [...acc, index] : acc),
|
||||
[] as number[]
|
||||
)
|
||||
const lastUserMsgIndex = userMsgIndices[userMsgIndices.length - 1] ?? -1
|
||||
const secondLastMsgUserIndex = userMsgIndices[userMsgIndices.length - 2] ?? -1
|
||||
return await this.client.beta.promptCaching.messages.create(
|
||||
{
|
||||
model: modelId,
|
||||
max_tokens: this.getModel().info.maxTokens,
|
||||
system: [{ text: systemPrompt, type: "text", cache_control: { type: "ephemeral" } }],
|
||||
messages: messages.map((message, index) => {
|
||||
if (index === lastUserMsgIndex || index === secondLastMsgUserIndex) {
|
||||
return {
|
||||
...message,
|
||||
content:
|
||||
typeof message.content === "string"
|
||||
? [
|
||||
{
|
||||
type: "text",
|
||||
text: message.content,
|
||||
cache_control: { type: "ephemeral" },
|
||||
},
|
||||
]
|
||||
: message.content.map((content, contentIndex) =>
|
||||
contentIndex === message.content.length - 1
|
||||
? { ...content, cache_control: { type: "ephemeral" } }
|
||||
: content
|
||||
),
|
||||
}
|
||||
}
|
||||
return message
|
||||
}),
|
||||
tools,
|
||||
tool_choice: { type: "auto" },
|
||||
},
|
||||
(() => {
|
||||
switch (modelId) {
|
||||
case "claude-3-5-sonnet-20240620":
|
||||
return {
|
||||
headers: {
|
||||
"anthropic-beta": "prompt-caching-2024-07-31",
|
||||
},
|
||||
}
|
||||
case "claude-3-haiku-20240307":
|
||||
return {
|
||||
headers: { "anthropic-beta": "prompt-caching-2024-07-31" },
|
||||
}
|
||||
default:
|
||||
return undefined
|
||||
}
|
||||
})()
|
||||
)
|
||||
default:
|
||||
return await this.client.messages.create({
|
||||
model: modelId,
|
||||
max_tokens: this.getModel().info.maxTokens,
|
||||
system: [{ text: systemPrompt, type: "text" }],
|
||||
messages,
|
||||
tools,
|
||||
tool_choice: { type: "auto" },
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
createUserReadableRequest(
|
||||
userContent: Array<
|
||||
| Anthropic.TextBlockParam
|
||||
| Anthropic.ImageBlockParam
|
||||
| Anthropic.ToolUseBlockParam
|
||||
| Anthropic.ToolResultBlockParam
|
||||
>
|
||||
): any {
|
||||
return {
|
||||
model: this.getModel().id,
|
||||
max_tokens: this.getModel().info.maxTokens,
|
||||
system: "(see SYSTEM_PROMPT in src/ClaudeDev.ts)",
|
||||
messages: [{ conversation_history: "..." }, { role: "user", content: withoutImageData(userContent) }],
|
||||
tools: "(see tools in src/ClaudeDev.ts)",
|
||||
tool_choice: { type: "auto" },
|
||||
}
|
||||
}
|
||||
|
||||
getModel(): { id: MaestroModelId; info: ModelInfo } {
|
||||
const modelId = this.options.apiModelId
|
||||
if (modelId && modelId in maestroModels) {
|
||||
const id = modelId as MaestroModelId
|
||||
return { id, info: maestroModels[id] }
|
||||
}
|
||||
return { id: maestroDefaultModelId, info: maestroModels[maestroDefaultModelId] }
|
||||
}
|
||||
}
|
||||
@@ -111,14 +111,11 @@ export function activate(context: vscode.ExtensionContext) {
|
||||
|
||||
// URI Handler
|
||||
const handleUri = async (uri: vscode.Uri) => {
|
||||
const query = new URLSearchParams(uri.query)
|
||||
const query = new URLSearchParams(uri.query.replace(/\+/g, "%2B"))
|
||||
const token = query.get("token")
|
||||
const fixedToken = token?.replaceAll("jwt?token=", "")
|
||||
console.log(fixedToken)
|
||||
console.log(uri)
|
||||
|
||||
if (fixedToken) {
|
||||
await sidebarProvider.saveMaestroToken(fixedToken)
|
||||
const email = query.get("email")
|
||||
if (token) {
|
||||
await sidebarProvider.saveKoduApiKey(token, email || undefined)
|
||||
}
|
||||
}
|
||||
context.subscriptions.push(vscode.window.registerUriHandler({ handleUri }))
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
import axios from "axios"
|
||||
import * as vscode from "vscode"
|
||||
import { MaestroUser, MaestroUserSchema } from "../shared/maestro"
|
||||
|
||||
const MAESTRO_BASE_URL = "https://maestro.im-ada.ai"
|
||||
|
||||
export function didClickMaestroSignIn() {
|
||||
const loginUrl = `${MAESTRO_BASE_URL}/auth/login?ext=1&redirectTo=${vscode.env.uriScheme}://saoudrizwan.claude-dev?token=jwt`
|
||||
vscode.env.openExternal(vscode.Uri.parse(loginUrl))
|
||||
}
|
||||
|
||||
export async function validateMaestroToken({
|
||||
token,
|
||||
showError = false,
|
||||
}: {
|
||||
token: string
|
||||
showError?: boolean
|
||||
}): Promise<MaestroUser> {
|
||||
try {
|
||||
const response = await axios.post(`${MAESTRO_BASE_URL}/api/extension/auth/callback`, { token })
|
||||
const user = MaestroUserSchema.parse(response.data.user)
|
||||
console.log("retrieved user", user)
|
||||
return user
|
||||
} catch (error) {
|
||||
if (showError) {
|
||||
if (axios.isAxiosError(error)) {
|
||||
vscode.window.showErrorMessage(
|
||||
"Failed to validate token:",
|
||||
error.response?.status,
|
||||
error.response?.data
|
||||
)
|
||||
} else {
|
||||
vscode.window.showErrorMessage("An unexpected error occurred:", error)
|
||||
}
|
||||
}
|
||||
throw error
|
||||
}
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
export * from "./auth"
|
||||
@@ -8,8 +8,7 @@ import { downloadTask, getNonce, getUri, selectImages } from "../utils"
|
||||
import * as path from "path"
|
||||
import fs from "fs/promises"
|
||||
import { HistoryItem } from "../shared/HistoryItem"
|
||||
import { didClickMaestroSignIn, validateMaestroToken } from "../maestro"
|
||||
import { MaestroUser } from "../shared/maestro"
|
||||
import { didClickKoduAddCredits, didClickKoduSignIn, fetchKoduCredits } from "../api/kodu"
|
||||
|
||||
/*
|
||||
https://github.com/microsoft/vscode-webview-ui-toolkit-samples/blob/main/default/weather-webview/src/providers/WeatherViewProvider.ts
|
||||
@@ -17,11 +16,13 @@ https://github.com/microsoft/vscode-webview-ui-toolkit-samples/blob/main/default
|
||||
https://github.com/KumarVariable/vscode-extension-sidebar-html/blob/master/src/customSidebarViewProvider.ts
|
||||
*/
|
||||
|
||||
type SecretKey = "apiKey" | "openRouterApiKey" | "awsAccessKey" | "awsSecretKey" | "maestroToken"
|
||||
type SecretKey = "apiKey" | "openRouterApiKey" | "awsAccessKey" | "awsSecretKey" | "koduApiKey"
|
||||
type GlobalStateKey =
|
||||
| "apiProvider"
|
||||
| "apiModelId"
|
||||
| "awsRegion"
|
||||
| "koduEmail"
|
||||
| "koduCredits"
|
||||
| "maxRequestsPerTask"
|
||||
| "lastShownAnnouncementId"
|
||||
| "customInstructions"
|
||||
@@ -34,11 +35,9 @@ export class ClaudeDevProvider implements vscode.WebviewViewProvider {
|
||||
private view?: vscode.WebviewView | vscode.WebviewPanel
|
||||
private claudeDev?: ClaudeDev
|
||||
private latestAnnouncementId = "aug-17-2024" // update to some unique identifier when we add a new announcement
|
||||
private maestroUser?: MaestroUser
|
||||
|
||||
constructor(readonly context: vscode.ExtensionContext, private readonly outputChannel: vscode.OutputChannel) {
|
||||
this.outputChannel.appendLine("ClaudeDevProvider instantiated")
|
||||
this.fetchMaestroUser({})
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -344,11 +343,23 @@ export class ClaudeDevProvider implements vscode.WebviewViewProvider {
|
||||
case "exportTaskWithId":
|
||||
this.exportTaskWithId(message.text!)
|
||||
break
|
||||
case "didClickMaestroSignIn":
|
||||
didClickMaestroSignIn()
|
||||
case "didClickKoduSignIn":
|
||||
didClickKoduSignIn()
|
||||
break
|
||||
case "didClickMaestroSignOut":
|
||||
await this.signOutMaestro()
|
||||
case "didClickKoduSignOut":
|
||||
await this.signOutKodu()
|
||||
break
|
||||
case "didClickKoduAddCredits":
|
||||
didClickKoduAddCredits()
|
||||
break
|
||||
case "fetchKoduCredits":
|
||||
const koduApiKey = await this.getSecret("koduApiKey")
|
||||
if (koduApiKey) {
|
||||
const credits = await fetchKoduCredits({ apiKey: koduApiKey })
|
||||
await this.updateGlobalState("koduCredits", credits)
|
||||
await this.postStateToWebview()
|
||||
await this.postMessageToWebview({ type: "action", action: "koduCreditsFetched" })
|
||||
}
|
||||
break
|
||||
// Add more switch case statements here as more webview message commands
|
||||
// are created within the webview context (i.e. inside media/main.js)
|
||||
@@ -359,33 +370,21 @@ export class ClaudeDevProvider implements vscode.WebviewViewProvider {
|
||||
)
|
||||
}
|
||||
|
||||
// Maestro
|
||||
// Kodu
|
||||
|
||||
async saveMaestroToken(token: string) {
|
||||
await this.storeSecret("maestroToken", token)
|
||||
await this.updateGlobalState("apiProvider", "maestro")
|
||||
await this.fetchMaestroUser({ showError: true })
|
||||
this.claudeDev?.updateApi({ apiProvider: "maestro", maestroToken: token })
|
||||
}
|
||||
|
||||
async fetchMaestroUser({ showError = false }: { showError?: boolean }): Promise<MaestroUser | undefined> {
|
||||
if (this.maestroUser) {
|
||||
return this.maestroUser
|
||||
}
|
||||
const token = await this.getSecret("maestroToken")
|
||||
if (!token) {
|
||||
return undefined
|
||||
}
|
||||
const user = await validateMaestroToken({ token, showError })
|
||||
this.maestroUser = user
|
||||
async saveKoduApiKey(apiKey: string, email?: string) {
|
||||
await this.storeSecret("koduApiKey", apiKey)
|
||||
await this.updateGlobalState("koduEmail", email)
|
||||
await this.updateGlobalState("apiProvider", "kodu")
|
||||
await this.postStateToWebview()
|
||||
return user
|
||||
this.claudeDev?.updateApi({ apiProvider: "kodu", koduApiKey: apiKey })
|
||||
}
|
||||
|
||||
async signOutMaestro() {
|
||||
await this.storeSecret("maestroToken", undefined)
|
||||
this.claudeDev?.updateApi({ apiProvider: "maestro", maestroToken: undefined })
|
||||
this.maestroUser = undefined
|
||||
async signOutKodu() {
|
||||
await this.storeSecret("koduApiKey", undefined)
|
||||
await this.updateGlobalState("koduEmail", undefined)
|
||||
await this.updateGlobalState("koduCredits", undefined)
|
||||
this.claudeDev?.updateApi({ apiProvider: "kodu", koduApiKey: undefined })
|
||||
await this.postStateToWebview()
|
||||
}
|
||||
|
||||
@@ -476,8 +475,14 @@ export class ClaudeDevProvider implements vscode.WebviewViewProvider {
|
||||
}
|
||||
|
||||
async postStateToWebview() {
|
||||
const { apiConfiguration, maxRequestsPerTask, lastShownAnnouncementId, customInstructions, taskHistory } =
|
||||
await this.getState()
|
||||
const {
|
||||
apiConfiguration,
|
||||
maxRequestsPerTask,
|
||||
lastShownAnnouncementId,
|
||||
customInstructions,
|
||||
taskHistory,
|
||||
koduCredits,
|
||||
} = await this.getState()
|
||||
this.postMessageToWebview({
|
||||
type: "state",
|
||||
state: {
|
||||
@@ -489,7 +494,7 @@ export class ClaudeDevProvider implements vscode.WebviewViewProvider {
|
||||
claudeMessages: this.claudeDev?.claudeMessages || [],
|
||||
taskHistory: (taskHistory || []).filter((item) => item.ts && item.task).sort((a, b) => b.ts - a.ts),
|
||||
shouldShowAnnouncement: lastShownAnnouncementId !== this.latestAnnouncementId,
|
||||
maestroUser: this.maestroUser,
|
||||
koduCredits,
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -589,6 +594,9 @@ export class ClaudeDevProvider implements vscode.WebviewViewProvider {
|
||||
awsAccessKey,
|
||||
awsSecretKey,
|
||||
awsRegion,
|
||||
koduApiKey,
|
||||
koduEmail,
|
||||
koduCredits,
|
||||
maxRequestsPerTask,
|
||||
lastShownAnnouncementId,
|
||||
customInstructions,
|
||||
@@ -601,6 +609,9 @@ export class ClaudeDevProvider implements vscode.WebviewViewProvider {
|
||||
this.getSecret("awsAccessKey") as Promise<string | undefined>,
|
||||
this.getSecret("awsSecretKey") as Promise<string | undefined>,
|
||||
this.getGlobalState("awsRegion") as Promise<string | undefined>,
|
||||
this.getSecret("koduApiKey") as Promise<string | undefined>,
|
||||
this.getGlobalState("koduEmail") as Promise<string | undefined>,
|
||||
this.getGlobalState("koduCredits") as Promise<number | undefined>,
|
||||
this.getGlobalState("maxRequestsPerTask") as Promise<number | undefined>,
|
||||
this.getGlobalState("lastShownAnnouncementId") as Promise<string | undefined>,
|
||||
this.getGlobalState("customInstructions") as Promise<string | undefined>,
|
||||
@@ -616,8 +627,8 @@ export class ClaudeDevProvider implements vscode.WebviewViewProvider {
|
||||
if (apiKey) {
|
||||
apiProvider = "anthropic"
|
||||
} else {
|
||||
// New users should default to anthropic (openrouter has issues, bedrock is complicated)
|
||||
apiProvider = "anthropic"
|
||||
// New users should default to kodu
|
||||
apiProvider = "kodu"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -630,11 +641,14 @@ export class ClaudeDevProvider implements vscode.WebviewViewProvider {
|
||||
awsAccessKey,
|
||||
awsSecretKey,
|
||||
awsRegion,
|
||||
koduApiKey,
|
||||
koduEmail,
|
||||
},
|
||||
maxRequestsPerTask,
|
||||
lastShownAnnouncementId,
|
||||
customInstructions,
|
||||
taskHistory,
|
||||
koduCredits,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,13 +2,17 @@
|
||||
|
||||
import { ApiConfiguration } from "./api"
|
||||
import { HistoryItem } from "./HistoryItem"
|
||||
import { MaestroUser } from "./maestro"
|
||||
|
||||
// webview will hold state
|
||||
export interface ExtensionMessage {
|
||||
type: "action" | "state" | "selectedImages"
|
||||
text?: string
|
||||
action?: "chatButtonTapped" | "settingsButtonTapped" | "historyButtonTapped" | "didBecomeVisible"
|
||||
action?:
|
||||
| "chatButtonTapped"
|
||||
| "settingsButtonTapped"
|
||||
| "historyButtonTapped"
|
||||
| "didBecomeVisible"
|
||||
| "koduCreditsFetched"
|
||||
state?: ExtensionState
|
||||
images?: string[]
|
||||
}
|
||||
@@ -22,7 +26,7 @@ export interface ExtensionState {
|
||||
claudeMessages: ClaudeMessage[]
|
||||
taskHistory: HistoryItem[]
|
||||
shouldShowAnnouncement: boolean
|
||||
maestroUser?: MaestroUser
|
||||
koduCredits?: number
|
||||
}
|
||||
|
||||
export interface ClaudeMessage {
|
||||
|
||||
@@ -15,8 +15,10 @@ export interface WebviewMessage {
|
||||
| "showTaskWithId"
|
||||
| "deleteTaskWithId"
|
||||
| "exportTaskWithId"
|
||||
| "didClickMaestroSignIn"
|
||||
| "didClickMaestroSignOut"
|
||||
| "didClickKoduSignIn"
|
||||
| "didClickKoduSignOut"
|
||||
| "didClickKoduAddCredits"
|
||||
| "fetchKoduCredits"
|
||||
text?: string
|
||||
askResponse?: ClaudeAskResponse
|
||||
apiConfiguration?: ApiConfiguration
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
export type ApiProvider = "anthropic" | "openrouter" | "bedrock" | "maestro"
|
||||
export type ApiProvider = "anthropic" | "openrouter" | "bedrock" | "kodu"
|
||||
|
||||
export interface ApiHandlerOptions {
|
||||
apiModelId?: ApiModelId
|
||||
@@ -7,7 +7,8 @@ export interface ApiHandlerOptions {
|
||||
awsAccessKey?: string
|
||||
awsSecretKey?: string
|
||||
awsRegion?: string
|
||||
maestroToken?: string
|
||||
koduApiKey?: string
|
||||
koduEmail?: string
|
||||
}
|
||||
|
||||
export type ApiConfiguration = ApiHandlerOptions & {
|
||||
@@ -234,9 +235,9 @@ export const openRouterModels = {
|
||||
// },
|
||||
} as const satisfies Record<string, ModelInfo>
|
||||
|
||||
// Maestro
|
||||
export type MaestroModelId = keyof typeof maestroModels
|
||||
export const maestroDefaultModelId: MaestroModelId = "claude-3-5-sonnet-20240620"
|
||||
export const maestroModels = {
|
||||
// Kodu
|
||||
export type KoduModelId = keyof typeof koduModels
|
||||
export const koduDefaultModelId: KoduModelId = "claude-3-5-sonnet-20240620"
|
||||
export const koduModels = {
|
||||
...anthropicModels,
|
||||
} as const satisfies Record<string, ModelInfo>
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
import { z } from "zod"
|
||||
|
||||
export const MaestroUserSchema = z.object({
|
||||
id: z.string(),
|
||||
image: z.string().nullable(),
|
||||
email: z.string().email(),
|
||||
name: z.string().nullable(),
|
||||
emailVerified: z.coerce.date().nullable(),
|
||||
})
|
||||
export type MaestroUser = z.infer<typeof MaestroUserSchema>
|
||||
Reference in New Issue
Block a user