mirror of
https://github.com/tiennm99/goclaw.git
synced 2026-10-19 20:15:02 +00:00
fix(providers): post-merge fixes for Codex OAuth pools (#450)
- fix Rules of Hooks violation in chatgpt-oauth-routing-section - add stale-while-revalidate with atomic dedup for RouteEligibility - move raw SQL from HTTP handler to TracingStore.ListCodexPoolSpans - persist round-robin state in Registry shared counter - extract duplicated frontend helpers to agent-display-utils - split oversized frontend files (964→214 lines max) - add GIN indexes for spans.metadata and sessions.metadata - fix tenant-aware provider lookup in handleQuota - separate empty-role vs error handling in resolveTenantHint - scope pool validation to chatgpt_oauth providers only - wrap buildEntries in useCallback for stable useMemo deps - document OAuth concurrent auth limitation and RoleAdmin breaking change
This commit is contained in:
1 parent
b9c1731e31
commit
74dc086a80
35 files changed
+1695
-1455
No files matched your search
@@ -2,7 +2,6 @@ package http
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"net/http"
|
||||
"slices"
|
||||
@@ -10,7 +9,6 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/lib/pq"
|
||||
|
||||
"github.com/nextlevelbuilder/goclaw/internal/i18n"
|
||||
"github.com/nextlevelbuilder/goclaw/internal/providers"
|
||||
@@ -183,8 +181,8 @@ func agentRoutingExtraNames(routing *store.ChatGPTOAuthRoutingConfig) []string {
|
||||
|
||||
func (h *AgentsHandler) handleCodexPoolActivity(w http.ResponseWriter, r *http.Request) {
|
||||
locale := store.LocaleFromContext(r.Context())
|
||||
if h.db == nil {
|
||||
writeJSON(w, http.StatusServiceUnavailable, map[string]string{"error": i18n.T(locale, i18n.MsgInvalidRequest, "database unavailable")})
|
||||
if h.tracingStore == nil {
|
||||
writeJSON(w, http.StatusServiceUnavailable, map[string]string{"error": i18n.T(locale, i18n.MsgInvalidRequest, "tracing store unavailable")})
|
||||
return
|
||||
}
|
||||
|
||||
@@ -222,57 +220,15 @@ func (h *AgentsHandler) handleCodexPoolActivity(w http.ResponseWriter, r *http.R
|
||||
return
|
||||
}
|
||||
|
||||
const query = `
|
||||
SELECT
|
||||
sp.id,
|
||||
sp.trace_id,
|
||||
sp.start_time,
|
||||
COALESCE(sp.duration_ms, 0),
|
||||
sp.status,
|
||||
COALESCE(sp.provider, ''),
|
||||
COALESCE(sp.model, ''),
|
||||
COALESCE(sp.metadata, '{}'::jsonb)
|
||||
FROM spans sp
|
||||
JOIN traces t ON t.id = sp.trace_id
|
||||
WHERE t.agent_id = $1
|
||||
AND t.tenant_id = $2
|
||||
AND t.parent_trace_id IS NULL
|
||||
AND sp.tenant_id = $2
|
||||
AND sp.span_type = 'llm_call'
|
||||
AND (
|
||||
sp.provider = ANY($3)
|
||||
OR COALESCE(sp.metadata->'chatgpt_oauth_routing'->>'selected_provider', '') = ANY($3)
|
||||
OR COALESCE(sp.metadata->'chatgpt_oauth_routing'->>'serving_provider', '') = ANY($3)
|
||||
)
|
||||
ORDER BY sp.start_time DESC
|
||||
LIMIT $4`
|
||||
|
||||
rows, err := h.db.QueryContext(r.Context(), query, agent.ID, agent.TenantID, pq.Array(poolProviders), statsLimit)
|
||||
rawSpans, err := h.tracingStore.ListCodexPoolSpans(r.Context(), agent.ID, agent.TenantID, poolProviders, statsLimit)
|
||||
if err != nil {
|
||||
writeJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
spans := make([]codexPoolSpanActivity, 0, statsLimit)
|
||||
for rows.Next() {
|
||||
var item codexPoolSpanActivity
|
||||
var metadata json.RawMessage
|
||||
if err := rows.Scan(
|
||||
&item.SpanID,
|
||||
&item.TraceID,
|
||||
&item.StartedAt,
|
||||
&item.DurationMS,
|
||||
&item.Status,
|
||||
&item.Provider,
|
||||
&item.Model,
|
||||
&metadata,
|
||||
); err != nil {
|
||||
writeJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
item.Metadata = metadata
|
||||
if evidence := providers.ExtractChatGPTOAuthRoutingEvidence(metadata); evidence.HasData() {
|
||||
spans := make([]store.CodexPoolSpan, 0, len(rawSpans))
|
||||
for _, item := range rawSpans {
|
||||
if evidence := providers.ExtractChatGPTOAuthRoutingEvidence(item.Metadata); evidence.HasData() {
|
||||
if !providerInPool(poolProviders, evidence.SelectedProvider) && !providerInPool(poolProviders, evidence.ServingProvider) {
|
||||
continue
|
||||
}
|
||||
@@ -281,10 +237,6 @@ LIMIT $4`
|
||||
}
|
||||
spans = append(spans, item)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
writeJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
providerCounts, recent := buildCodexPoolActivity(poolProviders, spans)
|
||||
if len(recent) > limit {
|
||||
|
||||
Reference in new issue
Block a user