Skip to content

Commit bb5e346

Browse files
committed
test
1 parent bd358a1 commit bb5e346

File tree

1 file changed

+62
-49
lines changed

1 file changed

+62
-49
lines changed

src/utils/modelDiscovery.ts

Lines changed: 62 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
import OpenAI from "openai"
2-
31
export type DiscoveredModel = {
42
id: string
53
name: string
@@ -15,6 +13,19 @@ export type ConnectionTestResult = {
1513
error?: string
1614
}
1715

16+
/**
17+
* Build headers for API requests
18+
*/
19+
const buildHeaders = (apiKey?: string): HeadersInit => {
20+
const headers: HeadersInit = {
21+
"Content-Type": "application/json",
22+
}
23+
if (apiKey) {
24+
headers["Authorization"] = `Bearer ${apiKey}`
25+
}
26+
return headers
27+
}
28+
1829
/**
1930
* Discover available models from an OpenAI-compatible endpoint
2031
*/
@@ -23,30 +34,38 @@ export const discoverModels = async (
2334
apiKey?: string,
2435
): Promise<ModelDiscoveryResult> => {
2536
try {
26-
const client = new OpenAI({
27-
baseURL: normalizeBaseUrl(baseUrl),
28-
apiKey: apiKey || "not-required",
29-
dangerouslyAllowBrowser: true,
37+
const normalizedUrl = normalizeBaseUrl(baseUrl)
38+
const response = await fetch(`${normalizedUrl}/models`, {
39+
method: "GET",
40+
headers: buildHeaders(apiKey),
3041
})
3142

32-
const response = await client.models.list()
33-
const models: DiscoveredModel[] = []
34-
35-
for await (const model of response) {
36-
models.push({
37-
id: model.id,
38-
name: model.id,
39-
owned_by: model.owned_by,
40-
})
43+
if (!response.ok) {
44+
if (response.status === 401) {
45+
return { success: false, error: "Invalid API key" }
46+
}
47+
if (response.status === 404) {
48+
return { success: false, error: "Models endpoint not found. Check the base URL." }
49+
}
50+
return { success: false, error: `Server returned ${response.status}: ${response.statusText}` }
4151
}
4252

53+
const data = await response.json()
54+
const modelList = data.data || data.models || []
55+
56+
const models: DiscoveredModel[] = modelList.map((model: any) => ({
57+
id: model.id || model.name,
58+
name: model.id || model.name,
59+
owned_by: model.owned_by,
60+
}))
61+
4362
// Sort models alphabetically by id
4463
models.sort((a, b) => a.id.localeCompare(b.id))
4564

4665
return { success: true, models }
4766
} catch (error) {
4867
const message = error instanceof Error ? error.message : "Failed to discover models"
49-
return { success: false, error: message }
68+
return { success: false, error: formatConnectionError(message) }
5069
}
5170
}
5271

@@ -56,51 +75,45 @@ export const discoverModels = async (
5675
export const testCustomProviderConnection = async (
5776
baseUrl: string,
5877
apiKey?: string,
59-
modelId?: string,
6078
): Promise<ConnectionTestResult> => {
6179
try {
62-
const client = new OpenAI({
63-
baseURL: normalizeBaseUrl(baseUrl),
64-
apiKey: apiKey || "not-required",
65-
dangerouslyAllowBrowser: true,
80+
const normalizedUrl = normalizeBaseUrl(baseUrl)
81+
const response = await fetch(`${normalizedUrl}/models`, {
82+
method: "GET",
83+
headers: buildHeaders(apiKey),
6684
})
6785

68-
if (modelId) {
69-
// If a model is specified, try a simple completion
70-
await client.chat.completions.create({
71-
model: modelId,
72-
messages: [{ role: "user", content: "ping" }],
73-
max_tokens: 5,
74-
})
75-
} else {
76-
// Otherwise just list models to verify connection
77-
const response = await client.models.list()
78-
// Consume at least one item to verify the connection works
79-
for await (const _ of response) {
80-
break
86+
if (!response.ok) {
87+
if (response.status === 401) {
88+
return { valid: false, error: "Invalid API key" }
8189
}
90+
if (response.status === 404) {
91+
return { valid: false, error: "Endpoint not found. Check the base URL." }
92+
}
93+
return { valid: false, error: `Server returned ${response.status}: ${response.statusText}` }
8294
}
8395

8496
return { valid: true }
8597
} catch (error) {
8698
const message = error instanceof Error ? error.message : "Connection failed"
99+
return { valid: false, error: formatConnectionError(message) }
100+
}
101+
}
87102

88-
// Check for common error types
89-
if (message.includes("401") || message.toLowerCase().includes("unauthorized")) {
90-
return { valid: false, error: "Invalid API key" }
91-
}
92-
if (message.includes("404") || message.toLowerCase().includes("not found")) {
93-
return { valid: false, error: "Endpoint not found. Check the base URL." }
94-
}
95-
if (message.includes("ECONNREFUSED") || message.toLowerCase().includes("connection refused")) {
96-
return { valid: false, error: "Connection refused. Is the server running?" }
97-
}
98-
if (message.toLowerCase().includes("network") || message.toLowerCase().includes("fetch")) {
99-
return { valid: false, error: "Network error. Check the URL and try again." }
100-
}
101-
102-
return { valid: false, error: message }
103+
/**
104+
* Format connection error messages to be more user-friendly
105+
*/
106+
const formatConnectionError = (message: string): string => {
107+
if (message.includes("ECONNREFUSED") || message.toLowerCase().includes("connection refused")) {
108+
return "Connection refused. Is the server running?"
109+
}
110+
if (message.toLowerCase().includes("network") || message.toLowerCase().includes("fetch failed")) {
111+
return "Network error. Check the URL and try again."
112+
}
113+
if (message.toLowerCase().includes("cors")) {
114+
return "CORS error. The server may need to allow requests from this origin."
103115
}
116+
return message
104117
}
105118

106119
/**

0 commit comments

Comments
 (0)