Skip to content

Commit 653a5f5

Browse files
committed
add makehub on roo
1 parent 82f9e9e commit 653a5f5

File tree

19 files changed

+568
-2
lines changed

19 files changed

+568
-2
lines changed

.github/ISSUE_TEMPLATE/bug_report.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ body:
3232
- Human Relay Provider
3333
- LiteLLM
3434
- LM Studio
35+
- MakeHub
3536
- Mistral AI
3637
- Ollama
3738
- OpenAI

evals/apps/web/src/app/runs/new/new-run.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,7 @@ export function NewRun() {
176176
ollamaModelId,
177177
lmStudioModelId,
178178
openAiModelId,
179+
makehubModelId,
179180
} = providerSettings
180181

181182
switch (apiProvider) {
@@ -210,6 +211,9 @@ export function NewRun() {
210211
case "lmstudio":
211212
setValue("model", lmStudioModelId ?? "")
212213
break
214+
case "makehub":
215+
setValue("model", makehubModelId ?? "")
216+
break
213217
default:
214218
throw new Error(`Unsupported API provider: ${apiProvider}`)
215219
}

evals/packages/types/src/roo-code.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ export const providerNames = [
2525
"human-relay",
2626
"fake-ai",
2727
"xai",
28+
"makehub",
2829
] as const
2930

3031
export const providerNamesSchema = z.enum(providerNames)
@@ -478,6 +479,11 @@ const litellmSchema = z.object({
478479
litellmModelId: z.string().optional(),
479480
})
480481

482+
const makehubSchema = z.object({
483+
makehubApiKey: z.string().optional(),
484+
makehubModelId: z.string().optional(),
485+
})
486+
481487
const defaultSchema = z.object({
482488
apiProvider: z.undefined(),
483489
})
@@ -589,6 +595,11 @@ export const providerSettingsSchemaDiscriminated = z
589595
apiProvider: z.literal("litellm"),
590596
}),
591597
),
598+
makehubSchema.merge(
599+
z.object({
600+
apiProvider: z.literal("makehub"),
601+
}),
602+
),
592603
defaultSchema,
593604
])
594605
.and(genericProviderSettingsSchema)
@@ -617,6 +628,7 @@ export const providerSettingsSchema = z.object({
617628
...chutesSchema.shape,
618629
...litellmSchema.shape,
619630
...genericProviderSettingsSchema.shape,
631+
...makehubSchema.shape,
620632
})
621633

622634
export type ProviderSettings = z.infer<typeof providerSettingsSchema>
@@ -716,6 +728,9 @@ const providerSettingsRecord: ProviderSettingsRecord = {
716728
litellmBaseUrl: undefined,
717729
litellmApiKey: undefined,
718730
litellmModelId: undefined,
731+
// MakeHub
732+
makehubApiKey: undefined,
733+
makehubModelId: undefined,
719734
}
720735

721736
export const PROVIDER_SETTINGS_KEYS = Object.keys(providerSettingsRecord) as Keys<ProviderSettings>[]
@@ -910,6 +925,7 @@ export type SecretState = Pick<
910925
| "unboundApiKey"
911926
| "requestyApiKey"
912927
| "xaiApiKey"
928+
| "makehubApiKey"
913929
>
914930

915931
type SecretStateRecord = Record<Keys<SecretState>, undefined>
@@ -929,6 +945,7 @@ const secretStateRecord: SecretStateRecord = {
929945
unboundApiKey: undefined,
930946
requestyApiKey: undefined,
931947
xaiApiKey: undefined,
948+
makehubApiKey: undefined,
932949
}
933950

934951
export const SECRET_STATE_KEYS = Object.keys(secretStateRecord) as Keys<SecretState>[]

packages/types/src/global-settings.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,7 @@ export type SecretState = Pick<
217217
| "groqApiKey"
218218
| "chutesApiKey"
219219
| "litellmApiKey"
220+
| "makehubApiKey"
220221
| "codeIndexOpenAiKey"
221222
| "codeIndexQdrantApiKey"
222223
>
@@ -239,6 +240,7 @@ export const SECRET_STATE_KEYS = keysOf<SecretState>()([
239240
"groqApiKey",
240241
"chutesApiKey",
241242
"litellmApiKey",
243+
"makehubApiKey",
242244
"codeIndexOpenAiKey",
243245
"codeIndexQdrantApiKey",
244246
])

packages/types/src/provider-settings.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ export const providerNames = [
3030
"groq",
3131
"chutes",
3232
"litellm",
33+
"makehub",
3334
] as const
3435

3536
export const providerNamesSchema = z.enum(providerNames)
@@ -200,6 +201,12 @@ const litellmSchema = baseProviderSettingsSchema.extend({
200201
litellmModelId: z.string().optional(),
201202
})
202203

204+
const makehubSchema = baseProviderSettingsSchema.extend({
205+
makehubApiKey: z.string().optional(),
206+
makehubModelId: z.string().optional(),
207+
makehubPerfRatio: z.number().optional(),
208+
})
209+
203210
const defaultSchema = z.object({
204211
apiProvider: z.undefined(),
205212
})
@@ -226,6 +233,7 @@ export const providerSettingsSchemaDiscriminated = z.discriminatedUnion("apiProv
226233
groqSchema.merge(z.object({ apiProvider: z.literal("groq") })),
227234
chutesSchema.merge(z.object({ apiProvider: z.literal("chutes") })),
228235
litellmSchema.merge(z.object({ apiProvider: z.literal("litellm") })),
236+
makehubSchema.merge(z.object({ apiProvider: z.literal("makehub") })),
229237
defaultSchema,
230238
])
231239

@@ -252,6 +260,7 @@ export const providerSettingsSchema = z.object({
252260
...groqSchema.shape,
253261
...chutesSchema.shape,
254262
...litellmSchema.shape,
263+
...makehubSchema.shape,
255264
...codebaseIndexProviderSchema.shape,
256265
})
257266

@@ -353,4 +362,8 @@ export const PROVIDER_SETTINGS_KEYS = keysOf<ProviderSettings>()([
353362
"litellmBaseUrl",
354363
"litellmApiKey",
355364
"litellmModelId",
365+
// MakeHub
366+
"makehubApiKey",
367+
"makehubModelId",
368+
"makehubPerfRatio",
356369
])

src/api/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import {
2727
GroqHandler,
2828
ChutesHandler,
2929
LiteLLMHandler,
30+
MakeHubHandler,
3031
} from "./providers"
3132

3233
export interface SingleCompletionHandler {
@@ -106,6 +107,8 @@ export function buildApiHandler(configuration: ProviderSettings): ApiHandler {
106107
return new ChutesHandler(options)
107108
case "litellm":
108109
return new LiteLLMHandler(options)
110+
case "makehub":
111+
return new MakeHubHandler(options)
109112
default:
110113
return new AnthropicHandler(options)
111114
}
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
import axios from "axios"
2+
import type { ModelRecord } from "../../../shared/api"
3+
4+
const MAKEHUB_BASE_URL = "https://api.makehub.ai/v1"
5+
6+
interface MakehubModelResponse {
7+
data: Array<{
8+
context: number
9+
model_id: string
10+
model_name: string
11+
display_name?: string
12+
organisation: string
13+
price_per_input_token: number
14+
price_per_output_token: number
15+
provider_name: string
16+
quantisation: string | null
17+
max_tokens?: number
18+
supports_images?: boolean
19+
supports_prompt_cache?: boolean
20+
cache_writes_price?: number
21+
cache_reads_price?: number
22+
assistant_ready: boolean
23+
providers_available?: string[]
24+
thinking_config?: {
25+
max_budget?: number
26+
output_price?: number
27+
}
28+
tiers?: Array<{
29+
context_window: number
30+
input_price?: number
31+
output_price?: number
32+
cache_writes_price?: number
33+
cache_reads_price?: number
34+
}>
35+
capabilities?: {
36+
image_input?: boolean
37+
tool_calling?: boolean
38+
json_mode?: boolean
39+
}
40+
}>
41+
}
42+
43+
/**
44+
* Fetches available models from the MakeHub API
45+
*
46+
* @param apiKey - The API key for authentication
47+
* @returns A promise that resolves to a record of model IDs to model info
48+
*/
49+
export const getMakehubModels = async (apiKey?: string): Promise<ModelRecord> => {
50+
try {
51+
// Configure headers based on whether API key is provided
52+
const headers: Record<string, string> = {
53+
Accept: "application/json",
54+
"Content-Type": "application/json",
55+
"HTTP-Referer": "vscode.dev",
56+
"X-Title": "RooCode",
57+
}
58+
59+
// Add Authorization header if API key is provided
60+
if (apiKey) {
61+
headers.Authorization = `Bearer ${apiKey}`
62+
}
63+
64+
const response = await axios.get<MakehubModelResponse>(`${MAKEHUB_BASE_URL}/models`, {
65+
headers,
66+
timeout: 10000,
67+
})
68+
69+
if (!response.data?.data) {
70+
console.error("Invalid MakeHub API response format:", response.data)
71+
return {}
72+
}
73+
74+
const modelRecord: ModelRecord = {}
75+
76+
for (const model of response.data.data) {
77+
if (!model.model_id || !model.assistant_ready) continue
78+
79+
// Create a model ID that includes provider information
80+
// Use just the model_id as provided by the API, since it already has the proper format
81+
const fullModelId = model.model_id.includes("/")
82+
? model.model_id // Already has organization format
83+
: `${model.organisation}/${model.model_id}` // Add organization prefix
84+
85+
// Log the raw price values from the API for debugging
86+
console.log(`Model ${fullModelId} raw prices:`, {
87+
input: model.price_per_input_token,
88+
output: model.price_per_output_token,
89+
})
90+
91+
// MakeHub API returns prices already in cost per million tokens,
92+
// so we can use them directly without further conversion
93+
const inputPrice = model.price_per_input_token
94+
const outputPrice = model.price_per_output_token
95+
96+
console.log(`Model ${fullModelId} stored prices:`, {
97+
input: inputPrice,
98+
output: outputPrice,
99+
})
100+
101+
modelRecord[fullModelId] = {
102+
maxTokens: model.max_tokens ?? undefined,
103+
contextWindow: model.context,
104+
supportsImages: model.capabilities?.image_input ?? false,
105+
supportsComputerUse: model.capabilities?.tool_calling ?? false,
106+
supportsPromptCache: model.supports_prompt_cache ?? false,
107+
inputPrice: inputPrice,
108+
outputPrice: outputPrice,
109+
cacheWritesPrice: model.cache_writes_price,
110+
cacheReadsPrice: model.cache_reads_price,
111+
description: model.display_name,
112+
tiers: model.tiers?.map((tier) => ({
113+
contextWindow: tier.context_window,
114+
inputPrice: tier.input_price,
115+
outputPrice: tier.output_price,
116+
cacheWritesPrice: tier.cache_writes_price,
117+
cacheReadsPrice: tier.cache_reads_price,
118+
})),
119+
}
120+
}
121+
122+
return modelRecord
123+
} catch (error) {
124+
console.error("Error fetching MakeHub models:", error)
125+
if (axios.isAxiosError(error)) {
126+
console.error("Response:", error.response?.data)
127+
console.error("Status:", error.response?.status)
128+
}
129+
return {}
130+
}
131+
}

src/api/providers/fetchers/modelCache.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import { getRequestyModels } from "./requesty"
1313
import { getGlamaModels } from "./glama"
1414
import { getUnboundModels } from "./unbound"
1515
import { getLiteLLMModels } from "./litellm"
16+
import { getMakehubModels } from "./makehub"
1617
import { GetModelsOptions } from "../../../shared/api"
1718
const memoryCache = new NodeCache({ stdTTL: 5 * 60, checkperiod: 5 * 60 })
1819

@@ -68,6 +69,10 @@ export const getModels = async (options: GetModelsOptions): Promise<ModelRecord>
6869
// Type safety ensures apiKey and baseUrl are always provided for litellm
6970
models = await getLiteLLMModels(options.apiKey, options.baseUrl)
7071
break
72+
case "makehub":
73+
// Type safety ensures apiKey is always provided for makehub
74+
models = await getMakehubModels(options.apiKey)
75+
break
7176
default: {
7277
// Ensures router is exhaustively checked if RouterName is a strict union
7378
const exhaustiveCheck: never = provider

src/api/providers/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,4 @@ export { XAIHandler } from "./xai"
2020
export { GroqHandler } from "./groq"
2121
export { ChutesHandler } from "./chutes"
2222
export { LiteLLMHandler } from "./litellm"
23+
export { MakeHubHandler } from "./makehub"

0 commit comments

Comments
 (0)