diff --git a/src/api/index.ts b/src/api/index.ts index cf8085e2893..0880f422182 100644 --- a/src/api/index.ts +++ b/src/api/index.ts @@ -20,6 +20,7 @@ import { ApiStream } from "./transform/stream" import { UnboundHandler } from "./providers/unbound" import { RequestyHandler } from "./providers/requesty" import { HumanRelayHandler } from "./providers/human-relay" +import { FakeAIHandler } from "./providers/fake-ai" export interface SingleCompletionHandler { completePrompt(prompt: string): Promise @@ -75,6 +76,8 @@ export function buildApiHandler(configuration: ApiConfiguration): ApiHandler { return new RequestyHandler(options) case "human-relay": return new HumanRelayHandler(options) + case "fake-ai": + return new FakeAIHandler(options) default: return new AnthropicHandler(options) } diff --git a/src/api/providers/fake-ai.ts b/src/api/providers/fake-ai.ts new file mode 100644 index 00000000000..f7509c8b066 --- /dev/null +++ b/src/api/providers/fake-ai.ts @@ -0,0 +1,39 @@ +import { Anthropic } from "@anthropic-ai/sdk" +import { ApiHandler, SingleCompletionHandler } from ".." +import { ApiHandlerOptions, ModelInfo } from "../../shared/api" +import { ApiStream } from "../transform/stream" + +interface FakeAI { + createMessage(systemPrompt: string, messages: Anthropic.Messages.MessageParam[]): ApiStream + getModel(): { id: string; info: ModelInfo } + countTokens(content: Array): Promise + completePrompt(prompt: string): Promise +} + +export class FakeAIHandler implements ApiHandler, SingleCompletionHandler { + private ai: FakeAI + + constructor(options: ApiHandlerOptions) { + if (!options.fakeAi) { + throw new Error("Fake AI is not set") + } + + this.ai = options.fakeAi as FakeAI + } + + async *createMessage(systemPrompt: string, messages: Anthropic.Messages.MessageParam[]): ApiStream { + yield* this.ai.createMessage(systemPrompt, messages) + } + + getModel(): { id: string; info: ModelInfo } { + return this.ai.getModel() + } + + countTokens(content: Array): Promise { + return this.ai.countTokens(content) + } + + completePrompt(prompt: string): Promise { + return this.ai.completePrompt(prompt) + } +} diff --git a/src/exports/roo-code.d.ts b/src/exports/roo-code.d.ts index daa147add44..8cdedc4b1a4 100644 --- a/src/exports/roo-code.d.ts +++ b/src/exports/roo-code.d.ts @@ -254,6 +254,7 @@ export type GlobalStateKey = | "showRooIgnoredFiles" | "remoteBrowserEnabled" | "language" + | "fakeAi" export type ConfigurationKey = GlobalStateKey | SecretKey diff --git a/src/shared/api.ts b/src/shared/api.ts index 1bc432157b7..fa22dd4e00f 100644 --- a/src/shared/api.ts +++ b/src/shared/api.ts @@ -17,6 +17,7 @@ export type ApiProvider = | "unbound" | "requesty" | "human-relay" + | "fake-ai" export interface ApiHandlerOptions { apiModelId?: string @@ -76,6 +77,7 @@ export interface ApiHandlerOptions { modelTemperature?: number | null modelMaxTokens?: number modelMaxThinkingTokens?: number + fakeAi?: unknown } export type ApiConfiguration = ApiHandlerOptions & { @@ -134,6 +136,7 @@ export const API_CONFIG_KEYS: GlobalStateKey[] = [ "modelTemperature", "modelMaxTokens", "modelMaxThinkingTokens", + "fakeAi", ] // Models diff --git a/src/shared/checkExistApiConfig.ts b/src/shared/checkExistApiConfig.ts index 77b58fa31f8..5246e954abe 100644 --- a/src/shared/checkExistApiConfig.ts +++ b/src/shared/checkExistApiConfig.ts @@ -4,8 +4,8 @@ import { SECRET_KEYS } from "./globalState" export function checkExistKey(config: ApiConfiguration | undefined) { if (!config) return false - // Special case for human-relay provider which doesn't need any configuration - if (config.apiProvider === "human-relay") { + // Special case for human-relay and fake-ai providers which don't need any configuration + if (config.apiProvider === "human-relay" || config.apiProvider === "fake-ai") { return true } diff --git a/src/shared/globalState.ts b/src/shared/globalState.ts index 4331effce95..cf1a6ffe735 100644 --- a/src/shared/globalState.ts +++ b/src/shared/globalState.ts @@ -122,6 +122,7 @@ export const GLOBAL_STATE_KEYS = [ "remoteBrowserEnabled", "language", "maxWorkspaceFiles", + "fakeAi", ] as const export const PASS_THROUGH_STATE_KEYS = ["taskHistory"] as const