Skip to content

Commit 42aee30

Browse files
committed
fix and update Makehub for PR
1 parent 653a5f5 commit 42aee30

File tree

5 files changed

+97
-83
lines changed

5 files changed

+97
-83
lines changed

src/api/providers/fetchers/makehub.ts

Lines changed: 37 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -57,55 +57,49 @@ export const getMakehubModels = async (apiKey?: string): Promise<ModelRecord> =>
5757
}
5858

5959
// Add Authorization header if API key is provided
60-
if (apiKey) {
61-
headers.Authorization = `Bearer ${apiKey}`
60+
if (apiKey && apiKey.trim()) {
61+
headers.Authorization = `Bearer ${apiKey.trim()}`
6262
}
6363

6464
const response = await axios.get<MakehubModelResponse>(`${MAKEHUB_BASE_URL}/models`, {
6565
headers,
66-
timeout: 10000,
66+
timeout: 15000,
6767
})
6868

6969
if (!response.data?.data) {
70-
console.error("Invalid MakeHub API response format:", response.data)
71-
return {}
70+
console.error("MakeHub: Invalid API response format:", response.data)
71+
throw new Error("Invalid API response format from MakeHub")
7272
}
7373

7474
const modelRecord: ModelRecord = {}
7575

7676
for (const model of response.data.data) {
77-
if (!model.model_id || !model.assistant_ready) continue
77+
if (!model.model_id || !model.assistant_ready) {
78+
continue
79+
}
7880

7981
// 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
8182
const fullModelId = model.model_id.includes("/")
8283
? model.model_id // Already has organization format
8384
: `${model.organisation}/${model.model_id}` // Add organization prefix
8485

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-
})
86+
// Validate pricing data
87+
if (typeof model.price_per_input_token !== "number" || typeof model.price_per_output_token !== "number") {
88+
console.warn(`MakeHub: Invalid pricing for model ${fullModelId}`, {
89+
input: model.price_per_input_token,
90+
output: model.price_per_output_token,
91+
})
92+
continue
93+
}
10094

10195
modelRecord[fullModelId] = {
10296
maxTokens: model.max_tokens ?? undefined,
10397
contextWindow: model.context,
10498
supportsImages: model.capabilities?.image_input ?? false,
10599
supportsComputerUse: model.capabilities?.tool_calling ?? false,
106100
supportsPromptCache: model.supports_prompt_cache ?? false,
107-
inputPrice: inputPrice,
108-
outputPrice: outputPrice,
101+
inputPrice: model.price_per_input_token,
102+
outputPrice: model.price_per_output_token,
109103
cacheWritesPrice: model.cache_writes_price,
110104
cacheReadsPrice: model.cache_reads_price,
111105
description: model.display_name,
@@ -121,11 +115,26 @@ export const getMakehubModels = async (apiKey?: string): Promise<ModelRecord> =>
121115

122116
return modelRecord
123117
} catch (error) {
124-
console.error("Error fetching MakeHub models:", error)
118+
console.error("MakeHub: Error fetching models:", error)
125119
if (axios.isAxiosError(error)) {
126-
console.error("Response:", error.response?.data)
127-
console.error("Status:", error.response?.status)
120+
console.error("MakeHub: HTTP Error Details:", {
121+
status: error.response?.status,
122+
statusText: error.response?.statusText,
123+
data: error.response?.data,
124+
hasApiKey: !!apiKey,
125+
})
126+
127+
if (error.response?.status === 401) {
128+
throw new Error("MakeHub: Invalid API key. Please check your API key configuration.")
129+
} else if (error.response?.status === 403) {
130+
throw new Error("MakeHub: Access forbidden. Please check your API key permissions.")
131+
} else if (error.response?.status >= 500) {
132+
throw new Error("MakeHub: Server error. Please try again later.")
133+
} else if (error.code === "ECONNABORTED") {
134+
throw new Error("MakeHub: Request timeout. Please check your internet connection.")
135+
}
128136
}
129-
return {}
137+
138+
throw new Error(`MakeHub: Failed to fetch models - ${error.message || "Unknown error"}`)
130139
}
131140
}

src/api/providers/makehub.ts

Lines changed: 29 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,7 @@ export class MakeHubHandler extends RouterProvider {
3434

3535
override async *createMessage(systemPrompt: string, messages: Anthropic.Messages.MessageParam[]): ApiStream {
3636
this.lastGenerationId = undefined
37-
await this.fetchModel()
38-
const { id: modelId, info: modelInfo } = this.getModel()
37+
const { id: modelId, info: modelInfo } = await this.fetchModel()
3938

4039
// Convert messages to OpenAI format
4140
let openAiMessages: OpenAI.Chat.ChatCompletionMessageParam[] = [
@@ -95,8 +94,6 @@ export class MakeHubHandler extends RouterProvider {
9594

9695
// Handle usage statistics if present
9796
if (!didOutputUsage && chunk.usage) {
98-
console.log("MakeHub usage data received:", chunk.usage)
99-
10097
// Validate token counts to prevent unreasonable values
10198
const promptTokens = chunk.usage.prompt_tokens || 0
10299
const completionTokens = chunk.usage.completion_tokens || 0
@@ -129,49 +126,40 @@ export class MakeHubHandler extends RouterProvider {
129126
* Calculate cost based on input and output tokens
130127
*/
131128
private calculateCost(inputTokens: number, outputTokens: number, modelInfo: any): number {
132-
// Log the input values for debugging
133-
console.log("MakeHub cost calculation inputs:", {
134-
inputTokens,
135-
outputTokens,
136-
modelInfoPrices: {
137-
inputPrice: modelInfo.inputPrice,
138-
outputPrice: modelInfo.outputPrice,
139-
},
140-
})
129+
// Validate inputs
130+
if (!modelInfo || typeof modelInfo.inputPrice !== "number" || typeof modelInfo.outputPrice !== "number") {
131+
console.warn("MakeHub: Invalid model pricing information", { modelInfo })
132+
return 0
133+
}
141134

142-
// MakeHub API returns prices already in dollars per million tokens,
143-
// so we just need to divide tokens by 1,000,000 to get the correct cost
144-
const inputCost = (inputTokens / 1_000_000) * (modelInfo.inputPrice || 0)
145-
const outputCost = (outputTokens / 1_000_000) * (modelInfo.outputPrice || 0)
146-
147-
let totalCost = inputCost + outputCost
148-
149-
// Safety check: If the cost is unreasonably high (over $100),
150-
// it's likely there's a calculation error, so apply a scaling factor
151-
// This is a temporary fix until we can determine the exact cause
152-
if (totalCost > 100) {
153-
console.warn("MakeHub cost exceeds $100, applying safety scaling factor")
154-
// Apply a scaling factor to bring it to a reasonable range
155-
// Assuming a typical conversation shouldn't cost more than a few dollars
156-
totalCost = totalCost / 10000
135+
if (inputTokens < 0 || outputTokens < 0) {
136+
console.warn("MakeHub: Invalid token counts", { inputTokens, outputTokens })
137+
return 0
157138
}
158139

159-
// Log the calculated costs for debugging
160-
console.log("MakeHub cost calculation result:", {
161-
inputTokens: inputTokens,
162-
outputTokens: outputTokens,
163-
inputPrice: modelInfo.inputPrice,
164-
outputPrice: modelInfo.outputPrice,
165-
inputCost,
166-
outputCost,
167-
totalCost,
168-
})
140+
// MakeHub API returns prices in dollars per million tokens
141+
const inputCost = (inputTokens / 1_000_000) * modelInfo.inputPrice
142+
const outputCost = (outputTokens / 1_000_000) * modelInfo.outputPrice
143+
const totalCost = inputCost + outputCost
144+
145+
// Log for debugging only if cost seems unusual
146+
if (totalCost > 10) {
147+
console.log("MakeHub high cost calculation:", {
148+
inputTokens,
149+
outputTokens,
150+
inputPrice: modelInfo.inputPrice,
151+
outputPrice: modelInfo.outputPrice,
152+
inputCost,
153+
outputCost,
154+
totalCost,
155+
})
156+
}
169157

170-
return totalCost
158+
return Math.max(0, totalCost)
171159
}
172160

173161
protected override supportsTemperature(modelId: string): boolean {
174-
const model = this.models[modelId]
175-
return model?.supportsImages ?? false
162+
// Most models support temperature, but exclude o3-mini variants like OpenAI
163+
return !modelId.toLowerCase().includes("o3-mini")
176164
}
177165
}

src/core/webview/webviewMessageHandler.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -317,9 +317,22 @@ export const webviewMessageHandler = async (provider: ClineProvider, message: We
317317
{ key: "requesty", options: { provider: "requesty", apiKey: apiConfiguration.requestyApiKey } },
318318
{ key: "glama", options: { provider: "glama" } },
319319
{ key: "unbound", options: { provider: "unbound", apiKey: apiConfiguration.unboundApiKey } },
320-
{ key: "makehub", options: { provider: "makehub", apiKey: apiConfiguration.makehubApiKey } },
321320
]
322321

322+
// Add MakeHub with proper API key handling
323+
if (apiConfiguration.makehubApiKey) {
324+
modelFetchPromises.push({
325+
key: "makehub",
326+
options: { provider: "makehub", apiKey: apiConfiguration.makehubApiKey },
327+
})
328+
} else {
329+
// MakeHub can work without API key, but with limited access
330+
modelFetchPromises.push({
331+
key: "makehub",
332+
options: { provider: "makehub" },
333+
})
334+
}
335+
323336
const litellmApiKey = apiConfiguration.litellmApiKey || message?.values?.litellmApiKey
324337
const litellmBaseUrl = apiConfiguration.litellmBaseUrl || message?.values?.litellmBaseUrl
325338
if (litellmApiKey && litellmBaseUrl) {

webview-ui/src/components/settings/ApiOptions.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -402,7 +402,12 @@ const ApiOptions = ({
402402
)}
403403

404404
{selectedProvider === "makehub" && (
405-
<MakeHub apiConfiguration={apiConfiguration} setApiConfigurationField={setApiConfigurationField} />
405+
<MakeHub
406+
apiConfiguration={apiConfiguration}
407+
setApiConfigurationField={setApiConfigurationField}
408+
routerModels={routerModels}
409+
refetchRouterModels={refetchRouterModels}
410+
/>
406411
)}
407412

408413
{selectedProvider === "human-relay" && (

webview-ui/src/components/settings/providers/MakeHub.tsx

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,6 @@ export const MakeHub = ({
3939

4040
const perfRatio = apiConfiguration?.makehubPerfRatio ?? 0.5
4141

42-
// Get all available models
43-
const models = routerModels?.makehub || {}
44-
const modelEntries = Object.entries(models).sort(([idA], [idB]) => idA.localeCompare(idB))
45-
4642
return (
4743
<>
4844
<VSCodeTextField
@@ -109,8 +105,8 @@ export const MakeHub = ({
109105
<VSCodeDropdown
110106
value={apiConfiguration?.makehubModelId || makehubDefaultModelId}
111107
style={{ width: "100%" }}>
112-
{modelEntries.length > 0 ? (
113-
modelEntries.map(([id, info]) => (
108+
{Object.entries(routerModels?.makehub ?? {}).length > 0 ? (
109+
Object.entries(routerModels?.makehub ?? {}).map(([id, info]) => (
114110
<VSCodeOption
115111
key={id}
116112
value={id}
@@ -123,27 +119,30 @@ export const MakeHub = ({
123119
)}
124120
</VSCodeDropdown>
125121

126-
{modelEntries.length === 0 && (
122+
{Object.entries(routerModels?.makehub ?? {}).length === 0 && (
127123
<div className="text-sm text-vscode-descriptionForeground mt-2">
128124
{t("settings:providers.noModelsFound", { provider: "MakeHub" })}
129125
</div>
130126
)}
131127

132-
{apiConfiguration?.makehubModelId && models[apiConfiguration.makehubModelId] && (
128+
{apiConfiguration?.makehubModelId && routerModels?.makehub?.[apiConfiguration.makehubModelId] && (
133129
<div className="mt-2 text-sm">
134130
<div className="flex justify-between">
135131
<span>{t("settings:modelInfo.contextWindow")}:</span>
136-
<span>{models[apiConfiguration.makehubModelId].contextWindow.toLocaleString()} tokens</span>
132+
<span>
133+
{routerModels.makehub[apiConfiguration.makehubModelId].contextWindow.toLocaleString()}{" "}
134+
tokens
135+
</span>
137136
</div>
138137
<div className="flex justify-between">
139138
<span>{t("settings:modelInfo.inputPrice")}:</span>
140-
<span>${models[apiConfiguration.makehubModelId].inputPrice}/M tokens</span>
139+
<span>${routerModels.makehub[apiConfiguration.makehubModelId].inputPrice}/M tokens</span>
141140
</div>
142141
<div className="flex justify-between">
143142
<span>{t("settings:modelInfo.outputPrice")}:</span>
144-
<span>${models[apiConfiguration.makehubModelId].outputPrice}/M tokens</span>
143+
<span>${routerModels.makehub[apiConfiguration.makehubModelId].outputPrice}/M tokens</span>
145144
</div>
146-
{models[apiConfiguration.makehubModelId].supportsImages && (
145+
{routerModels.makehub[apiConfiguration.makehubModelId].supportsImages && (
147146
<div className="flex justify-between">
148147
<span>{t("settings:modelInfo.supportsImages")}</span>
149148
<span>{t("settings:common.yes")}</span>

0 commit comments

Comments
 (0)