From 20014b31049220482a1b5395c4f199f6fdba565d Mon Sep 17 00:00:00 2001 From: decolua Date: Tue, 22 Sep 2026 14:41:59 +0700 Subject: [PATCH] fix(dashboard): probe System One models through /v1/systemone The inline model test sent a chat-completions payload and failed with 500 on decision models. Add a systemone branch to pingModelByKind that submits a native state+questions probe, and restore the test button that was hidden for System One models. Co-Authored-By: Claude Code --- .../providers/components/ModelsCard.js | 5 ++-- src/app/api/models/test/ping.js | 30 +++++++++++++++++++ 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/src/app/(dashboard)/dashboard/providers/components/ModelsCard.js b/src/app/(dashboard)/dashboard/providers/components/ModelsCard.js index 78bb5df8..9bdf4b41 100644 --- a/src/app/(dashboard)/dashboard/providers/components/ModelsCard.js +++ b/src/app/(dashboard)/dashboard/providers/components/ModelsCard.js @@ -119,7 +119,6 @@ export default function ModelsCard({ providerId, kindFilter, providerAliasOverri const providerAlias = providerAliasOverride || getProviderAlias(providerId); const effectiveType = kindFilter || "llm"; - const supportsTest = kindFilter !== "systemone"; const fetchData = useCallback(async () => { try { @@ -239,7 +238,7 @@ export default function ModelsCard({ providerId, kindFilter, providerAliasOverri onSetAlias={(alias) => handleSetAlias(model.id, alias)} onDeleteAlias={() => handleDeleteAlias(existingAlias)} testStatus={modelTestResults[model.id]} - onTest={supportsTest ? () => handleTestModel(model.id) : undefined} + onTest={() => handleTestModel(model.id)} isTesting={testingModelId === model.id} isFree={model.isFree} /> @@ -256,7 +255,7 @@ export default function ModelsCard({ providerId, kindFilter, providerAliasOverri onSetAlias={() => {}} onDeleteAlias={() => handleDeleteCustomModel(model.id)} testStatus={modelTestResults[model.id]} - onTest={supportsTest ? () => handleTestModel(model.id) : undefined} + onTest={() => handleTestModel(model.id)} isTesting={testingModelId === model.id} isCustom /> diff --git a/src/app/api/models/test/ping.js b/src/app/api/models/test/ping.js index a5c882d5..f38bea81 100644 --- a/src/app/api/models/test/ping.js +++ b/src/app/api/models/test/ping.js @@ -132,6 +132,36 @@ export async function pingModelByKind(model, kind, baseUrl = `http://127.0.0.1:$ return { ok: true, latencyMs, error: null, status: res.status }; } + if (kind === "systemone") { + const res = await fetch(`${baseUrl}/api/v1/systemone`, { + method: "POST", + headers, + body: JSON.stringify({ + model, + state: "Customer: I was charged twice for my order this morning.", + questions: { + probe: { type: "noul", instructions: "Is the customer reporting a billing problem?" }, + }, + }), + signal: AbortSignal.timeout(15000), + }); + const latencyMs = Date.now() - start; + const rawText = await res.text().catch(() => ""); + let parsed = null; + try { parsed = rawText ? JSON.parse(rawText) : null; } catch {} + + if (!res.ok) { + const detail = parsed?.error?.message || parsed?.msg || parsed?.message || parsed?.error || rawText; + return { ok: false, latencyMs, error: `HTTP ${res.status}${detail ? `: ${String(detail).slice(0, 240)}` : ""}`, status: res.status }; + } + + const hasAnswers = parsed?.answers && typeof parsed.answers === "object" && Object.keys(parsed.answers).length > 0; + if (!hasAnswers) { + return { ok: false, latencyMs, status: res.status, error: "Provider returned no answers for this model" }; + } + return { ok: true, latencyMs, error: null, status: res.status }; + } + const res = await fetch(`${baseUrl}/api/v1/chat/completions`, { method: "POST", headers,