feat: pre-request token validation, mid-stream error handling, and usage stats improvements
- Qoder: handle mid-stream errors by returning proper error Response instead of embedding in stream - Qoder: add refreshCredentials() to validate token via quota endpoint before requests - chatCore: validate and refresh provider tokens before sending chat requests - chatCore: bail early with 401 on unrecoverable token refresh errors - Usage stats: track apiKey, comboName, fallbackHistory in request details - Dashboard: improve Combos, Endpoint, Provider, Usage, and RequestDetails pages - API keys route: upsert logic with provider_type support - DB repos: usageRepo query improvements, requestDetailsRepo pagination, apiKeysRepo updates
This commit is contained in:
@@ -60,6 +60,9 @@ export function buildRequestDetail(base, overrides = {}) {
|
||||
provider: base.provider || "unknown",
|
||||
model: base.model || "unknown",
|
||||
connectionId: base.connectionId || undefined,
|
||||
apiKey: base.apiKey || undefined,
|
||||
comboName: base.comboName || null,
|
||||
fallbackHistory: base.fallbackHistory || null,
|
||||
timestamp: new Date().toISOString(),
|
||||
latency: base.latency || { ttft: 0, total: 0 },
|
||||
tokens: base.tokens || { prompt_tokens: 0, completion_tokens: 0 },
|
||||
@@ -72,13 +75,13 @@ export function buildRequestDetail(base, overrides = {}) {
|
||||
};
|
||||
}
|
||||
|
||||
export function saveUsageStats({ provider, model, tokens, connectionId, apiKey, endpoint, label = "USAGE" }) {
|
||||
export function saveUsageStats({ provider, model, tokens, connectionId, apiKey, endpoint, comboName, fallbackHistory, status = "ok", label = "USAGE" }) {
|
||||
if (!tokens || typeof tokens !== "object") return;
|
||||
|
||||
const inTokens = tokens.input_tokens ?? tokens.prompt_tokens ?? 0;
|
||||
const outTokens = tokens.output_tokens ?? tokens.completion_tokens ?? 0;
|
||||
|
||||
if (inTokens === 0 && outTokens === 0) return;
|
||||
if (inTokens === 0 && outTokens === 0 && status !== "error") return;
|
||||
|
||||
// Extract cache/reasoning tokens (unified from different formats)
|
||||
const cacheRead = tokens.cache_read_input_tokens || tokens.cached_tokens || tokens.prompt_tokens_details?.cached_tokens || 0;
|
||||
@@ -112,6 +115,9 @@ export function saveUsageStats({ provider, model, tokens, connectionId, apiKey,
|
||||
timestamp: new Date().toISOString(),
|
||||
connectionId: connectionId || undefined,
|
||||
apiKey: apiKey || undefined,
|
||||
endpoint: endpoint || null
|
||||
endpoint: endpoint || null,
|
||||
comboName: comboName || undefined,
|
||||
fallbackHistory: fallbackHistory || undefined,
|
||||
status: status || "ok",
|
||||
}).catch(() => {});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user