diff --git a/backend/internal/server/api_contract_test.go b/backend/internal/server/api_contract_test.go index 24b5ef68..17455410 100644 --- a/backend/internal/server/api_contract_test.go +++ b/backend/internal/server/api_contract_test.go @@ -788,14 +788,7 @@ func TestAPIContracts(t *testing.T) { "payment_visible_method_wxpay_enabled": false, "openai_advanced_scheduler_enabled": true, "openai_fast_policy_settings": { - "rules": [ - { - "service_tier": "priority", - "action": "filter", - "scope": "all", - "fallback_action": "pass" - } - ] + "rules": [] }, "custom_menu_items": [], "custom_endpoints": [], @@ -1003,14 +996,7 @@ func TestAPIContracts(t *testing.T) { "payment_visible_method_wxpay_enabled": false, "openai_advanced_scheduler_enabled": false, "openai_fast_policy_settings": { - "rules": [ - { - "service_tier": "priority", - "action": "filter", - "scope": "all", - "fallback_action": "pass" - } - ] + "rules": [] }, "payment_enabled": false, "payment_min_amount": 0, diff --git a/backend/internal/service/openai_fast_policy_test.go b/backend/internal/service/openai_fast_policy_test.go index b52da614..70fcaffa 100644 --- a/backend/internal/service/openai_fast_policy_test.go +++ b/backend/internal/service/openai_fast_policy_test.go @@ -8,6 +8,7 @@ import ( "github.com/Wei-Shaw/sub2api/internal/config" "github.com/stretchr/testify/require" + "github.com/tidwall/gjson" ) type openAIFastPolicyRepoStub struct { @@ -62,25 +63,33 @@ func newOpenAIGatewayServiceWithSettings(t *testing.T, settings *OpenAIFastPolic } } -func TestEvaluateOpenAIFastPolicy_DefaultFiltersAllModelsPriority(t *testing.T) { +func openAIFastFilterPriorityPolicy() *OpenAIFastPolicySettings { + return &OpenAIFastPolicySettings{ + Rules: []OpenAIFastPolicyRule{{ + ServiceTier: OpenAIFastTierPriority, + Action: BetaPolicyActionFilter, + Scope: BetaPolicyScopeAll, + ModelWhitelist: []string{}, + FallbackAction: BetaPolicyActionPass, + }}, + } +} + +func TestEvaluateOpenAIFastPolicy_DefaultPassesKnownTiers(t *testing.T) { + require.Empty(t, DefaultOpenAIFastPolicySettings().Rules, "default policy must not rewrite service_tier unless admin configured rules") + svc := newOpenAIGatewayServiceWithSettings(t, DefaultOpenAIFastPolicySettings()) account := &Account{Platform: PlatformOpenAI, Type: AccountTypeAPIKey} - // 默认策略对所有模型生效(whitelist 为空),因为 codex 的 service_tier=fast - // 是用户级开关,与 model 正交。 - // gpt-5.5 + priority → filter action, _ := svc.evaluateOpenAIFastPolicy(context.Background(), account, "gpt-5.5", OpenAIFastTierPriority) - require.Equal(t, BetaPolicyActionFilter, action) + require.Equal(t, BetaPolicyActionPass, action) - // gpt-5.5-turbo → filter action, _ = svc.evaluateOpenAIFastPolicy(context.Background(), account, "gpt-5.5-turbo", OpenAIFastTierPriority) - require.Equal(t, BetaPolicyActionFilter, action) + require.Equal(t, BetaPolicyActionPass, action) - // gpt-4 + priority → filter(默认策略覆盖所有模型) action, _ = svc.evaluateOpenAIFastPolicy(context.Background(), account, "gpt-4", OpenAIFastTierPriority) - require.Equal(t, BetaPolicyActionFilter, action) + require.Equal(t, BetaPolicyActionPass, action) - // gpt-5.5 + flex → pass (tier doesn't match) action, _ = svc.evaluateOpenAIFastPolicy(context.Background(), account, "gpt-5.5", OpenAIFastTierFlex) require.Equal(t, BetaPolicyActionPass, action) @@ -129,27 +138,24 @@ func TestEvaluateOpenAIFastPolicy_ScopeFiltersOAuth(t *testing.T) { require.Equal(t, BetaPolicyActionPass, action) } -func TestApplyOpenAIFastPolicyToBody_FilterRemovesField(t *testing.T) { +func TestApplyOpenAIFastPolicyToBody_DefaultPassesPriorityAndFast(t *testing.T) { svc := newOpenAIGatewayServiceWithSettings(t, DefaultOpenAIFastPolicySettings()) account := &Account{Platform: PlatformOpenAI, Type: AccountTypeAPIKey} - // gpt-5.5 fast → service_tier stripped body := []byte(`{"model":"gpt-5.5","service_tier":"priority","messages":[]}`) updated, err := svc.applyOpenAIFastPolicyToBody(context.Background(), account, "gpt-5.5", body) require.NoError(t, err) - require.NotContains(t, string(updated), `"service_tier"`) + require.Equal(t, string(body), string(updated)) - // Client sending "fast" (alias for priority) also filtered body = []byte(`{"model":"gpt-5.5","service_tier":"fast"}`) updated, err = svc.applyOpenAIFastPolicyToBody(context.Background(), account, "gpt-5.5", body) require.NoError(t, err) - require.NotContains(t, string(updated), `"service_tier"`) + require.Equal(t, "priority", gjson.GetBytes(updated, "service_tier").String()) - // gpt-4 priority → 默认策略对所有模型 filter,service_tier 被移除 body = []byte(`{"model":"gpt-4","service_tier":"priority"}`) updated, err = svc.applyOpenAIFastPolicyToBody(context.Background(), account, "gpt-4", body) require.NoError(t, err) - require.NotContains(t, string(updated), `"service_tier"`) + require.Equal(t, string(body), string(updated)) // No service_tier → no-op body = []byte(`{"model":"gpt-5.5"}`) @@ -158,9 +164,23 @@ func TestApplyOpenAIFastPolicyToBody_FilterRemovesField(t *testing.T) { require.Equal(t, string(body), string(updated)) } -// TestApplyOpenAIFastPolicyToBody_OfficialTiersBypassDefaultRule 验证扩展白名单后 -// 客户端显式发送的 OpenAI 官方合法 tier(auto/default/scale)能透传到上游而不被 -// 静默剥离。默认策略只针对 priority,所以这些 tier 落在 fall-through pass 分支。 +func TestApplyOpenAIFastPolicyToBody_ExplicitFilterRemovesField(t *testing.T) { + svc := newOpenAIGatewayServiceWithSettings(t, openAIFastFilterPriorityPolicy()) + account := &Account{Platform: PlatformOpenAI, Type: AccountTypeAPIKey} + + body := []byte(`{"model":"gpt-5.5","service_tier":"priority","messages":[]}`) + updated, err := svc.applyOpenAIFastPolicyToBody(context.Background(), account, "gpt-5.5", body) + require.NoError(t, err) + require.NotContains(t, string(updated), `"service_tier"`) + + body = []byte(`{"model":"gpt-5.5","service_tier":"fast"}`) + updated, err = svc.applyOpenAIFastPolicyToBody(context.Background(), account, "gpt-5.5", body) + require.NoError(t, err) + require.NotContains(t, string(updated), `"service_tier"`) +} + +// TestApplyOpenAIFastPolicyToBody_OfficialTiersBypassDefaultRule 验证默认配置 +// 下客户端显式发送的 OpenAI 官方合法 tier 能透传到上游而不被静默剥离。 func TestApplyOpenAIFastPolicyToBody_OfficialTiersBypassDefaultRule(t *testing.T) { svc := newOpenAIGatewayServiceWithSettings(t, DefaultOpenAIFastPolicySettings()) account := &Account{Platform: PlatformOpenAI, Type: AccountTypeAPIKey} @@ -170,10 +190,10 @@ func TestApplyOpenAIFastPolicyToBody_OfficialTiersBypassDefaultRule(t *testing.T updated, err := svc.applyOpenAIFastPolicyToBody(context.Background(), account, "gpt-5.5", body) require.NoError(t, err, "tier %q should pass without error", tier) require.Contains(t, string(updated), `"service_tier":"`+tier+`"`, - "tier %q should be preserved in body under default rule", tier) + "tier %q should be preserved in body under default policy", tier) } - // evaluate 层也应判定为 pass(默认规则 ServiceTier=priority 与 auto/default/scale 不匹配) + // evaluate 层也应判定为 pass(默认配置没有内置规则)。 for _, tier := range []string{"auto", "default", "scale"} { action, _ := svc.evaluateOpenAIFastPolicy(context.Background(), account, "gpt-5.5", tier) require.Equal(t, BetaPolicyActionPass, action, "tier %q should evaluate to pass", tier) diff --git a/backend/internal/service/openai_fast_policy_ws_test.go b/backend/internal/service/openai_fast_policy_ws_test.go index 7c8341b2..4624e7a5 100644 --- a/backend/internal/service/openai_fast_policy_ws_test.go +++ b/backend/internal/service/openai_fast_policy_ws_test.go @@ -22,7 +22,7 @@ import ( // --- Helper-level (unit) tests for applyOpenAIFastPolicyToWSResponseCreate --- -func TestWSResponseCreate_FilterStripsServiceTier(t *testing.T) { +func TestWSResponseCreate_DefaultPassesPriorityAndNormalizesFast(t *testing.T) { svc := newOpenAIGatewayServiceWithSettings(t, DefaultOpenAIFastPolicySettings()) account := &Account{Platform: PlatformOpenAI, Type: AccountTypeAPIKey} @@ -30,26 +30,37 @@ func TestWSResponseCreate_FilterStripsServiceTier(t *testing.T) { updated, blocked, err := svc.applyOpenAIFastPolicyToWSResponseCreate(context.Background(), account, "gpt-5.5", frame) require.NoError(t, err) require.Nil(t, blocked) - require.NotContains(t, string(updated), `"service_tier"`, "filter action should strip service_tier") + require.Equal(t, "priority", gjson.GetBytes(updated, "service_tier").String(), "default policy should preserve priority tier") // Other fields preserved. require.Equal(t, "response.create", gjson.GetBytes(updated, "type").String()) require.Equal(t, "gpt-5.5", gjson.GetBytes(updated, "model").String()) require.Equal(t, "hi", gjson.GetBytes(updated, "input.0.text").String()) + + frame = []byte(`{"type":"response.create","model":"gpt-5.5","service_tier":"fast"}`) + updated, blocked, err = svc.applyOpenAIFastPolicyToWSResponseCreate(context.Background(), account, "gpt-5.5", frame) + require.NoError(t, err) + require.Nil(t, blocked) + require.Equal(t, "priority", gjson.GetBytes(updated, "service_tier").String(), "fast alias should normalize before reaching upstream") + + // Mixed-case + whitespace variant should also normalize. + frame = []byte(`{"type":"response.create","model":"gpt-5.5","service_tier":" Fast "}`) + updated, blocked, err = svc.applyOpenAIFastPolicyToWSResponseCreate(context.Background(), account, "gpt-5.5", frame) + require.NoError(t, err) + require.Nil(t, blocked) + require.Equal(t, "priority", gjson.GetBytes(updated, "service_tier").String()) } -func TestWSResponseCreate_FastNormalizedToPriorityThenFiltered(t *testing.T) { - svc := newOpenAIGatewayServiceWithSettings(t, DefaultOpenAIFastPolicySettings()) +func TestWSResponseCreate_ExplicitFilterStripsServiceTier(t *testing.T) { + svc := newOpenAIGatewayServiceWithSettings(t, openAIFastFilterPriorityPolicy()) account := &Account{Platform: PlatformOpenAI, Type: AccountTypeAPIKey} - // Verbatim "fast" → normalized to "priority" → matches default rule → filter. - frame := []byte(`{"type":"response.create","model":"gpt-5.5","service_tier":"fast"}`) + frame := []byte(`{"type":"response.create","model":"gpt-5.5","service_tier":"priority","input":[{"type":"input_text","text":"hi"}]}`) updated, blocked, err := svc.applyOpenAIFastPolicyToWSResponseCreate(context.Background(), account, "gpt-5.5", frame) require.NoError(t, err) require.Nil(t, blocked) - require.NotContains(t, string(updated), `"service_tier"`) + require.NotContains(t, string(updated), `"service_tier"`, "filter action should strip service_tier") - // Mixed-case + whitespace variant should also normalize and filter. - frame = []byte(`{"type":"response.create","model":"gpt-5.5","service_tier":" Fast "}`) + frame = []byte(`{"type":"response.create","model":"gpt-5.5","service_tier":"fast"}`) updated, blocked, err = svc.applyOpenAIFastPolicyToWSResponseCreate(context.Background(), account, "gpt-5.5", frame) require.NoError(t, err) require.Nil(t, blocked) @@ -60,7 +71,7 @@ func TestWSResponseCreate_FlexPassThrough(t *testing.T) { svc := newOpenAIGatewayServiceWithSettings(t, DefaultOpenAIFastPolicySettings()) account := &Account{Platform: PlatformOpenAI, Type: AccountTypeAPIKey} - // Default policy targets priority only; flex is left untouched. + // Default policy has no rules; flex is left untouched. frame := []byte(`{"type":"response.create","model":"gpt-5.5","service_tier":"flex"}`) updated, blocked, err := svc.applyOpenAIFastPolicyToWSResponseCreate(context.Background(), account, "gpt-5.5", frame) require.NoError(t, err) @@ -220,8 +231,8 @@ func (f *fakePassthroughFrameConn) Close() error { } // gpt55WhitelistFastPolicy 返回一份强制带 model whitelist 的策略,用于 -// 验证 capturedSessionModel fallback 的语义(默认策略 whitelist 为空时 -// fallback 路径无法被观察到)。 +// 验证 capturedSessionModel fallback 的语义(默认配置没有规则,fallback +// 路径无法被观察到)。 func gpt55WhitelistFastPolicy() *OpenAIFastPolicySettings { return &OpenAIFastPolicySettings{ Rules: []OpenAIFastPolicyRule{{ @@ -242,7 +253,7 @@ func gpt55WhitelistFastPolicy() *OpenAIFastPolicySettings { // through to the upstream. func TestPolicyEnforcingFrameConn_FollowupFrameWithoutModelUsesCapturedModel(t *testing.T) { // 此处特意使用带 whitelist 的策略,以便观察 capturedSessionModel - // fallback 是否生效(默认策略 whitelist 为空,fallback 与否结果一致, + // fallback 是否生效(默认配置没有规则,fallback 与否结果一致, // 不能用来覆盖此回归)。 svc := newOpenAIGatewayServiceWithSettings(t, gpt55WhitelistFastPolicy()) account := &Account{Platform: PlatformOpenAI, Type: AccountTypeAPIKey} @@ -310,13 +321,13 @@ func TestPolicyEnforcingFrameConn_WithoutCapturedFallbackPolicyMisses(t *testing "sanity: without capturedSessionModel fallback the leak (D5) reproduces — confirms the fix is load-bearing") } -// --- Ingress end-to-end test (filter path) --- +// --- Ingress end-to-end test (explicit filter path) --- // TestWSResponseCreate_IngressFiltersServiceTierBeforeUpstream wires up the // real ProxyResponsesWebSocketFromClient ingress session pipeline against a // captureConn upstream and asserts that a client frame with service_tier=fast -// is normalized + filtered out before being written upstream. This is the -// integration flavour of TestWSResponseCreate_FilterStripsServiceTier. +// is normalized + filtered out by an explicit admin policy before being +// written upstream. func TestWSResponseCreate_IngressFiltersServiceTierBeforeUpstream(t *testing.T) { gin.SetMode(gin.TestMode) @@ -345,9 +356,9 @@ func TestWSResponseCreate_IngressFiltersServiceTierBeforeUpstream(t *testing.T) pool.setClientDialerForTest(captureDialer) repo := &openAIFastPolicyRepoStub{values: map[string]string{}} - defaultJSON, err := json.Marshal(DefaultOpenAIFastPolicySettings()) + filterPolicyJSON, err := json.Marshal(openAIFastFilterPriorityPolicy()) require.NoError(t, err) - repo.values[SettingKeyOpenAIFastPolicySettings] = string(defaultJSON) + repo.values[SettingKeyOpenAIFastPolicySettings] = string(filterPolicyJSON) svc := &OpenAIGatewayService{ cfg: cfg, @@ -631,13 +642,13 @@ func TestApplyOpenAIFastPolicyToBody_BlockShortCircuitsUpstream(t *testing.T) { require.Equal(t, string(body), string(updated), "block must not mutate body") } -// TestForwardAsAnthropicMessages_BetaFastModeTriggersOpenAIFastPolicy verifies -// the Anthropic-compat entrypoint chain: anthropic-beta: fast-mode → BetaFastMode -// detection → ServiceTier="priority" injection (openai_gateway_messages.go:60) -// → applyOpenAIFastPolicyToBody filter on default policy → upstream body has -// no service_tier. We exercise the same internal pipeline (Anthropic→Responses -// + BetaFastMode + policy) without spinning up a real upstream HTTP server. -func TestForwardAsAnthropicMessages_BetaFastModeTriggersOpenAIFastPolicy(t *testing.T) { +// TestForwardAsAnthropicMessages_BetaFastModePassesOpenAIFastPolicyByDefault +// verifies the Anthropic-compat entrypoint chain: anthropic-beta: fast-mode → +// BetaFastMode detection → ServiceTier="priority" injection +// (openai_gateway_messages.go:60) → default OpenAI fast policy pass. We +// exercise the same internal pipeline (Anthropic→Responses + BetaFastMode + +// policy) without spinning up a real upstream HTTP server. +func TestForwardAsAnthropicMessages_BetaFastModePassesOpenAIFastPolicyByDefault(t *testing.T) { svc := newOpenAIGatewayServiceWithSettings(t, DefaultOpenAIFastPolicySettings()) account := &Account{Platform: PlatformOpenAI, Type: AccountTypeAPIKey} @@ -663,8 +674,9 @@ func TestForwardAsAnthropicMessages_BetaFastModeTriggersOpenAIFastPolicy(t *test upstreamBody, policyErr := svc.applyOpenAIFastPolicyToBody(context.Background(), account, "gpt-5.5", responsesBody) require.NoError(t, policyErr) - // Step 4: assert that policy filtered the field before the upstream HTTP request. - require.NotContains(t, string(upstreamBody), `"service_tier"`, "default policy 命中 gpt-5.5 priority 应当 filter 掉 service_tier") + // Step 4: default policy must preserve the explicit fast/priority request. + require.Equal(t, "priority", gjson.GetBytes(upstreamBody, "service_tier").String(), + "default policy should pass service_tier=priority through to upstream") } // --- Fix1: passthrough capturedSessionModel must follow session.update --- @@ -808,7 +820,7 @@ func TestApplyOpenAIFastPolicyToBody_PassNormalizesFastAlias(t *testing.T) { // tier) instead of the user-requested "priority". This test pins the // contract those two helpers must uphold for the adapter's billing path. func TestPassthroughBilling_PostFilterServiceTier(t *testing.T) { - svc := newOpenAIGatewayServiceWithSettings(t, DefaultOpenAIFastPolicySettings()) + svc := newOpenAIGatewayServiceWithSettings(t, openAIFastFilterPriorityPolicy()) account := &Account{Platform: PlatformOpenAI, Type: AccountTypeAPIKey} raw := []byte(`{"type":"response.create","model":"gpt-5.5","service_tier":"priority"}`) @@ -821,7 +833,7 @@ func TestPassthroughBilling_PostFilterServiceTier(t *testing.T) { require.Equal(t, "priority", *pre, "sanity: raw first frame carries priority that pre-fix billing would have reported") - // Apply policy filter (default rule: gpt-5.5 + priority → filter). + // Apply explicit policy filter (gpt-5.5 + priority → filter). filtered, blocked, err := svc.applyOpenAIFastPolicyToWSResponseCreate(context.Background(), account, "gpt-5.5", raw) require.NoError(t, err) require.Nil(t, blocked) @@ -890,9 +902,9 @@ func TestApplyOpenAIFastPolicyToBody_NonStringServiceTier(t *testing.T) { // atomic.Pointer[string] on every successful response.create frame. // // This test pins the four legs of the semantic contract: -// - turn 1: service_tier=priority hits the default whitelist filter, so +// - turn 1: service_tier=priority hits the explicit filter rule, so // after filter the upstream sees no tier → billing is nil. -// - turn 2: service_tier=flex passes (default rule targets priority only), +// - turn 2: service_tier=flex passes (the filter rule targets priority only), // billing should now reflect "flex". // - turn 3: response.create without any service_tier — the upstream will // treat it as default; we choose to mirror that and overwrite billing @@ -900,7 +912,7 @@ func TestApplyOpenAIFastPolicyToBody_NonStringServiceTier(t *testing.T) { // - non-response.create frame (response.cancel here) carrying a stray // service_tier-shaped field must NOT clobber the billing pointer. func TestPassthroughBilling_MultiTurnServiceTierFollowsFilteredFrames(t *testing.T) { - svc := newOpenAIGatewayServiceWithSettings(t, DefaultOpenAIFastPolicySettings()) + svc := newOpenAIGatewayServiceWithSettings(t, openAIFastFilterPriorityPolicy()) account := &Account{Platform: PlatformOpenAI, Type: AccountTypeAPIKey} // Mirror the production filter closure (openai_ws_v2_passthrough_adapter.go diff --git a/backend/internal/service/openai_gateway_service.go b/backend/internal/service/openai_gateway_service.go index 16ed5cce..91ff502a 100644 --- a/backend/internal/service/openai_gateway_service.go +++ b/backend/internal/service/openai_gateway_service.go @@ -6241,7 +6241,7 @@ func writeOpenAIFastPolicyBlockedResponse(c *gin.Context, err *OpenAIFastBlocked // applyOpenAIFastPolicyToBody contract but operates on a Realtime/Responses // WS payload: // -// - pass: returns frame unchanged (newBytes == frame, blocked == nil) +// - pass: keeps service_tier, normalizing aliases such as "fast" to "priority" // - filter: returns a copy with top-level service_tier removed // - block: returns (frame, *OpenAIFastBlockedError) // @@ -6305,7 +6305,14 @@ func (s *OpenAIGatewayService) applyOpenAIFastPolicyToWSResponseCreate( } return trimmed, nil, nil default: - return frame, nil, nil + if normTier == rawTier { + return frame, nil, nil + } + updated, err := sjson.SetBytes(frame, "service_tier", normTier) + if err != nil { + return frame, nil, fmt.Errorf("normalize service_tier in ws frame: %w", err) + } + return updated, nil, nil } } diff --git a/backend/internal/service/openai_ws_v2_passthrough_adapter.go b/backend/internal/service/openai_ws_v2_passthrough_adapter.go index e2760725..0a89e2dd 100644 --- a/backend/internal/service/openai_ws_v2_passthrough_adapter.go +++ b/backend/internal/service/openai_ws_v2_passthrough_adapter.go @@ -267,9 +267,8 @@ func (s *OpenAIGatewayService) proxyResponsesWebSocketV2Passthrough( // omits "model" — Realtime clients are allowed to send response.create // without re-stating the model, in which case the upstream uses the model // negotiated at session.update time. Without this fallback, an empty - // model would miss the default ["gpt-5.5","gpt-5.5*"] whitelist and be - // silently passed through, defeating the policy on every frame after - // the first. + // model would miss any admin-configured model whitelist and be silently + // passed through, defeating that policy on every frame after the first. capturedSessionModel := openAIWSPassthroughPolicyModelForFrame(account, firstClientMessage) initialRequestModel := "" if hooks != nil { diff --git a/backend/internal/service/settings_view.go b/backend/internal/service/settings_view.go index bfe85995..9066e050 100644 --- a/backend/internal/service/settings_view.go +++ b/backend/internal/service/settings_view.go @@ -491,25 +491,10 @@ type OpenAIFastPolicySettings struct { } // DefaultOpenAIFastPolicySettings 返回默认的 OpenAI fast 策略配置。 -// 默认对所有模型的 priority(fast)请求执行 filter,即剔除 service_tier 字段, -// 让上游按 normal 优先级处理。 -// -// 为什么 ModelWhitelist 为空(=对所有模型生效): -// codex 客户端的 service_tier=fast 是用户级开关,与 model 字段正交。即使 -// 用户使用 gpt-4 + fast,priority 配额仍会被消耗。如果默认规则只锁 -// gpt-5.5*,"用 gpt-4 + fast 透传 priority 上游" 这条路径就会绕过策略。 -// 与 codex 真实语义对齐,默认对所有模型生效;管理员若需要只针对特定 -// 模型,可在 admin UI 中显式配置 model_whitelist。 +// 默认不配置任何规则,保留 OpenAI 上游 service_tier 语义;管理员如需 +// 限制 priority/flex,可以在 admin UI 中显式配置 filter 或 block 规则。 func DefaultOpenAIFastPolicySettings() *OpenAIFastPolicySettings { return &OpenAIFastPolicySettings{ - Rules: []OpenAIFastPolicyRule{ - { - ServiceTier: OpenAIFastTierPriority, - Action: BetaPolicyActionFilter, - Scope: BetaPolicyScopeAll, - ModelWhitelist: []string{}, - FallbackAction: BetaPolicyActionPass, - }, - }, + Rules: []OpenAIFastPolicyRule{}, } }