Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
phsl
/
new-api
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Members
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
bb7ad0ce
authored
Feb 21, 2026
by
Seefs
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: gate Claude inference_geo passthrough behind channel setting and add field docs
parent
8a214d35
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
101 additions
and
26 deletions
+101
-26
dto/channel_settings.go
+1
-0
dto/claude.go
+5
-3
dto/openai_request.go
+31
-23
relay/common/override_test.go
+33
-0
relay/common/relay_info.go
+8
-0
web/src/components/table/channels/modals/EditChannelModal.jsx
+23
-0
No files found.
dto/channel_settings.go
View file @
bb7ad0ce
...
@@ -29,6 +29,7 @@ type ChannelOtherSettings struct {
...
@@ -29,6 +29,7 @@ type ChannelOtherSettings struct {
OpenRouterEnterprise
*
bool
`json:"openrouter_enterprise,omitempty"`
OpenRouterEnterprise
*
bool
`json:"openrouter_enterprise,omitempty"`
ClaudeBetaQuery
bool
`json:"claude_beta_query,omitempty"`
// Claude 渠道是否强制追加 ?beta=true
ClaudeBetaQuery
bool
`json:"claude_beta_query,omitempty"`
// Claude 渠道是否强制追加 ?beta=true
AllowServiceTier
bool
`json:"allow_service_tier,omitempty"`
// 是否允许 service_tier 透传(默认过滤以避免额外计费)
AllowServiceTier
bool
`json:"allow_service_tier,omitempty"`
// 是否允许 service_tier 透传(默认过滤以避免额外计费)
AllowInferenceGeo
bool
`json:"allow_inference_geo,omitempty"`
// 是否允许 inference_geo 透传(仅 Claude,默认过滤以满足数据驻留合规)
DisableStore
bool
`json:"disable_store,omitempty"`
// 是否禁用 store 透传(默认允许透传,禁用后可能导致 Codex 无法使用)
DisableStore
bool
`json:"disable_store,omitempty"`
// 是否禁用 store 透传(默认允许透传,禁用后可能导致 Codex 无法使用)
AllowSafetyIdentifier
bool
`json:"allow_safety_identifier,omitempty"`
// 是否允许 safety_identifier 透传(默认过滤以保护用户隐私)
AllowSafetyIdentifier
bool
`json:"allow_safety_identifier,omitempty"`
// 是否允许 safety_identifier 透传(默认过滤以保护用户隐私)
AllowIncludeObfuscation
bool
`json:"allow_include_obfuscation,omitempty"`
// 是否允许 stream_options.include_obfuscation 透传(默认过滤以避免关闭流混淆保护)
AllowIncludeObfuscation
bool
`json:"allow_include_obfuscation,omitempty"`
// 是否允许 stream_options.include_obfuscation 透传(默认过滤以避免关闭流混淆保护)
...
...
dto/claude.go
View file @
bb7ad0ce
...
@@ -194,8 +194,9 @@ type ClaudeRequest struct {
...
@@ -194,8 +194,9 @@ type ClaudeRequest struct {
Prompt
string
`json:"prompt,omitempty"`
Prompt
string
`json:"prompt,omitempty"`
System
any
`json:"system,omitempty"`
System
any
`json:"system,omitempty"`
Messages
[]
ClaudeMessage
`json:"messages,omitempty"`
Messages
[]
ClaudeMessage
`json:"messages,omitempty"`
// https://platform.claude.com/docs/en/build-with-claude/data-residency#inference-geo
// InferenceGeo controls Claude data residency region.
// InferenceGeo string `json:"inference_geo,omitempty"`
// This field is filtered by default and can be enabled via channel setting allow_inference_geo.
InferenceGeo
string
`json:"inference_geo,omitempty"`
MaxTokens
uint
`json:"max_tokens,omitempty"`
MaxTokens
uint
`json:"max_tokens,omitempty"`
MaxTokensToSample
uint
`json:"max_tokens_to_sample,omitempty"`
MaxTokensToSample
uint
`json:"max_tokens_to_sample,omitempty"`
StopSequences
[]
string
`json:"stop_sequences,omitempty"`
StopSequences
[]
string
`json:"stop_sequences,omitempty"`
...
@@ -212,7 +213,8 @@ type ClaudeRequest struct {
...
@@ -212,7 +213,8 @@ type ClaudeRequest struct {
Thinking
*
Thinking
`json:"thinking,omitempty"`
Thinking
*
Thinking
`json:"thinking,omitempty"`
McpServers
json
.
RawMessage
`json:"mcp_servers,omitempty"`
McpServers
json
.
RawMessage
`json:"mcp_servers,omitempty"`
Metadata
json
.
RawMessage
`json:"metadata,omitempty"`
Metadata
json
.
RawMessage
`json:"metadata,omitempty"`
// 服务层级字段,用于指定 API 服务等级。允许透传可能导致实际计费高于预期,默认应过滤
// ServiceTier specifies upstream service level and may affect billing.
// This field is filtered by default and can be enabled via channel setting allow_service_tier.
ServiceTier
string
`json:"service_tier,omitempty"`
ServiceTier
string
`json:"service_tier,omitempty"`
}
}
...
...
dto/openai_request.go
View file @
bb7ad0ce
...
@@ -56,18 +56,20 @@ type GeneralOpenAIRequest struct {
...
@@ -56,18 +56,20 @@ type GeneralOpenAIRequest struct {
ToolChoice
any
`json:"tool_choice,omitempty"`
ToolChoice
any
`json:"tool_choice,omitempty"`
FunctionCall
json
.
RawMessage
`json:"function_call,omitempty"`
FunctionCall
json
.
RawMessage
`json:"function_call,omitempty"`
User
string
`json:"user,omitempty"`
User
string
`json:"user,omitempty"`
ServiceTier
string
`json:"service_tier,omitempty"`
// ServiceTier specifies upstream service level and may affect billing.
LogProbs
bool
`json:"logprobs,omitempty"`
// This field is filtered by default and can be enabled via channel setting allow_service_tier.
TopLogProbs
int
`json:"top_logprobs,omitempty"`
ServiceTier
string
`json:"service_tier,omitempty"`
Dimensions
int
`json:"dimensions,omitempty"`
LogProbs
bool
`json:"logprobs,omitempty"`
Modalities
json
.
RawMessage
`json:"modalities,omitempty"`
TopLogProbs
int
`json:"top_logprobs,omitempty"`
Audio
json
.
RawMessage
`json:"audio,omitempty"`
Dimensions
int
`json:"dimensions,omitempty"`
Modalities
json
.
RawMessage
`json:"modalities,omitempty"`
Audio
json
.
RawMessage
`json:"audio,omitempty"`
// 安全标识符,用于帮助 OpenAI 检测可能违反使用政策的应用程序用户
// 安全标识符,用于帮助 OpenAI 检测可能违反使用政策的应用程序用户
// 注意:此字段会向 OpenAI 发送用户标识信息,默认过滤
以保护用户隐私
// 注意:此字段会向 OpenAI 发送用户标识信息,默认过滤
,可通过 allow_safety_identifier 开启
SafetyIdentifier
string
`json:"safety_identifier,omitempty"`
SafetyIdentifier
string
`json:"safety_identifier,omitempty"`
// Whether or not to store the output of this chat completion request for use in our model distillation or evals products.
// Whether or not to store the output of this chat completion request for use in our model distillation or evals products.
// 是否存储此次请求数据供 OpenAI 用于评估和优化产品
// 是否存储此次请求数据供 OpenAI 用于评估和优化产品
// 注意:默认
过滤此字段以保护用户隐私,但过滤
后可能导致 Codex 无法正常使用
// 注意:默认
允许透传,可通过 disable_store 禁用;禁用
后可能导致 Codex 无法正常使用
Store
json
.
RawMessage
`json:"store,omitempty"`
Store
json
.
RawMessage
`json:"store,omitempty"`
// Used by OpenAI to cache responses for similar requests to optimize your cache hit rates. Replaces the user field
// Used by OpenAI to cache responses for similar requests to optimize your cache hit rates. Replaces the user field
PromptCacheKey
string
`json:"prompt_cache_key,omitempty"`
PromptCacheKey
string
`json:"prompt_cache_key,omitempty"`
...
@@ -263,7 +265,8 @@ type FunctionRequest struct {
...
@@ -263,7 +265,8 @@ type FunctionRequest struct {
type
StreamOptions
struct
{
type
StreamOptions
struct
{
IncludeUsage
bool
`json:"include_usage,omitempty"`
IncludeUsage
bool
`json:"include_usage,omitempty"`
// for /v1/responses
// IncludeObfuscation is only for /v1/responses stream payload.
// This field is filtered by default and can be enabled via channel setting allow_include_obfuscation.
IncludeObfuscation
bool
`json:"include_obfuscation,omitempty"`
IncludeObfuscation
bool
`json:"include_obfuscation,omitempty"`
}
}
...
@@ -817,23 +820,28 @@ type OpenAIResponsesRequest struct {
...
@@ -817,23 +820,28 @@ type OpenAIResponsesRequest struct {
ParallelToolCalls
json
.
RawMessage
`json:"parallel_tool_calls,omitempty"`
ParallelToolCalls
json
.
RawMessage
`json:"parallel_tool_calls,omitempty"`
PreviousResponseID
string
`json:"previous_response_id,omitempty"`
PreviousResponseID
string
`json:"previous_response_id,omitempty"`
Reasoning
*
Reasoning
`json:"reasoning,omitempty"`
Reasoning
*
Reasoning
`json:"reasoning,omitempty"`
// 服务层级字段,用于指定 API 服务等级。允许透传可能导致实际计费高于预期,默认应过滤
// ServiceTier specifies upstream service level and may affect billing.
ServiceTier
string
`json:"service_tier,omitempty"`
// This field is filtered by default and can be enabled via channel setting allow_service_tier.
ServiceTier
string
`json:"service_tier,omitempty"`
// Store controls whether upstream may store request/response data.
// This field is allowed by default and can be disabled via channel setting disable_store.
Store
json
.
RawMessage
`json:"store,omitempty"`
Store
json
.
RawMessage
`json:"store,omitempty"`
PromptCacheKey
json
.
RawMessage
`json:"prompt_cache_key,omitempty"`
PromptCacheKey
json
.
RawMessage
`json:"prompt_cache_key,omitempty"`
PromptCacheRetention
json
.
RawMessage
`json:"prompt_cache_retention,omitempty"`
PromptCacheRetention
json
.
RawMessage
`json:"prompt_cache_retention,omitempty"`
SafetyIdentifier
string
`json:"safety_identifier,omitempty"`
// SafetyIdentifier carries client identity for policy abuse detection.
Stream
bool
`json:"stream,omitempty"`
// This field is filtered by default and can be enabled via channel setting allow_safety_identifier.
StreamOptions
*
StreamOptions
`json:"stream_options,omitempty"`
SafetyIdentifier
string
`json:"safety_identifier,omitempty"`
Temperature
*
float64
`json:"temperature,omitempty"`
Stream
bool
`json:"stream,omitempty"`
Text
json
.
RawMessage
`json:"text,omitempty"`
StreamOptions
*
StreamOptions
`json:"stream_options,omitempty"`
ToolChoice
json
.
RawMessage
`json:"tool_choice,omitempty"`
Temperature
*
float64
`json:"temperature,omitempty"`
Tools
json
.
RawMessage
`json:"tools,omitempty"`
// 需要处理的参数很少,MCP 参数太多不确定,所以用 map
Text
json
.
RawMessage
`json:"text,omitempty"`
TopP
*
float64
`json:"top_p,omitempty"`
ToolChoice
json
.
RawMessage
`json:"tool_choice,omitempty"`
Truncation
string
`json:"truncation,omitempty"`
Tools
json
.
RawMessage
`json:"tools,omitempty"`
// 需要处理的参数很少,MCP 参数太多不确定,所以用 map
User
string
`json:"user,omitempty"`
TopP
*
float64
`json:"top_p,omitempty"`
MaxToolCalls
uint
`json:"max_tool_calls,omitempty"`
Truncation
string
`json:"truncation,omitempty"`
Prompt
json
.
RawMessage
`json:"prompt,omitempty"`
User
string
`json:"user,omitempty"`
MaxToolCalls
uint
`json:"max_tool_calls,omitempty"`
Prompt
json
.
RawMessage
`json:"prompt,omitempty"`
// qwen
// qwen
EnableThinking
json
.
RawMessage
`json:"enable_thinking,omitempty"`
EnableThinking
json
.
RawMessage
`json:"enable_thinking,omitempty"`
// perplexity
// perplexity
...
...
relay/common/override_test.go
View file @
bb7ad0ce
...
@@ -812,6 +812,39 @@ func TestRemoveDisabledFieldsSkipWhenGlobalPassThroughEnabled(t *testing.T) {
...
@@ -812,6 +812,39 @@ func TestRemoveDisabledFieldsSkipWhenGlobalPassThroughEnabled(t *testing.T) {
assertJSONEqual
(
t
,
input
,
string
(
out
))
assertJSONEqual
(
t
,
input
,
string
(
out
))
}
}
func
TestRemoveDisabledFieldsDefaultFiltering
(
t
*
testing
.
T
)
{
input
:=
`{
"service_tier":"flex",
"inference_geo":"eu",
"safety_identifier":"user-123",
"store":true,
"stream_options":{"include_obfuscation":false}
}`
settings
:=
dto
.
ChannelOtherSettings
{}
out
,
err
:=
RemoveDisabledFields
([]
byte
(
input
),
settings
,
false
)
if
err
!=
nil
{
t
.
Fatalf
(
"RemoveDisabledFields returned error: %v"
,
err
)
}
assertJSONEqual
(
t
,
`{"store":true}`
,
string
(
out
))
}
func
TestRemoveDisabledFieldsAllowInferenceGeo
(
t
*
testing
.
T
)
{
input
:=
`{
"inference_geo":"eu",
"store":true
}`
settings
:=
dto
.
ChannelOtherSettings
{
AllowInferenceGeo
:
true
,
}
out
,
err
:=
RemoveDisabledFields
([]
byte
(
input
),
settings
,
false
)
if
err
!=
nil
{
t
.
Fatalf
(
"RemoveDisabledFields returned error: %v"
,
err
)
}
assertJSONEqual
(
t
,
`{"inference_geo":"eu","store":true}`
,
string
(
out
))
}
func
assertJSONEqual
(
t
*
testing
.
T
,
want
,
got
string
)
{
func
assertJSONEqual
(
t
*
testing
.
T
,
want
,
got
string
)
{
t
.
Helper
()
t
.
Helper
()
...
...
relay/common/relay_info.go
View file @
bb7ad0ce
...
@@ -700,6 +700,7 @@ func FailTaskInfo(reason string) *TaskInfo {
...
@@ -700,6 +700,7 @@ func FailTaskInfo(reason string) *TaskInfo {
// RemoveDisabledFields 从请求 JSON 数据中移除渠道设置中禁用的字段
// RemoveDisabledFields 从请求 JSON 数据中移除渠道设置中禁用的字段
// service_tier: 服务层级字段,可能导致额外计费(OpenAI、Claude、Responses API 支持)
// service_tier: 服务层级字段,可能导致额外计费(OpenAI、Claude、Responses API 支持)
// inference_geo: Claude 数据驻留推理区域字段(仅 Claude 支持,默认过滤)
// store: 数据存储授权字段,涉及用户隐私(仅 OpenAI、Responses API 支持,默认允许透传,禁用后可能导致 Codex 无法使用)
// store: 数据存储授权字段,涉及用户隐私(仅 OpenAI、Responses API 支持,默认允许透传,禁用后可能导致 Codex 无法使用)
// safety_identifier: 安全标识符,用于向 OpenAI 报告违规用户(仅 OpenAI 支持,涉及用户隐私)
// safety_identifier: 安全标识符,用于向 OpenAI 报告违规用户(仅 OpenAI 支持,涉及用户隐私)
// stream_options.include_obfuscation: 响应流混淆控制字段(仅 OpenAI Responses API 支持)
// stream_options.include_obfuscation: 响应流混淆控制字段(仅 OpenAI Responses API 支持)
...
@@ -721,6 +722,13 @@ func RemoveDisabledFields(jsonData []byte, channelOtherSettings dto.ChannelOther
...
@@ -721,6 +722,13 @@ func RemoveDisabledFields(jsonData []byte, channelOtherSettings dto.ChannelOther
}
}
}
}
// 默认移除 inference_geo,除非明确允许(避免在未授权情况下透传数据驻留区域)
if
!
channelOtherSettings
.
AllowInferenceGeo
{
if
_
,
exists
:=
data
[
"inference_geo"
];
exists
{
delete
(
data
,
"inference_geo"
)
}
}
// 默认允许 store 透传,除非明确禁用(禁用可能影响 Codex 使用)
// 默认允许 store 透传,除非明确禁用(禁用可能影响 Codex 使用)
if
channelOtherSettings
.
DisableStore
{
if
channelOtherSettings
.
DisableStore
{
if
_
,
exists
:=
data
[
"store"
];
exists
{
if
_
,
exists
:=
data
[
"store"
];
exists
{
...
...
web/src/components/table/channels/modals/EditChannelModal.jsx
View file @
bb7ad0ce
...
@@ -171,6 +171,7 @@ const EditChannelModal = (props) => {
...
@@ -171,6 +171,7 @@ const EditChannelModal = (props) => {
disable_store
:
false
,
// false = 允许透传(默认开启)
disable_store
:
false
,
// false = 允许透传(默认开启)
allow_safety_identifier
:
false
,
allow_safety_identifier
:
false
,
allow_include_obfuscation
:
false
,
allow_include_obfuscation
:
false
,
allow_inference_geo
:
false
,
claude_beta_query
:
false
,
claude_beta_query
:
false
,
};
};
const
[
batch
,
setBatch
]
=
useState
(
false
);
const
[
batch
,
setBatch
]
=
useState
(
false
);
...
@@ -637,6 +638,8 @@ const EditChannelModal = (props) => {
...
@@ -637,6 +638,8 @@ const EditChannelModal = (props) => {
parsedSettings
.
allow_safety_identifier
||
false
;
parsedSettings
.
allow_safety_identifier
||
false
;
data
.
allow_include_obfuscation
=
data
.
allow_include_obfuscation
=
parsedSettings
.
allow_include_obfuscation
||
false
;
parsedSettings
.
allow_include_obfuscation
||
false
;
data
.
allow_inference_geo
=
parsedSettings
.
allow_inference_geo
||
false
;
data
.
claude_beta_query
=
parsedSettings
.
claude_beta_query
||
false
;
data
.
claude_beta_query
=
parsedSettings
.
claude_beta_query
||
false
;
}
catch
(
error
)
{
}
catch
(
error
)
{
console
.
error
(
'解析其他设置失败:'
,
error
);
console
.
error
(
'解析其他设置失败:'
,
error
);
...
@@ -649,6 +652,7 @@ const EditChannelModal = (props) => {
...
@@ -649,6 +652,7 @@ const EditChannelModal = (props) => {
data
.
disable_store
=
false
;
data
.
disable_store
=
false
;
data
.
allow_safety_identifier
=
false
;
data
.
allow_safety_identifier
=
false
;
data
.
allow_include_obfuscation
=
false
;
data
.
allow_include_obfuscation
=
false
;
data
.
allow_inference_geo
=
false
;
data
.
claude_beta_query
=
false
;
data
.
claude_beta_query
=
false
;
}
}
}
else
{
}
else
{
...
@@ -660,6 +664,7 @@ const EditChannelModal = (props) => {
...
@@ -660,6 +664,7 @@ const EditChannelModal = (props) => {
data
.
disable_store
=
false
;
data
.
disable_store
=
false
;
data
.
allow_safety_identifier
=
false
;
data
.
allow_safety_identifier
=
false
;
data
.
allow_include_obfuscation
=
false
;
data
.
allow_include_obfuscation
=
false
;
data
.
allow_inference_geo
=
false
;
data
.
claude_beta_query
=
false
;
data
.
claude_beta_query
=
false
;
}
}
...
@@ -1406,6 +1411,7 @@ const EditChannelModal = (props) => {
...
@@ -1406,6 +1411,7 @@ const EditChannelModal = (props) => {
localInputs
.
allow_include_obfuscation
===
true
;
localInputs
.
allow_include_obfuscation
===
true
;
}
}
if
(
localInputs
.
type
===
14
)
{
if
(
localInputs
.
type
===
14
)
{
settings
.
allow_inference_geo
=
localInputs
.
allow_inference_geo
===
true
;
settings
.
claude_beta_query
=
localInputs
.
claude_beta_query
===
true
;
settings
.
claude_beta_query
=
localInputs
.
claude_beta_query
===
true
;
}
}
}
}
...
@@ -1429,6 +1435,7 @@ const EditChannelModal = (props) => {
...
@@ -1429,6 +1435,7 @@ const EditChannelModal = (props) => {
delete
localInputs
.
disable_store
;
delete
localInputs
.
disable_store
;
delete
localInputs
.
allow_safety_identifier
;
delete
localInputs
.
allow_safety_identifier
;
delete
localInputs
.
allow_include_obfuscation
;
delete
localInputs
.
allow_include_obfuscation
;
delete
localInputs
.
allow_inference_geo
;
delete
localInputs
.
claude_beta_query
;
delete
localInputs
.
claude_beta_query
;
let
res
;
let
res
;
...
@@ -3322,6 +3329,22 @@ const EditChannelModal = (props) => {
...
@@ -3322,6 +3329,22 @@ const EditChannelModal = (props) => {
'service_tier 字段用于指定服务层级,允许透传可能导致实际计费高于预期。默认关闭以避免额外费用'
,
'service_tier 字段用于指定服务层级,允许透传可能导致实际计费高于预期。默认关闭以避免额外费用'
,
)
}
)
}
/>
/>
<
Form
.
Switch
field=
'allow_inference_geo'
label=
{
t
(
'允许 inference_geo 透传'
)
}
checkedText=
{
t
(
'开'
)
}
uncheckedText=
{
t
(
'关'
)
}
onChange=
{
(
value
)
=>
handleChannelOtherSettingsChange
(
'allow_inference_geo'
,
value
,
)
}
extraText=
{
t
(
'inference_geo 字段用于控制 Claude 数据驻留推理区域。默认关闭以避免未经授权透传地域信息'
,
)
}
/>
</>
</>
)
}
)
}
</
Card
>
</
Card
>
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment