package plugin import ( "encoding/json" "fmt" "net/http" "net/http/httptest" "net/url" "path/filepath" "strings" "testing" "time" ) func managementCall(t *testing.T, app *App, method, path string) ManagementResponse { return managementCallBody(t, app, method, path, nil) } func managementCallBody(t *testing.T, app *App, method, path string, body []byte) ManagementResponse { return managementCallRequest(t, app, ManagementRequest{Method: method, Path: path, Body: body}) } func managementCallRequest(t *testing.T, app *App, requestValue ManagementRequest) ManagementResponse { t.Helper() request, err := json.Marshal(requestValue) if err != nil { t.Fatal(err) } raw, err := app.HandleMethod(MethodManagementHandle, request) if err != nil { t.Fatal(err) } var envelope Envelope if err := json.Unmarshal(raw, &envelope); err != nil { t.Fatal(err) } var response ManagementResponse if err := json.Unmarshal(envelope.Result, &response); err != nil { t.Fatal(err) } return response } func TestManagementRegistrationDeclaresUsageAPIAndUI(t *testing.T) { raw, err := NewApp().HandleMethod(MethodManagementRegister, nil) if err != nil { t.Fatal(err) } var envelope Envelope if err := json.Unmarshal(raw, &envelope); err != nil { t.Fatal(err) } var registration ManagementRegistrationResponse if err := json.Unmarshal(envelope.Result, ®istration); err != nil { t.Fatal(err) } if len(registration.Routes) != 19 || registration.Routes[0].Path != managementBase+routeUsage || registration.Routes[1].Path != managementBase+routeUsageSummary || registration.Routes[2].Path != managementBase+routePrices || registration.Routes[18].Path != managementBase+routeEvents { t.Fatalf("unexpected management routes: %+v", registration.Routes) } if len(registration.Resources) != 1+len(resourceAssets) || registration.Resources[0].Path != resourceBase+resourceUI { t.Fatalf("unexpected resource routes: %+v", registration.Resources) } for index, path := range resourceAssets { if registration.Resources[index+1].Path != resourceBase+path { t.Fatalf("resource %d = %q, want %q", index+1, registration.Resources[index+1].Path, resourceBase+path) } } } func TestBusinessEventsPersistSuccessfulAndFailedManagementActions(t *testing.T) { app := NewApp() defer app.Shutdown() if _, err := app.HandleMethod(MethodPluginRegister, lifecycleRequest(t, SchemaVersion, testConfig(t, "enabled: true\ncodex_only: false\n"))); err != nil { t.Fatal(err) } created := managementCallBody(t, app, http.MethodPost, managementBase+routeKeys, []byte(`{"name":"Alice","secret":"alice-000000"}`)) if created.StatusCode != http.StatusCreated { t.Fatalf("create status=%d body=%s", created.StatusCode, created.Body) } failed := managementCallBody(t, app, http.MethodPost, managementBase+routeKeys, []byte(`{"name":"","secret":"secret-000000"}`)) if failed.StatusCode != http.StatusBadRequest { t.Fatalf("failed create status=%d body=%s", failed.StatusCode, failed.Body) } resetAll := managementCallBody(t, app, http.MethodPost, managementBase+routeBillingReset, []byte(`{"all":true}`)) if resetAll.StatusCode != http.StatusOK || !strings.Contains(string(resetAll.Body), `"reset_count":2`) { t.Fatalf("reset all status=%d body=%s", resetAll.StatusCode, resetAll.Body) } events := managementCall(t, app, http.MethodGet, managementBase+routeEvents) body := string(events.Body) if events.StatusCode != http.StatusOK || !strings.Contains(body, "管理员创建用户 `Alice` 的 Key") || !strings.Contains(body, `"status":"成功"`) || !strings.Contains(body, `"status":"失败:Key 名称必须为 1-64 个字符"`) || !strings.Contains(body, `"status":"成功,处理 2 个用户"`) { t.Fatalf("events status=%d body=%s", events.StatusCode, body) } if strings.Contains(body, "alice-000000") || strings.Contains(body, "secret-000000") { t.Fatalf("business events exposed a key: %s", body) } readOnly := managementCallRequest(t, app, ManagementRequest{Method: http.MethodGet, Path: resourceBase + resourceUI, Query: url.Values{"view": {"events"}}}) if readOnly.StatusCode != http.StatusOK || !strings.Contains(string(readOnly.Body), "管理员创建用户 `Alice` 的 Key") { t.Fatalf("read-only events status=%d body=%s", readOnly.StatusCode, readOnly.Body) } } func TestReadOnlyResourceReturnsRealDataWithoutSecrets(t *testing.T) { app := NewApp() defer app.Shutdown() if _, err := app.HandleMethod(MethodPluginRegister, lifecycleRequest(t, SchemaVersion, testConfig(t, "enabled: true\ncodex_only: false\n"))); err != nil { t.Fatal(err) } keys := managementCallRequest(t, app, ManagementRequest{ Method: http.MethodGet, Path: resourceBase + resourceUI, Query: url.Values{"view": {"keys"}}, }) if keys.StatusCode != http.StatusOK || !strings.Contains(string(keys.Body), `"masked_secret":"00******0000"`) { t.Fatalf("unexpected read-only keys: status=%d body=%s", keys.StatusCode, keys.Body) } if strings.Contains(string(keys.Body), `"secret":`) { t.Fatalf("read-only response exposed a complete secret: %s", keys.Body) } usageRaw, _ := json.Marshal(UsageRecord{Provider: "openai", Model: "gpt-test", APIKey: "000000", RequestedAt: time.Now(), Detail: UsageDetail{TotalTokens: 1}}) if _, err := app.HandleMethod(MethodUsageHandle, usageRaw); err != nil { t.Fatal(err) } usage := managementCallRequest(t, app, ManagementRequest{ Method: http.MethodGet, Path: resourceBase + resourceUI, Query: url.Values{"view": {"usage"}, "page": {"9"}, "page_size": {"100"}}, }) if usage.StatusCode != http.StatusOK || strings.Contains(string(usage.Body), `"api_key":"000000"`) { t.Fatalf("read-only usage exposed a historical key: status=%d body=%s", usage.StatusCode, usage.Body) } var readOnlyPayload usageListResponse if err := json.Unmarshal(usage.Body, &readOnlyPayload); err != nil { t.Fatal(err) } if readOnlyPayload.Pagination.Page != 1 || readOnlyPayload.Pagination.PageSize != 50 { t.Fatalf("read-only usage pagination=%+v", readOnlyPayload.Pagination) } invalid := managementCallRequest(t, app, ManagementRequest{ Method: http.MethodGet, Path: resourceBase + resourceUI, Query: url.Values{"view": {"missing"}}, }) if invalid.StatusCode != http.StatusBadRequest || !strings.Contains(string(invalid.Body), `"code":"invalid_view"`) { t.Fatalf("unexpected invalid view response: status=%d body=%s", invalid.StatusCode, invalid.Body) } } func TestModelsDevCatalogRequiresExplicitImportAndConfirmedRefresh(t *testing.T) { catalogBody := `{"providers":{"openai":{"id":"openai","name":"OpenAI","models":{"gpt-5.6-sol":{"id":"gpt-5.6-sol","name":"GPT-5.6 Sol","cost":{"input":5,"output":30,"cache_read":0.5,"cache_write":6.25}}}},"free":{"id":"free","name":"Free","models":{"placeholder":{"id":"placeholder","cost":{"input":0,"output":0}}}}}}` serverStatus := http.StatusOK server := httptest.NewServer(http.HandlerFunc(func(response http.ResponseWriter, _ *http.Request) { response.WriteHeader(serverStatus) _, _ = response.Write([]byte(catalogBody)) })) defer server.Close() directory := t.TempDir() config := fmt.Sprintf("database_path: %q\nmodels_dev_url: %q\nmodels_dev_cache_path: %q\nenabled: true\ncodex_only: false\n", filepath.Join(directory, "usage.db"), server.URL, filepath.Join(directory, "catalog.json")) app := NewApp() defer app.Shutdown() if _, err := app.HandleMethod(MethodPluginRegister, lifecycleRequest(t, SchemaVersion, config)); err != nil { t.Fatal(err) } status := managementCallRequest(t, app, ManagementRequest{Method: http.MethodGet, Path: managementBase + routeCatalog, Query: url.Values{"q": {"gpt"}}}) if status.StatusCode != http.StatusOK || !strings.Contains(string(status.Body), `"loaded":false`) { t.Fatalf("catalog status=%d body=%s", status.StatusCode, status.Body) } refresh := managementCall(t, app, http.MethodPost, managementBase+routeCatalogRefresh) if refresh.StatusCode != http.StatusOK || !strings.Contains(string(refresh.Body), `"changed":0`) { t.Fatalf("initial refresh status=%d body=%s", refresh.StatusCode, refresh.Body) } search := managementCallRequest(t, app, ManagementRequest{Method: http.MethodGet, Path: managementBase + routeCatalog, Query: url.Values{"q": {"gpt-5.6"}}}) if search.StatusCode != http.StatusOK || !strings.Contains(string(search.Body), `"id":"openai/gpt-5.6-sol"`) || strings.Contains(string(search.Body), "placeholder") { t.Fatalf("catalog search status=%d body=%s", search.StatusCode, search.Body) } imported := managementCallBody(t, app, http.MethodPost, managementBase+routePriceImport, []byte(`{"model":"deepseek-v4-flash","catalog_id":"openai/gpt-5.6-sol"}`)) if imported.StatusCode != http.StatusOK || !strings.Contains(string(imported.Body), `"input_per_1m":"5"`) || !strings.Contains(string(imported.Body), `"kind":"models.dev"`) { t.Fatalf("catalog import status=%d body=%s", imported.StatusCode, imported.Body) } catalogBody = strings.Replace(catalogBody, `"input":5`, `"input":6`, 1) preview := managementCall(t, app, http.MethodPost, managementBase+routeCatalogRefresh) if preview.StatusCode != http.StatusOK || !strings.Contains(string(preview.Body), `"changed":1`) || !strings.Contains(string(preview.Body), `"input_per_1m":"6"`) { t.Fatalf("refresh preview status=%d body=%s", preview.StatusCode, preview.Body) } pricesBefore := managementCall(t, app, http.MethodGet, managementBase+routePrices) if !strings.Contains(string(pricesBefore.Body), `"input_per_1m":"5"`) { t.Fatalf("preview silently changed local price: %s", pricesBefore.Body) } var previewPayload struct { Catalog struct { Revision string `json:"revision"` } `json:"catalog"` } if err := json.Unmarshal(preview.Body, &previewPayload); err != nil { t.Fatal(err) } applyBody, _ := json.Marshal(map[string]any{"revision": previewPayload.Catalog.Revision, "models": []string{"deepseek-v4-flash"}}) applied := managementCallBody(t, app, http.MethodPost, managementBase+routeCatalogApply, applyBody) if applied.StatusCode != http.StatusOK || !strings.Contains(string(applied.Body), `"updated":1`) { t.Fatalf("catalog apply status=%d body=%s", applied.StatusCode, applied.Body) } pricesAfter := managementCall(t, app, http.MethodGet, managementBase+routePrices) if !strings.Contains(string(pricesAfter.Body), `"input_per_1m":"6"`) { t.Fatalf("confirmed price was not applied: %s", pricesAfter.Body) } manual := []byte(`{"model":"deepseek-v4-flash","base":{"input_per_1m":"7","cache_read_per_1m":"0.5","cache_write_per_1m":"6.25","output_per_1m":"30"},"fast_pricing_enabled":false,"fast_multiplier":"2.5"}`) if response := managementCallBody(t, app, http.MethodPut, managementBase+routePrices, manual); response.StatusCode != http.StatusOK || !strings.Contains(string(response.Body), `"kind":"manual"`) { t.Fatalf("manual save status=%d body=%s", response.StatusCode, response.Body) } catalogBody = strings.Replace(catalogBody, `"input":6`, `"input":8`, 1) manualPreview := managementCall(t, app, http.MethodPost, managementBase+routeCatalogRefresh) if manualPreview.StatusCode != http.StatusOK || !strings.Contains(string(manualPreview.Body), `"changed":0`) { t.Fatalf("manual price followed catalog: status=%d body=%s", manualPreview.StatusCode, manualPreview.Body) } serverStatus = http.StatusBadGateway failed := managementCall(t, app, http.MethodPost, managementBase+routeCatalogRefresh) if failed.StatusCode != http.StatusBadGateway { t.Fatalf("failed refresh status=%d body=%s", failed.StatusCode, failed.Body) } lastGood := managementCallRequest(t, app, ManagementRequest{Method: http.MethodGet, Path: managementBase + routeCatalog, Query: url.Values{"q": {"gpt"}}}) if lastGood.StatusCode != http.StatusOK || !strings.Contains(string(lastGood.Body), `"loaded":true`) || !strings.Contains(string(lastGood.Body), `"input_per_1m":"8"`) { t.Fatalf("last-known-good catalog unavailable: status=%d body=%s", lastGood.StatusCode, lastGood.Body) } } func TestUsageManagementSupportsServerPaginationFiltersAndSummary(t *testing.T) { app := NewApp() if _, err := app.HandleMethod(MethodPluginRegister, lifecycleRequest(t, SchemaVersion, testConfig(t, "enabled: true\ncodex_only: false\n"))); err != nil { t.Fatal(err) } base := time.Date(2026, 8, 15, 8, 0, 0, 0, time.UTC) for index := 0; index < 205; index++ { record := UsageRecord{Provider: "openai", Model: fmt.Sprintf("model-%d", index%2), AuthID: fmt.Sprintf("auth-%d", index%2), RequestedAt: base.Add(time.Duration(index) * time.Second), Failed: index%10 == 0, Detail: UsageDetail{TotalTokens: int64(index + 1)}} raw, _ := json.Marshal(record) if _, err := app.HandleMethod(MethodUsageHandle, raw); err != nil { t.Fatal(err) } } response := managementCallRequest(t, app, ManagementRequest{Method: http.MethodGet, Path: managementBase + routeUsage, Query: url.Values{"page": {"2"}, "page_size": {"100"}, "model": {"model-1"}}}) if response.StatusCode != http.StatusOK { t.Fatalf("usage query status=%d body=%s", response.StatusCode, response.Body) } var payload usageListResponse if err := json.Unmarshal(response.Body, &payload); err != nil { t.Fatal(err) } if payload.Pagination.Total != 102 || payload.Pagination.Page != 2 || payload.Pagination.TotalPages != 2 || len(payload.Records) != 2 { t.Fatalf("unexpected paginated response: %+v", payload.Pagination) } if payload.Records[0].Model != "model-1" || payload.Records[1].Model != "model-1" { t.Fatalf("filter leaked records: %+v", payload.Records) } invalid := managementCallRequest(t, app, ManagementRequest{Method: http.MethodGet, Path: managementBase + routeUsage, Query: url.Values{"page_size": {"101"}}}) if invalid.StatusCode != http.StatusBadRequest { t.Fatalf("invalid page size status=%d", invalid.StatusCode) } summary := managementCall(t, app, http.MethodGet, managementBase+routeUsageSummary) if summary.StatusCode != http.StatusOK || !strings.Contains(string(summary.Body), `"users"`) || !strings.Contains(string(summary.Body), `"days"`) { t.Fatalf("unexpected summary: status=%d body=%s", summary.StatusCode, summary.Body) } } func TestFormatMicrosSupportsNegativeBalances(t *testing.T) { if got := formatMicros(-125_000); got != "-0.125" { t.Fatalf("formatMicros(-125000)=%q", got) } } func TestPriceManagementCalculatesUsageWithLongContextAndFastPolicy(t *testing.T) { app := NewApp() if _, err := app.HandleMethod(MethodPluginRegister, lifecycleRequest(t, SchemaVersion, testConfig(t, "enabled: true\ncodex_only: true\n"))); err != nil { t.Fatal(err) } priceBody := []byte(`{ "model":"gpt-5.6-sol", "base":{"input_per_1m":"2.5","cache_read_per_1m":"0.25","cache_write_per_1m":"3.125","output_per_1m":"15"}, "long_context":{"threshold_input_tokens":272000,"comparison":"gt","input_per_1m":"5","cache_read_per_1m":"0.5","cache_write_per_1m":"6.25","output_per_1m":"22.5"}, "fast_pricing_enabled":true, "fast_multiplier":"2.5" }`) response := managementCallBody(t, app, http.MethodPut, managementBase+routePrices, priceBody) if response.StatusCode != http.StatusOK { t.Fatalf("put price status = %d, body = %s", response.StatusCode, response.Body) } record := UsageRecord{ Provider: "codex", Model: "gpt-5.6-sol", ServiceTier: "priority", RequestedAt: time.Now(), Detail: UsageDetail{InputTokens: 272_001, OutputTokens: 10_000, TotalTokens: 282_001}, } raw, _ := json.Marshal(record) if _, err := app.HandleMethod(MethodUsageHandle, raw); err != nil { t.Fatal(err) } usageResponse := managementCall(t, app, http.MethodGet, managementBase+routeUsage) var payload usageListResponse if err := json.Unmarshal(usageResponse.Body, &payload); err != nil { t.Fatal(err) } got := payload.Records[0] if !got.CostAvailable || got.CostUSD == nil || *got.CostUSD != 3.962513 || got.PriceTier != "long_context" || !got.FastRequested || !got.FastPricingApplied { t.Fatalf("unexpected priced usage: %+v", got) } pricesResponse := managementCall(t, app, http.MethodGet, managementBase+routePrices) if pricesResponse.StatusCode != http.StatusOK || !strings.Contains(string(pricesResponse.Body), `"fast_multiplier":"2.5"`) { t.Fatalf("unexpected prices response: %d %s", pricesResponse.StatusCode, pricesResponse.Body) } } func TestFastRequestCanUseStandardPricing(t *testing.T) { app := NewApp() if _, err := app.HandleMethod(MethodPluginRegister, lifecycleRequest(t, SchemaVersion, testConfig(t, "enabled: true\ncodex_only: true\n"))); err != nil { t.Fatal(err) } priceBody := []byte(`{"model":"gpt-5.6-sol","base":{"input_per_1m":"2.5","cache_read_per_1m":"0.25","cache_write_per_1m":"3.125","output_per_1m":"15"},"fast_pricing_enabled":false,"fast_multiplier":"2.5"}`) if response := managementCallBody(t, app, http.MethodPut, managementBase+routePrices, priceBody); response.StatusCode != http.StatusOK { t.Fatalf("put price status = %d, body = %s", response.StatusCode, response.Body) } record := UsageRecord{Provider: "codex", Model: "gpt-5.6-sol", ServiceTier: "fast", RequestedAt: time.Now(), Detail: UsageDetail{InputTokens: 100_000, TotalTokens: 100_000}} raw, _ := json.Marshal(record) if _, err := app.HandleMethod(MethodUsageHandle, raw); err != nil { t.Fatal(err) } response := managementCall(t, app, http.MethodGet, managementBase+routeUsage) var payload usageListResponse if err := json.Unmarshal(response.Body, &payload); err != nil { t.Fatal(err) } got := payload.Records[0] if got.CostUSD == nil || *got.CostUSD != 0.25 || !got.FastRequested || got.FastPricingApplied { t.Fatalf("unexpected standard-priced Fast usage: %+v", got) } } func TestCanceledRequestWithoutUsageRemainsVisible(t *testing.T) { app := NewApp() if _, err := app.HandleMethod(MethodPluginRegister, lifecycleRequest(t, SchemaVersion, testConfig(t, "enabled: true\ncodex_only: false\n"))); err != nil { t.Fatal(err) } startedAt := time.Date(2026, 8, 14, 12, 0, 0, 0, time.UTC) completion := RequestCompletion{ RequestID: "request-canceled", TraceID: "trace-canceled", SourceFormat: "openai-response", Model: "deepseek-v4-flash", RequestedModel: "deepseek-flash", Stream: true, Outcome: RequestCompletionCanceled, StatusCode: 499, Error: "context canceled", StartedAt: startedAt, CompletedAt: startedAt.Add(2 * time.Second), Metadata: map[string]any{"request_path": "/v1/responses"}, } raw, _ := json.Marshal(completion) if _, err := app.HandleMethod(MethodRequestComplete, raw); err != nil { t.Fatal(err) } response := managementCall(t, app, http.MethodGet, managementBase+routeUsage) var payload usageListResponse if err := json.Unmarshal(response.Body, &payload); err != nil { t.Fatal(err) } if len(payload.Records) != 1 { t.Fatalf("records = %d, want 1", len(payload.Records)) } got := payload.Records[0] if got.RequestID != "request-canceled" || got.TraceID != "trace-canceled" || got.Outcome != "canceled" || !got.Failed || got.StatusCode != 499 || got.RequestType != "SSE" || got.CostAvailable { t.Fatalf("unexpected canceled request: %+v", got) } } func TestCompactUsageIsZeroPricedAndUsesJSONMetrics(t *testing.T) { app := NewApp() if _, err := app.HandleMethod(MethodPluginRegister, lifecycleRequest(t, SchemaVersion, testConfig(t, "enabled: true\ncodex_only: false\n"))); err != nil { t.Fatal(err) } priceBody := []byte(`{"model":"deepseek-v4-flash","base":{"input_per_1m":"2.5","cache_read_per_1m":"0.25","cache_write_per_1m":"3.125","output_per_1m":"15"},"fast_pricing_enabled":true,"fast_multiplier":"2.5"}`) if response := managementCallBody(t, app, http.MethodPut, managementBase+routePrices, priceBody); response.StatusCode != http.StatusOK { t.Fatalf("put price status = %d, body = %s", response.StatusCode, response.Body) } startedAt := time.Now() interceptRaw, _ := json.Marshal(RequestInterceptRequest{ RequestID: "compact-success", Body: []byte(`{"model":"deepseek-v4-flash"}`), Metadata: map[string]any{"request_path": "/v1/responses/compact"}, }) if _, err := app.HandleMethod(MethodRequestBefore, interceptRaw); err != nil { t.Fatal(err) } record := UsageRecord{ RequestID: "compact-success", Provider: "openai", Model: "deepseek-v4-flash", RequestedAt: startedAt, Latency: time.Second, TTFT: 200 * time.Millisecond, Detail: UsageDetail{InputTokens: 1_000, OutputTokens: 100, TotalTokens: 1_100}, } raw, _ := json.Marshal(record) if _, err := app.HandleMethod(MethodUsageHandle, raw); err != nil { t.Fatal(err) } completionRaw, _ := json.Marshal(RequestCompletion{ RequestID: "compact-success", Model: "deepseek-v4-flash", Outcome: RequestCompletionSucceeded, StartedAt: startedAt, CompletedAt: startedAt.Add(time.Second), Metadata: map[string]any{"request_path": "/v1/responses/compact"}, }) if _, err := app.HandleMethod(MethodRequestComplete, completionRaw); err != nil { t.Fatal(err) } response := managementCall(t, app, http.MethodGet, managementBase+routeUsage) var payload usageListResponse if err := json.Unmarshal(response.Body, &payload); err != nil { t.Fatal(err) } if len(payload.Records) != 1 { t.Fatalf("records = %d, want 1", len(payload.Records)) } got := payload.Records[0] if got.RequestType != "JSON" || got.Endpoint != "/v1/responses/compact" || got.TTFTMilliseconds != 0 || got.SpeedTPS != nil { t.Fatalf("unexpected compact metadata: %+v", got) } if !got.CostAvailable || got.CostUSD == nil || *got.CostUSD != 0 { t.Fatalf("unexpected compact cost: %+v", got) } } func TestRemoteV2CompactTriggerDisplaysCompactAndCostsZero(t *testing.T) { app := NewApp() if _, err := app.HandleMethod(MethodPluginRegister, lifecycleRequest(t, SchemaVersion, testConfig(t, "enabled: true\ncodex_only: false\n"))); err != nil { t.Fatal(err) } priceBody := []byte(`{"model":"gpt-5.6-sol","base":{"input_per_1m":"2.5","cache_read_per_1m":"0.25","cache_write_per_1m":"3.125","output_per_1m":"15"}}`) if response := managementCallBody(t, app, http.MethodPut, managementBase+routePrices, priceBody); response.StatusCode != http.StatusOK { t.Fatalf("put price status = %d, body = %s", response.StatusCode, response.Body) } startedAt := time.Now() interceptRaw, _ := json.Marshal(RequestInterceptRequest{ RequestID: "compact-v2", Model: "gpt-5.6-sol", Stream: true, Body: []byte(`{"model":"gpt-5.6-sol","input":[{"type":"message","role":"user","content":"history"},{"type":"compaction_trigger"}]}`), Metadata: map[string]any{"request_path": "/v1/responses"}, }) if _, err := app.HandleMethod(MethodRequestBefore, interceptRaw); err != nil { t.Fatal(err) } usageRaw, _ := json.Marshal(UsageRecord{ RequestID: "compact-v2", Provider: "codex", Model: "gpt-5.6-sol", RequestedAt: startedAt, Latency: time.Second, TTFT: 200 * time.Millisecond, Detail: UsageDetail{InputTokens: 17_235, OutputTokens: 144, TotalTokens: 17_379}, }) if _, err := app.HandleMethod(MethodUsageHandle, usageRaw); err != nil { t.Fatal(err) } completionRaw, _ := json.Marshal(RequestCompletion{ RequestID: "compact-v2", Model: "gpt-5.6-sol", Stream: true, Outcome: RequestCompletionSucceeded, StartedAt: startedAt, CompletedAt: startedAt.Add(time.Second), Metadata: map[string]any{"request_path": "/v1/responses"}, }) if _, err := app.HandleMethod(MethodRequestComplete, completionRaw); err != nil { t.Fatal(err) } response := managementCall(t, app, http.MethodGet, managementBase+routeUsage) var payload usageListResponse if err := json.Unmarshal(response.Body, &payload); err != nil { t.Fatal(err) } if len(payload.Records) != 1 { t.Fatalf("records = %d, want 1", len(payload.Records)) } got := payload.Records[0] if got.Endpoint != compactEndpoint || got.TTFTMilliseconds != 0 || got.SpeedTPS != nil { t.Fatalf("unexpected compact v2 metadata: %+v", got) } if !got.CostAvailable || got.CostUSD == nil || *got.CostUSD != 0 { t.Fatalf("unexpected compact v2 cost: %+v", got) } } func TestCompactFailureAndCancellationRemainVisible(t *testing.T) { for _, test := range []struct { name string outcome RequestCompletionOutcome statusCode int }{ {name: "failed", outcome: RequestCompletionFailed, statusCode: 500}, {name: "canceled", outcome: RequestCompletionCanceled, statusCode: 499}, } { t.Run(test.name, func(t *testing.T) { app := NewApp() if _, err := app.HandleMethod(MethodPluginRegister, lifecycleRequest(t, SchemaVersion, testConfig(t, "enabled: true\ncodex_only: false\n"))); err != nil { t.Fatal(err) } startedAt := time.Date(2026, 8, 14, 12, 0, 0, 0, time.UTC) completion := RequestCompletion{ RequestID: "compact-" + test.name, Model: "deepseek-v4-flash", Stream: false, Outcome: test.outcome, StatusCode: test.statusCode, Error: test.name, StartedAt: startedAt, CompletedAt: startedAt.Add(time.Second), Metadata: map[string]any{"request_path": "/v1/responses/compact"}, } raw, _ := json.Marshal(completion) if _, err := app.HandleMethod(MethodRequestComplete, raw); err != nil { t.Fatal(err) } response := managementCall(t, app, http.MethodGet, managementBase+routeUsage) var payload usageListResponse if err := json.Unmarshal(response.Body, &payload); err != nil { t.Fatal(err) } if len(payload.Records) != 1 { t.Fatalf("records = %d, want 1", len(payload.Records)) } got := payload.Records[0] if got.Outcome != string(test.outcome) || !got.Failed || got.StatusCode != test.statusCode || got.RequestType != "JSON" || got.Endpoint != "/v1/responses/compact" || got.SpeedTPS != nil || got.CostAvailable { t.Fatalf("unexpected compact terminal record: %+v", got) } }) } } func TestUsageAndLifecycleMergeInEitherOrderAndDeduplicateUsage(t *testing.T) { for _, usageFirst := range []bool{true, false} { app := NewApp() if _, err := app.HandleMethod(MethodPluginRegister, lifecycleRequest(t, SchemaVersion, testConfig(t, "enabled: true\ncodex_only: false\n"))); err != nil { t.Fatal(err) } startedAt := time.Date(2026, 8, 14, 12, 0, 0, 0, time.UTC) usage := UsageRecord{Provider: "openai", Model: "deepseek-v4-flash", RequestedAt: startedAt, Detail: UsageDetail{InputTokens: 10, TotalTokens: 10}} completion := RequestCompletion{ RequestID: "request-1", TraceID: "trace-1", Model: "deepseek-v4-flash", Outcome: RequestCompletionFailed, StatusCode: 500, Error: "upstream failed", StartedAt: startedAt, CompletedAt: startedAt.Add(time.Second), } usageRaw, _ := json.Marshal(usage) completionRaw, _ := json.Marshal(completion) calls := []struct { method string raw []byte }{{MethodUsageHandle, usageRaw}, {MethodRequestComplete, completionRaw}} if !usageFirst { calls[0], calls[1] = calls[1], calls[0] } for _, call := range calls { if _, err := app.HandleMethod(call.method, call.raw); err != nil { t.Fatal(err) } } // 重复的 Usage 回调不能生成第二条执行记录。 if _, err := app.HandleMethod(MethodUsageHandle, usageRaw); err != nil { t.Fatal(err) } response := managementCall(t, app, http.MethodGet, managementBase+routeUsage) var payload usageListResponse if err := json.Unmarshal(response.Body, &payload); err != nil { t.Fatal(err) } if len(payload.Records) != 1 || payload.Records[0].RequestID != "request-1" || payload.Records[0].ExecutionID != "" || payload.Records[0].Outcome != "failed" || payload.Records[0].StatusCode != 500 { t.Fatalf("usageFirst=%v records=%+v", usageFirst, payload.Records) } } } func TestDistinctContractUsageEventsRemainSeparate(t *testing.T) { app := NewApp() if _, err := app.HandleMethod(MethodPluginRegister, lifecycleRequest(t, SchemaVersion, testConfig(t, "enabled: true\ncodex_only: false\n"))); err != nil { t.Fatal(err) } startedAt := time.Date(2026, 8, 14, 12, 0, 0, 0, time.UTC) for index, failed := range []bool{true, false} { usage := UsageRecord{ Provider: "openai", Model: "deepseek-v4-flash", RequestedAt: startedAt.Add(time.Duration(index) * time.Second), Failed: failed, Detail: UsageDetail{InputTokens: int64(10 + index), TotalTokens: int64(10 + index)}, } raw, _ := json.Marshal(usage) if _, err := app.HandleMethod(MethodUsageHandle, raw); err != nil { t.Fatal(err) } } completion := RequestCompletion{RequestID: "request-retry", Model: "deepseek-v4-flash", Outcome: RequestCompletionSucceeded, StartedAt: startedAt, CompletedAt: startedAt.Add(2 * time.Second)} raw, _ := json.Marshal(completion) if _, err := app.HandleMethod(MethodRequestComplete, raw); err != nil { t.Fatal(err) } response := managementCall(t, app, http.MethodGet, managementBase+routeUsage) var payload usageListResponse if err := json.Unmarshal(response.Body, &payload); err != nil { t.Fatal(err) } if len(payload.Records) != 2 || payload.Records[0].ExecutionID != "" || payload.Records[0].RequestID != "" || payload.Records[0].Failed || payload.Records[1].ExecutionID != "" || payload.Records[1].RequestID != "request-retry" || !payload.Records[1].Failed { t.Fatalf("unexpected usage records: %+v", payload.Records) } } func TestUsageManagementResponseContainsDisplayFields(t *testing.T) { app := NewApp() if _, err := app.HandleMethod(MethodPluginRegister, lifecycleRequest(t, SchemaVersion, testConfig(t, "enabled: true\ncodex_only: true\n"))); err != nil { t.Fatal(err) } startedAt := time.Date(2026, 8, 14, 12, 0, 0, 0, time.UTC) record := UsageRecord{ Provider: "codex", APIKey: "test-key", Model: "gpt-5.5", ReasoningEffort: "high", ServiceTier: "priority", ExecutorType: "CodexExecutor", RequestedAt: startedAt, Latency: 1500 * time.Millisecond, TTFT: 250 * time.Millisecond, Detail: UsageDetail{ InputTokens: 10, OutputTokens: 5, TotalTokens: 15, CachedTokens: 4, CacheReadTokens: 4, CacheCreationTokens: 1, ReasoningTokens: 2, }, } raw, _ := json.Marshal(record) if _, err := app.HandleMethod(MethodUsageHandle, raw); err != nil { t.Fatal(err) } completionRaw, _ := json.Marshal(RequestCompletion{ RequestID: "request-display", TraceID: "trace-display", Model: "gpt-5.5", Stream: true, Outcome: RequestCompletionSucceeded, StartedAt: startedAt, CompletedAt: startedAt.Add(1500 * time.Millisecond), Metadata: map[string]any{"request_path": "/v1/responses"}, }) if _, err := app.HandleMethod(MethodRequestComplete, completionRaw); err != nil { t.Fatal(err) } response := managementCall(t, app, http.MethodGet, managementBase+routeUsage) if response.StatusCode != http.StatusOK { t.Fatalf("status = %d, body = %s", response.StatusCode, response.Body) } var payload usageListResponse if err := json.Unmarshal(response.Body, &payload); err != nil { t.Fatal(err) } if len(payload.Records) != 1 { t.Fatalf("records = %d, want 1", len(payload.Records)) } got := payload.Records[0] if got.APIKey != "test-key" || got.Model != "gpt-5.5" || got.ReasoningEffort != "high" || got.ServiceTier != "priority" || got.ExecutorType != "CodexExecutor" { t.Fatalf("unexpected usage identity fields: %+v", got) } if got.RequestID != "request-display" || got.ExecutionID != "" || got.TraceID != "trace-display" || got.RequestType != "SSE" || got.Endpoint != "/v1/responses" || got.ClientIP != "" { t.Fatalf("unexpected request metadata: %+v", got) } if got.TotalTokens != 15 || got.TTFTMilliseconds != 250 || got.CacheReadTokens != 4 || got.CacheWriteTokens != 1 { t.Fatalf("unexpected usage counters: %+v", got) } if got.SpeedTPS == nil || *got.SpeedTPS != 4 || got.CacheRate == nil || *got.CacheRate != 40 { t.Fatalf("unexpected derived display fields: %+v", got) } if got.KeyAlias != "" || got.CostUSD != nil || got.CostAvailable { t.Fatalf("unexpected usage item: %+v", got) } } func TestUsageResourceServesFeatureModules(t *testing.T) { pageResponse := managementCall(t, NewApp(), http.MethodGet, resourceBase+resourceUI) page := string(pageResponse.Body) if pageResponse.StatusCode != http.StatusOK || !strings.Contains(page, `data-view="logs">日志`) { t.Fatalf("unexpected UI response: status=%d", pageResponse.StatusCode) } for _, feature := range []string{``, ``, `id="demo-perspective" class="demo-perspective hidden"`, `data-perspective="admin">管理员示教`, `data-perspective="user">普通用户视角`, `data-view="stats">统计`, `data-view="users">用户`, `id="view-users" class="view admin-only"`, `id="quota-chart"`, `id="quota-health"`, `id="page-buttons" class="page-buttons admin-only"`, `id="user-usage"`, `id="usage-filter-panel" class="usage-filter-panel admin-only"`, `id="refresh" class="admin-only"`, `id="editor-show-stats"`, `id="editor-quota"`, `id="billing-ledger"`, `id="key-management" class="user-management"`, `id="reset-all-billing"`, `id="key-rows" class="user-card-grid"`, `class="surface price-panel price-layout"`, `src="./ui-config.js"`, `type="module" src="./app/main.js"`, `href="./styles/base.css"`, `href="./styles/keys.css"`, `href="./styles/usage.css"`, `href="./styles/pricing.css"`} { if !strings.Contains(page, feature) { t.Fatalf("UI does not contain HTML feature %q", feature) } } for _, removed := range []string{`

Day

`, `

Week

`} { if strings.Contains(page, removed) { t.Fatalf("UI still contains removed card title %q", removed) } } if strings.Index(page, `id="page-buttons"`) > strings.Index(page, `id="headers"`) { t.Fatal("UI pagination controls are not above the usage table") } for _, path := range []string{"/styles/base.css", "/styles/layout.css", "/styles/keys.css", "/styles/usage.css", "/styles/pricing.css", "/styles/responsive.css"} { response := managementCall(t, NewApp(), http.MethodGet, resourceBase+path) if response.StatusCode != http.StatusOK || response.Headers.Get("Content-Type") != "text/css; charset=utf-8" || len(response.Body) == 0 { t.Fatalf("unexpected CSS resource %s: status=%d headers=%v", path, response.StatusCode, response.Headers) } } var javascript strings.Builder for _, path := range []string{"/app/main.js", "/app/core/runtime.js", "/app/core/shared.js", "/app/features/keys.js", "/app/features/usage.js", "/app/features/pricing.js"} { response := managementCall(t, NewApp(), http.MethodGet, resourceBase+path) if response.StatusCode != http.StatusOK || response.Headers.Get("Content-Type") != "text/javascript; charset=utf-8" { t.Fatalf("unexpected JS resource %s: status=%d headers=%v", path, response.StatusCode, response.Headers) } javascript.Write(response.Body) } for _, feature := range []string{"initializeRuntime", "dataFetch", "isManagementAuthorized", "adminPageSize = 100", "userPageSize = 50", `row.setAttribute("role", "button")`, "syncLongSectionVisibility", `return "compact"`, "isCompactEndpoint(record.endpoint)", `identity.title = "点击复制 Key"`, `return "自由选择"`, "今日使用", "剩余额度", "quotaAmount(item.cost)", "quotaAmount(item.balance)", "resetTime(item)", "show_in_stats", "renderQuotaHealth", `document.body.classList.toggle("read-only"`, "compactTokens(price.long_context.threshold_input_tokens)", "appendPriceRow(table, \"长上下文\", price.long_context, true)", `删除 ${model} 的真实价格配置`, `发现 ${changed.length} 个已关联价格发生变化`} { if !strings.Contains(javascript.String(), feature) { t.Fatalf("UI modules do not contain feature %q", feature) } } for _, removed := range []string{"DEMO_STORE_KEY", "demoState", "mode-button", `data-mode="demo"`, "scrollIntoView", "maskedSecret("} { if strings.Contains(javascript.String(), removed) { t.Fatalf("UI modules still contain removed feature %q", removed) } } usageResponse := managementCall(t, NewApp(), http.MethodGet, resourceBase+"/app/features/usage.js") usageModule := string(usageResponse.Body) if strings.Index(usageModule, "const columns =") > strings.Index(usageModule, "let visibleColumns = loadVisibleColumns()") { t.Fatal("usage module initializes visible columns before defining the column schema") } configResponse := managementCall(t, NewApp(), http.MethodGet, resourceBase+"/ui-config.js") if configResponse.StatusCode != http.StatusOK || !strings.Contains(string(configResponse.Body), "BILLING_UI_CONFIG") { t.Fatalf("unexpected UI config resource: status=%d", configResponse.StatusCode) } }