Skip to content

Commit 6f11424

Browse files
committed
fix(ai-gateway): improve provider key test UX and error messages
- Increase test prompt max_tokens to 20 and use "Say ok" for reliable completions - Extract human-readable error.message from upstream JSON responses - Fix dialog overflow for long error messages with scroll and word-break
1 parent f31395c commit 6f11424

File tree

3 files changed

+30
-9
lines changed

3 files changed

+30
-9
lines changed

crates/temps-ai-gateway/src/handlers/providers.rs

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -343,7 +343,7 @@ async fn test_provider_key_inline(
343343
Err(e) => TestProviderKeyResponse {
344344
success: false,
345345
provider: request.provider,
346-
error: Some(e.to_string()),
346+
error: Some(friendly_error_message(&e)),
347347
latency_ms,
348348
},
349349
};
@@ -399,10 +399,31 @@ async fn test_provider_key_by_id(
399399
Err(e) => TestProviderKeyResponse {
400400
success: false,
401401
provider: provider_name,
402-
error: Some(e.to_string()),
402+
error: Some(friendly_error_message(&e)),
403403
latency_ms,
404404
},
405405
};
406406

407407
Ok(Json(response))
408408
}
409+
410+
/// Extract a human-friendly error message from an AiGatewayError.
411+
/// For upstream errors the raw body is often a JSON blob; we try to
412+
/// pull out just the `error.message` field for a cleaner UX.
413+
fn friendly_error_message(err: &AiGatewayError) -> String {
414+
if let AiGatewayError::UpstreamError {
415+
status, message, ..
416+
} = err
417+
{
418+
if let Ok(parsed) = serde_json::from_str::<serde_json::Value>(message) {
419+
if let Some(msg) = parsed
420+
.get("error")
421+
.and_then(|e| e.get("message"))
422+
.and_then(|m| m.as_str())
423+
{
424+
return format!("{} — {}", status, msg);
425+
}
426+
}
427+
}
428+
err.to_string()
429+
}

crates/temps-ai-gateway/src/services/gateway_service.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ impl GatewayService {
170170
}
171171

172172
/// Send a minimal chat completion to verify a provider API key works.
173-
/// Uses the cheapest model for the provider and `max_tokens: 1`.
173+
/// Uses the cheapest model for the provider and a small `max_tokens`.
174174
pub async fn test_provider(
175175
&self,
176176
provider_id: &str,
@@ -200,14 +200,14 @@ impl GatewayService {
200200
model: test_model.to_string(),
201201
messages: vec![ChatMessage {
202202
role: "user".to_string(),
203-
content: Some(MessageContent::Text("Hi".to_string())),
203+
content: Some(MessageContent::Text("Say ok".to_string())),
204204
name: None,
205205
tool_calls: None,
206206
tool_call_id: None,
207207
}],
208208
stream: false,
209209
temperature: None,
210-
max_tokens: Some(1),
210+
max_tokens: Some(20),
211211
top_p: None,
212212
stop: None,
213213
n: None,

web/src/pages/AiGateway.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2895,18 +2895,18 @@ console.log(response.choices[0].message.content);`,
28952895
</div>
28962896
{inlineTestResult && (
28972897
<div
2898-
className={`flex items-center gap-2 rounded-md px-3 py-2 text-sm ${
2898+
className={`flex items-start gap-2 rounded-md px-3 py-2 text-sm max-h-24 overflow-y-auto ${
28992899
inlineTestResult.success
29002900
? 'bg-green-500/10 text-green-500'
29012901
: 'bg-destructive/10 text-destructive'
29022902
}`}
29032903
>
29042904
{inlineTestResult.success ? (
2905-
<CheckCircle2 className="h-4 w-4 shrink-0" />
2905+
<CheckCircle2 className="h-4 w-4 shrink-0 mt-0.5" />
29062906
) : (
2907-
<XCircle className="h-4 w-4 shrink-0" />
2907+
<XCircle className="h-4 w-4 shrink-0 mt-0.5" />
29082908
)}
2909-
<span>
2909+
<span className="break-all">
29102910
{inlineTestResult.success
29112911
? 'Key is valid'
29122912
: inlineTestResult.error || 'Key test failed'}

0 commit comments

Comments
 (0)