# v0.4.29 (2026-05-10)
## Features - Add Cline & Kilo Code tool cards - Tailscale TUN mode for stable Funnel TLS - Sort APIKEY providers by usage, collapse to top 20 ## Improvements - Local Material Symbols font (no Google Fonts) - Docker base: Bun → Node 22-alpine - MITM reads aliases from JSON cache (no native sqlite) - Stream stall timeout (2 min) in open-sse ## Fixes - Fal.ai key test: use stable models endpoint
This commit is contained in:
@@ -2,6 +2,7 @@ import { NextResponse } from "next/server";
|
||||
import { getProviderConnectionById, getApiKeys } from "@/lib/localDb";
|
||||
import { getProviderModels, PROVIDER_ID_TO_ALIAS } from "open-sse/config/providerModels.js";
|
||||
import { isOpenAICompatibleProvider, isAnthropicCompatibleProvider } from "@/shared/constants/providers";
|
||||
import { UPDATER_CONFIG } from "@/shared/constants/config";
|
||||
|
||||
/**
|
||||
* Get an active API key to pass through auth when requireApiKey is enabled.
|
||||
@@ -64,10 +65,12 @@ export async function POST(request, { params }) {
|
||||
|
||||
let models = getProviderModels(alias);
|
||||
|
||||
const baseUrl = `http://127.0.0.1:${UPDATER_CONFIG.appPort}`;
|
||||
|
||||
// Compatible providers: fetch live model list
|
||||
if (isCompatible && models.length === 0) {
|
||||
try {
|
||||
const modelsRes = await fetch(`${getBaseUrl(request)}/api/providers/${id}/models`);
|
||||
const modelsRes = await fetch(`${baseUrl}/api/providers/${id}/models`);
|
||||
if (modelsRes.ok) {
|
||||
const data = await modelsRes.json();
|
||||
models = (data.models || []).map((m) => ({ id: m.id || m.name, name: m.name || m.id }));
|
||||
@@ -79,7 +82,6 @@ export async function POST(request, { params }) {
|
||||
return NextResponse.json({ error: "No models configured for this provider" }, { status: 400 });
|
||||
}
|
||||
|
||||
const baseUrl = getBaseUrl(request);
|
||||
const apiKey = await getInternalApiKey();
|
||||
|
||||
// Warm up with first model to trigger token refresh (if needed) before parallel calls.
|
||||
@@ -104,8 +106,3 @@ export async function POST(request, { params }) {
|
||||
return NextResponse.json({ error: "Test failed" }, { status: 500 });
|
||||
}
|
||||
}
|
||||
|
||||
function getBaseUrl(request) {
|
||||
const url = new URL(request.url);
|
||||
return `${url.protocol}//${url.host}`;
|
||||
}
|
||||
|
||||
@@ -551,6 +551,11 @@ async function testApiKeyConnection(connection, effectiveProxy = null) {
|
||||
const res = await fetchWithConnectionProxy("https://api.nanobananaapi.ai/v1/models", { headers: { Authorization: `Bearer ${connection.apiKey}` } }, effectiveProxy);
|
||||
return { valid: res.ok, error: res.ok ? null : "Invalid API key" };
|
||||
}
|
||||
case "fal-ai": {
|
||||
const res = await fetchWithConnectionProxy("https://api.fal.ai/v1/models?limit=1", { headers: { Authorization: `Key ${connection.apiKey}` } }, effectiveProxy);
|
||||
const valid = res.status !== 401 && res.status !== 403;
|
||||
return { valid, error: valid ? null : "Invalid API key" };
|
||||
}
|
||||
case "chutes": {
|
||||
const res = await fetchWithConnectionProxy("https://llm.chutes.ai/v1/models", { headers: { Authorization: `Bearer ${connection.apiKey}` } }, effectiveProxy);
|
||||
return { valid: res.ok, error: res.ok ? null : "Invalid API key" };
|
||||
|
||||
Reference in New Issue
Block a user