Unified · Split
| @@ -384,22 +384,20 @@ func (h *Handler) resolveMetaToken(ctx context.Context, auth *coreauth.Auth, req · 383 unmodified lines | |||
| 384 | } | 384 | } |
| 385 | 385 | ||
| 386 | var dcaToken string | 386 | var dcaToken string |
| 387 | if auth.Metadata != nil { | 387 | if !coreauth.IsConfigAPIKeyAuth(auth) { |
| 388 | if d, ok := auth.Metadata["dca_token"].(string); ok && strings.TrimSpace(d) != "" { | 388 | if auth.Metadata != nil { |
| 389 | dcaToken = strings.TrimSpace(d) | 389 | if d, ok := auth.Metadata["dca_token"].(string); ok && strings.TrimSpace(d) != "" { |
| 390 | } else if t, ok := auth.Metadata["access_token"].(string); ok && strings.HasPrefix(strings.TrimSpace(t), "dca:") { | 390 | dcaToken = strings.TrimSpace(d) |
| 391 | dcaToken = strings.TrimSpace(t) | 391 | } else if t, ok := auth.Metadata["access_token"].(string); ok && strings.HasPrefix(strings.TrimSpace(t), "dca:") { |
| 392 | } else if k, ok := auth.Metadata["api_key"].(string); ok && strings.HasPrefix(strings.TrimSpace(k), "dca:") { | 392 | dcaToken = strings.TrimSpace(t) |
| 393 | dcaToken = strings.TrimSpace(k) | 393 | } |
| 394 | } | 394 | } |
| 395 | } | 395 | if dcaToken == "" && auth.Attributes != nil { |
| 396 | if dcaToken == "" && auth.Attributes != nil { | 396 | if d := strings.TrimSpace(auth.Attributes["dca_token"]); d != "" { |
| 397 | if d := strings.TrimSpace(auth.Attributes["dca_token"]); d != "" { | 397 | dcaToken = d |
| 398 | dcaToken = d | 398 | } else if t := strings.TrimSpace(auth.Attributes["access_token"]); strings.HasPrefix(t, "dca:") { |
| 399 | } else if t := strings.TrimSpace(auth.Attributes["access_token"]); strings.HasPrefix(t, "dca:") { | 399 | dcaToken = t |
| 400 | dcaToken = t | 400 | } |
| 401 | } else if k := strings.TrimSpace(auth.Attributes["api_key"]); strings.HasPrefix(k, "dca:") { | ||
| 402 | dcaToken = k | ||
| 403 | } | 401 | } |
| 404 | } | 402 | } |
| 405 | 403 | ||
| @@ -9,13 +9,13 @@ func TestMetaConfigDropsUnusableKeys(t *testing.T) { · 8 unmodified lines | |||
| 9 | - base-url: "https://api.meta.ai/v1" | 9 | - base-url: "https://api.meta.ai/v1" |
| 10 | - headers: {X-Trace: placeholder} | 10 | - headers: {X-Trace: placeholder} |
| 11 | - api-key: " LLM|valid " | 11 | - api-key: " LLM|valid " |
| 12 | - api-key: "dca:recoverable" | 12 | - api-key: "dca:requires-oauth-storage" |
| 13 | `)) | 13 | `)) |
| 14 | if err != nil { | 14 | if err != nil { |
| 15 | t.Fatal(err) | 15 | t.Fatal(err) |
| 16 | } | 16 | } |
| 17 | if len(cfg.MetaKey) != 2 { | 17 | if len(cfg.MetaKey) != 1 { |
| 18 | t.Fatalf("got %d keys, want only the two usable credentials", len(cfg.MetaKey)) | 18 | t.Fatalf("got %d keys, want only the 1 valid API key (DCA tokens require OAuth storage)", len(cfg.MetaKey)) |
| 19 | } | 19 | } |
| 20 | if cfg.MetaKey[0].APIKey != "LLM|valid" || cfg.MetaKey[0].BaseURL != "https://api.meta.ai/v1" { | 20 | if cfg.MetaKey[0].APIKey != "LLM|valid" || cfg.MetaKey[0].BaseURL != "https://api.meta.ai/v1" { |
| 21 | t.Fatalf("valid key not normalized: %#v", cfg.MetaKey[0]) | 21 | t.Fatalf("valid key not normalized: %#v", cfg.MetaKey[0]) |
| @@ -210,8 +210,8 @@ func sanitizeMetaKeyEntries(entries []MetaKey) []MetaKey { · 209 unmodified lines | |||
| 210 | for i := range entries { | 210 | for i := range entries { |
| 211 | e := entries[i] | 211 | e := entries[i] |
| 212 | e.APIKey = strings.TrimSpace(e.APIKey) | 212 | e.APIKey = strings.TrimSpace(e.APIKey) |
| 213 | // The native Meta executor requires an API key or a DCA token in this field. | 213 | // meta-api-key requires a valid API key. DCA tokens require OAuth storage (auths/*.json). |
| 214 | if e.APIKey == "" { | 214 | if e.APIKey == "" || strings.HasPrefix(e.APIKey, "dca:") { |
| 215 | continue | 215 | continue |
| 216 | } | 216 | } |
| 217 | e.Prefix = normalizeModelPrefix(e.Prefix) | 217 | e.Prefix = normalizeModelPrefix(e.Prefix) |
| @@ -254,7 +254,7 @@ func (e *MetaExecutor) Refresh(ctx context.Context, auth *cliproxyauth.Auth) (*c · 253 unmodified lines | |||
| 254 | 254 | ||
| 255 | // ShouldPrepareRequestAuth reports true when a Meta auth has a DCA token but no usable API key. | 255 | // ShouldPrepareRequestAuth reports true when a Meta auth has a DCA token but no usable API key. |
| 256 | func (e *MetaExecutor) ShouldPrepareRequestAuth(auth *cliproxyauth.Auth) bool { | 256 | func (e *MetaExecutor) ShouldPrepareRequestAuth(auth *cliproxyauth.Auth) bool { |
| 257 | if auth == nil { | 257 | if auth == nil || cliproxyauth.IsConfigAPIKeyAuth(auth) { |
| 258 | return false | 258 | return false |
| 259 | } | 259 | } |
| 260 | _, token := metaCreds(auth) | 260 | _, token := metaCreds(auth) |
| @@ -291,6 +291,12 @@ func (e *MetaExecutor) ensureAuth(ctx context.Context, auth *cliproxyauth.Auth) · 30 unmodified lines | |||
| 291 | } | 291 | } |
| 292 | 292 | ||
| 293 | if token == "" { | 293 | if token == "" { |
| 294 | if cliproxyauth.IsConfigAPIKeyAuth(auth) { | ||
| 295 | return nil, statusErr{ | ||
| 296 | code: http.StatusUnauthorized, | ||
| 297 | msg: "meta executor: meta-api-key requires a valid API key (DCA tokens require OAuth storage)", | ||
| 298 | } | ||
| 299 | } | ||
| 294 | return nil, statusErr{ | 300 | return nil, statusErr{ |
| 295 | code: http.StatusUnauthorized, | 301 | code: http.StatusUnauthorized, |
| 296 | msg: "meta executor: missing API key or access token", | 302 | msg: "meta executor: missing API key or access token", |
| @@ -326,7 +332,7 @@ func (e *MetaExecutor) enrichAuth(auth *cliproxyauth.Auth) *cliproxyauth.Auth { · 29 unmodified lines | |||
| 326 | } | 332 | } |
| 327 | 333 | ||
| 328 | func extractDCAToken(a *cliproxyauth.Auth) string { | 334 | func extractDCAToken(a *cliproxyauth.Auth) string { |
| 329 | if a == nil { | 335 | if a == nil || cliproxyauth.IsConfigAPIKeyAuth(a) { |
| 330 | return "" | 336 | return "" |
| 331 | } | 337 | } |
| 332 | if a.Attributes != nil { | 338 | if a.Attributes != nil { |
| @@ -336,9 +342,6 @@ func extractDCAToken(a *cliproxyauth.Auth) string { · 3 unmodified lines | |||
| 336 | if t := strings.TrimSpace(a.Attributes["access_token"]); strings.HasPrefix(t, "dca:") { | 342 | if t := strings.TrimSpace(a.Attributes["access_token"]); strings.HasPrefix(t, "dca:") { |
| 337 | return t | 343 | return t |
| 338 | } | 344 | } |
| 339 | if k := strings.TrimSpace(a.Attributes["api_key"]); strings.HasPrefix(k, "dca:") { | ||
| 340 | return k | ||
| 341 | } | ||
| 342 | } | 345 | } |
| 343 | if a.Metadata != nil { | 346 | if a.Metadata != nil { |
| 344 | if d, ok := a.Metadata["dca_token"].(string); ok && strings.TrimSpace(d) != "" { | 347 | if d, ok := a.Metadata["dca_token"].(string); ok && strings.TrimSpace(d) != "" { |
| @@ -347,9 +350,6 @@ func extractDCAToken(a *cliproxyauth.Auth) string { · 2 unmodified lines | |||
| 347 | if t, ok := a.Metadata["access_token"].(string); ok && strings.HasPrefix(strings.TrimSpace(t), "dca:") { | 350 | if t, ok := a.Metadata["access_token"].(string); ok && strings.HasPrefix(strings.TrimSpace(t), "dca:") { |
| 348 | return strings.TrimSpace(t) | 351 | return strings.TrimSpace(t) |
| 349 | } | 352 | } |
| 350 | if k, ok := a.Metadata["api_key"].(string); ok && strings.HasPrefix(strings.TrimSpace(k), "dca:") { | ||
| 351 | return strings.TrimSpace(k) | ||
| 352 | } | ||
| 353 | } | 353 | } |
| 354 | if a.Storage != nil { | 354 | if a.Storage != nil { |
| 355 | if ms, ok := a.Storage.(*metaauth.MetaTokenStorage); ok && ms != nil { | 355 | if ms, ok := a.Storage.(*metaauth.MetaTokenStorage); ok && ms != nil { |
| @@ -572,6 +572,17 @@ func TestMetaExecutor_RequestAuthPreparer(t *testing.T) { · 571 unmodified lines | |||
| 572 | t.Errorf("ShouldPrepareRequestAuth should be false when dca_token is missing") | 572 | t.Errorf("ShouldPrepareRequestAuth should be false when dca_token is missing") |
| 573 | } | 573 | } |
| 574 | 574 | ||
| 575 | authConfigDCA := &cliproxyauth.Auth{ | ||
| 576 | Provider: "meta", | ||
| 577 | Attributes: map[string]string{ | ||
| 578 | "api_key": "dca:invalid-for-config", | ||
| 579 | cliproxyauth.AttributeSource: "config:meta[0]", | ||
| 580 | }, | ||
| 581 | } | ||
| 582 | if exec.ShouldPrepareRequestAuth(authConfigDCA) { | ||
| 583 | t.Errorf("ShouldPrepareRequestAuth should be false for config API key auths") | ||
| 584 | } | ||
| 585 | |||
| 575 | authDCAOnly := &cliproxyauth.Auth{ | 586 | authDCAOnly := &cliproxyauth.Auth{ |
| 576 | ID: "meta-prep-test", | 587 | ID: "meta-prep-test", |
| 577 | Provider: "meta", | 588 | Provider: "meta", |