( ports: number[] = [1234, 8080], )
| 251 | * isn't reachable (older LM Studio, llama.cpp, etc.). |
| 252 | */ |
| 253 | export async function detectLmStudioContextWindows( |
| 254 | ports: number[] = [1234, 8080], |
| 255 | ): Promise<Record<string, number>> { |
| 256 | const out: Record<string, number> = {}; |
| 257 | for (const port of ports) { |
| 258 | const r = await fetchWithTimeout(`http://127.0.0.1:${port}/api/v0/models`); |
| 259 | if (!r || !r.ok) continue; |
| 260 | try { |
| 261 | const body = await r.json() as { |
| 262 | data?: Array<{ id: string; max_context_length?: number; loaded_context_length?: number }>; |
| 263 | }; |
| 264 | if (!Array.isArray(body.data)) continue; |
| 265 | for (const m of body.data) { |
| 266 | // Prefer the loaded window (what's actually usable right now); fall back |
| 267 | // to the model's max. Either is vastly better than a hardcoded 32768. |
| 268 | const ctx = m.loaded_context_length || m.max_context_length; |
| 269 | if (m.id && typeof ctx === 'number' && ctx > 0) out[m.id] = ctx; |
| 270 | } |
| 271 | } catch { |
| 272 | /* ignore parse errors — heuristic will cover it */ |
| 273 | } |
| 274 | } |
| 275 | return out; |
| 276 | } |
| 277 | |
| 278 | /** |
| 279 | * Recommend a primary model from the detected list. |
no test coverage detected