Repository navigation
Expand file tree
/
Copy pathindex.ts
More file actions
292 lines (273 loc) · 10.3 KB
/
Copy pathindex.ts
File metadata and controls
292 lines (273 loc) · 10.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
import { Anthropic } from "@anthropic-ai/sdk"
import OpenAI from "openai"
import {
isRetiredProvider,
providerIdentifiers,
retiredProviderIdentifiers,
type ProviderSettings,
type ModelInfo,
type ModelRecord,
} from "@roo-code/types"
import { getRouterRemovalMessage } from "../core/config/routerRemoval"
import type { GetModelsOptions } from "../shared/api"
import { ApiStream } from "./transform/stream"
import {
AnthropicHandler,
AwsBedrockHandler,
OpenRouterHandler,
PoeHandler,
VertexHandler,
AnthropicVertexHandler,
OpenAiHandler,
OpenAiCodexHandler,
LmStudioHandler,
GeminiHandler,
OpenAiNativeHandler,
DeepSeekHandler,
MoonshotHandler,
KimiCodeHandler,
MistralHandler,
VsCodeLmHandler,
GitHubCopilotHandler,
RequestyHandler,
UnboundHandler,
FakeAIHandler,
XAIHandler,
LiteLLMHandler,
QwenCodeHandler,
SambaNovaHandler,
ZAiHandler,
FireworksHandler,
FriendliHandler,
VercelAiGatewayHandler,
OpencodeGoHandler,
KenariHandler,
IOIntelligenceHandler,
NanoGptHandler,
ZooGatewayHandler,
MiniMaxHandler,
MimoHandler,
BasetenHandler,
} from "./providers"
import { NativeOllamaHandler } from "./providers/native-ollama"
/**
* Options for completePrompt — unified with ApiHandlerCreateMessageMetadata.
* Uses abortSignal (not signal) to match the metadata pattern used in stream path.
*/
export interface CompletePromptOptions extends Pick<ApiHandlerCreateMessageMetadata, "abortSignal"> {
/** Optional timeout override (ms) — falls back to provider default if omitted */
timeoutMs?: number
/**
* Task the completion belongs to, when it belongs to one.
*
* Providers that key cache affinity off a body field use this to route repeated
* completions for one task to the same bucket. Omit it when the completion is not
* scoped to a task; providers then fall back to a per-handler key.
*/
taskId?: string
}
export interface SingleCompletionHandler {
completePrompt(prompt: string, options?: CompletePromptOptions): Promise<string>
}
export interface ApiHandlerCreateMessageMetadata {
/**
* Task ID used for tracking and provider-specific features:
* - Roo: Sent as X-Roo-Task-ID header
* - Requesty: Sent as trace_id
*/
taskId: string
/**
* Current mode slug for provider-specific tracking:
* - Requesty: Sent in extra metadata
*/
mode?: string
suppressPreviousResponseId?: boolean
/**
* Controls whether the response should be stored for 30 days in OpenAI's Responses API.
* When true (default), responses are stored and can be referenced in future requests
* using the previous_response_id for efficient conversation continuity.
* Set to false to opt out of response storage for privacy or compliance reasons.
* @default true
*/
store?: boolean
/**
* Optional array of tool definitions to pass to the model.
* For OpenAI-compatible providers, these are ChatCompletionTool definitions.
*/
tools?: OpenAI.Chat.ChatCompletionTool[]
/**
* Controls which (if any) tool is called by the model.
* Can be "none", "auto", "required", or a specific tool choice.
*/
tool_choice?: OpenAI.Chat.ChatCompletionCreateParams["tool_choice"]
/**
* Controls whether the model can return multiple tool calls in a single response.
* When true (default), parallel tool calls are enabled (OpenAI's parallel_tool_calls=true).
* When false, only one tool call is returned per response.
*/
parallelToolCalls?: boolean
/**
* Optional array of tool names that the model is allowed to call.
* When provided, all tool definitions are passed to the model (so it can reference
* historical tool calls), but only the specified tools can actually be invoked.
* This is used when switching modes to prevent model errors from missing tool
* definitions while still restricting callable tools to the current mode's permissions.
* Only applies to providers that support function calling restrictions (e.g., Gemini).
*/
allowedFunctionNames?: string[]
/**
* Abort signal for cancelling the HTTP request mid-stream.
* Passed through to AI SDK's streamText() so the underlying HTTP request is aborted
* when the user clicks stop, preventing wasted API tokens/compute on the provider side.
*/
abortSignal?: AbortSignal
}
/**
* Describes how the model cache must key and persist a provider's catalog.
*/
export interface ModelCacheScope {
/** Cache key must include the normalized baseUrl. */
urlScoped: boolean
/** Cache key must include a short, irreversible API-key discriminator. */
keyScoped: boolean
/** Never persist to disk/memory; results are per signed-in user. */
authScoped: boolean
}
export interface ApiHandler {
createMessage(
systemPrompt: string,
messages: Anthropic.Messages.MessageParam[],
metadata?: ApiHandlerCreateMessageMetadata,
): ApiStream
getModel(): { id: string; info: ModelInfo }
/**
* Ensures model metadata has been fetched from the remote API so that getModel()
* returns accurate info (context window, pricing, etc.) instead of hardcoded defaults.
* Only router providers that discover models over the network implement this.
*
* `signal` bounds the caller's wait: when it aborts (e.g. the caller's bounded
* metadata wait expired or the owning task was cancelled), the returned promise
* settles with a rejection so no handler-side waiter outlives its caller.
* Fetchers that observe the signal may also stop their network request; the
* shared, de-duplicated catalog fetch may still complete and populate the model
* cache, which is by design for concurrent waiters.
*/
ensureModelFetched?(signal?: AbortSignal): Promise<void>
/**
* Optional context window for context-management / auto-condense when it must differ from
* getModel().info.contextWindow. Only VS Code LM overrides it (static `maxInputTokens` vs its
* inflated live window); others leave it undefined and callers fall back.
*/
getCondenseContextWindow?(): number
/**
* Counts tokens for content blocks
* All providers extend BaseProvider which provides a default tiktoken implementation,
* but they can override this to use their native token counting endpoints
*
* @param content The content to count tokens for
* @returns A promise resolving to the token count
*/
countTokens(content: Array<Anthropic.Messages.ContentBlockParam>): Promise<number>
/**
* Fetch this provider's live model catalog. Only dynamic-catalog providers
* implement it; others leave it undefined and the model cache rejects.
*/
fetchModels?(options: GetModelsOptions, signal?: AbortSignal): Promise<ModelRecord>
/**
* How the model cache must key and persist this provider's catalog.
* Defaults to all-false in BaseProvider.
*/
getModelCacheScope(): ModelCacheScope
}
export { disposeApiHandler } from "./dispose-api-handler"
export function buildApiHandler(configuration: ProviderSettings): ApiHandler {
const { apiProvider, ...options } = configuration
if (apiProvider === retiredProviderIdentifiers.roo) {
throw new Error(getRouterRemovalMessage())
}
if (apiProvider && isRetiredProvider(apiProvider)) {
throw new Error(
`Sorry, this provider is no longer supported. We saw very few Roo users actually using it and we need to reduce the surface area of our codebase so we can keep shipping fast and serving our community well in this space. It was a really hard decision but it lets us focus on what matters most to you. It sucks, we know.\n\nPlease select a different provider in your API profile settings.`,
)
}
switch (apiProvider) {
case providerIdentifiers.anthropic:
return new AnthropicHandler(options)
case providerIdentifiers.openrouter:
return new OpenRouterHandler(options)
case providerIdentifiers.bedrock:
return new AwsBedrockHandler(options)
case providerIdentifiers.vertex:
return options.apiModelId?.startsWith("claude")
? new AnthropicVertexHandler(options)
: new VertexHandler(options)
case providerIdentifiers.openai:
return new OpenAiHandler(options)
case providerIdentifiers.ollama:
return new NativeOllamaHandler(options)
case providerIdentifiers.lmstudio:
return new LmStudioHandler(options)
case providerIdentifiers.gemini:
return new GeminiHandler(options)
case providerIdentifiers.openaiCodex:
return new OpenAiCodexHandler(options)
case providerIdentifiers.openaiNative:
return new OpenAiNativeHandler(options)
case providerIdentifiers.deepseek:
return new DeepSeekHandler(options)
case providerIdentifiers.qwenCode:
return new QwenCodeHandler(options)
case providerIdentifiers.moonshot:
return new MoonshotHandler(options)
case providerIdentifiers.kimiCode:
return new KimiCodeHandler(options)
case providerIdentifiers.vscodeLm:
return new VsCodeLmHandler(options)
case providerIdentifiers.githubCopilot:
return new GitHubCopilotHandler(options)
case providerIdentifiers.mistral:
return new MistralHandler(options)
case providerIdentifiers.requesty:
return new RequestyHandler(options)
case providerIdentifiers.unbound:
return new UnboundHandler(options)
case providerIdentifiers.fakeAi:
return new FakeAIHandler(options)
case providerIdentifiers.xai:
return new XAIHandler(options)
case providerIdentifiers.litellm:
return new LiteLLMHandler(options)
case providerIdentifiers.sambanova:
return new SambaNovaHandler(options)
case providerIdentifiers.mimo:
return new MimoHandler(options)
case providerIdentifiers.zai:
return new ZAiHandler(options)
case providerIdentifiers.fireworks:
return new FireworksHandler(options)
case providerIdentifiers.friendli:
return new FriendliHandler(options)
case providerIdentifiers.vercelAiGateway:
return new VercelAiGatewayHandler(options)
case providerIdentifiers.opencodeGo:
return new OpencodeGoHandler(options)
case providerIdentifiers.kenari:
return new KenariHandler(options)
case providerIdentifiers.ioIntelligence:
return new IOIntelligenceHandler(options)
case providerIdentifiers.nanogpt:
return new NanoGptHandler(options)
case providerIdentifiers.zooGateway:
return new ZooGatewayHandler(options)
case providerIdentifiers.minimax:
return new MiniMaxHandler(options)
case providerIdentifiers.baseten:
return new BasetenHandler(options)
case providerIdentifiers.poe:
return new PoeHandler(options)
case providerIdentifiers.geminiCli:
// Intentionally falls through to the Anthropic handler pending a dedicated Gemini CLI handler implementation.
default:
return new AnthropicHandler(options)
}
}