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 {
OpenRouterEnterprise
*
bool
`json:"openrouter_enterprise,omitempty"`
ClaudeBetaQuery
bool
`json:"claude_beta_query,omitempty"`
// Claude 渠道是否强制追加 ?beta=true
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 无法使用)
AllowSafetyIdentifier
bool
`json:"allow_safety_identifier,omitempty"`
// 是否允许 safety_identifier 透传(默认过滤以保护用户隐私)
AllowIncludeObfuscation
bool
`json:"allow_include_obfuscation,omitempty"`
// 是否允许 stream_options.include_obfuscation 透传(默认过滤以避免关闭流混淆保护)
...
...
dto/claude.go
View file @
bb7ad0ce
...
...
@@ -194,8 +194,9 @@ type ClaudeRequest struct {
Prompt
string
`json:"prompt,omitempty"`
System
any
`json:"system,omitempty"`
Messages
[]
ClaudeMessage
`json:"messages,omitempty"`
// https://platform.claude.com/docs/en/build-with-claude/data-residency#inference-geo
// InferenceGeo string `json:"inference_geo,omitempty"`
// InferenceGeo controls Claude data residency region.
// 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"`
MaxTokensToSample
uint
`json:"max_tokens_to_sample,omitempty"`
StopSequences
[]
string
`json:"stop_sequences,omitempty"`
...
...
@@ -212,7 +213,8 @@ type ClaudeRequest struct {
Thinking
*
Thinking
`json:"thinking,omitempty"`
McpServers
json
.
RawMessage
`json:"mcp_servers,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"`
}
...
...
dto/openai_request.go
View file @
bb7ad0ce
...
...
@@ -56,18 +56,20 @@ type GeneralOpenAIRequest struct {
ToolChoice
any
`json:"tool_choice,omitempty"`
FunctionCall
json
.
RawMessage
`json:"function_call,omitempty"`
User
string
`json:"user,omitempty"`
ServiceTier
string
`json:"service_tier,omitempty"`
LogProbs
bool
`json:"logprobs,omitempty"`
TopLogProbs
int
`json:"top_logprobs,omitempty"`
Dimensions
int
`json:"dimensions,omitempty"`
Modalities
json
.
RawMessage
`json:"modalities,omitempty"`
Audio
json
.
RawMessage
`json:"audio,omitempty"`
// 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"`
LogProbs
bool
`json:"logprobs,omitempty"`
TopLogProbs
int
`json:"top_logprobs,omitempty"`
Dimensions
int
`json:"dimensions,omitempty"`
Modalities
json
.
RawMessage
`json:"modalities,omitempty"`
Audio
json
.
RawMessage
`json:"audio,omitempty"`
// 安全标识符,用于帮助 OpenAI 检测可能违反使用政策的应用程序用户
// 注意:此字段会向 OpenAI 发送用户标识信息,默认过滤
以保护用户隐私
// 注意:此字段会向 OpenAI 发送用户标识信息,默认过滤
,可通过 allow_safety_identifier 开启
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.
// 是否存储此次请求数据供 OpenAI 用于评估和优化产品
// 注意:默认
过滤此字段以保护用户隐私,但过滤
后可能导致 Codex 无法正常使用
// 注意:默认
允许透传,可通过 disable_store 禁用;禁用
后可能导致 Codex 无法正常使用
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
PromptCacheKey
string
`json:"prompt_cache_key,omitempty"`
...
...
@@ -263,7 +265,8 @@ type FunctionRequest struct {
type
StreamOptions
struct
{
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"`
}
...
...
@@ -817,23 +820,28 @@ type OpenAIResponsesRequest struct {
ParallelToolCalls
json
.
RawMessage
`json:"parallel_tool_calls,omitempty"`
PreviousResponseID
string
`json:"previous_response_id,omitempty"`
Reasoning
*
Reasoning
`json:"reasoning,omitempty"`
// 服务层级字段,用于指定 API 服务等级。允许透传可能导致实际计费高于预期,默认应过滤
ServiceTier
string
`json:"service_tier,omitempty"`
// 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"`
// 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"`
PromptCacheKey
json
.
RawMessage
`json:"prompt_cache_key,omitempty"`
PromptCacheRetention
json
.
RawMessage
`json:"prompt_cache_retention,omitempty"`
SafetyIdentifier
string
`json:"safety_identifier,omitempty"`
Stream
bool
`json:"stream,omitempty"`
StreamOptions
*
StreamOptions
`json:"stream_options,omitempty"`
Temperature
*
float64
`json:"temperature,omitempty"`
Text
json
.
RawMessage
`json:"text,omitempty"`
ToolChoice
json
.
RawMessage
`json:"tool_choice,omitempty"`
Tools
json
.
RawMessage
`json:"tools,omitempty"`
// 需要处理的参数很少,MCP 参数太多不确定,所以用 map
TopP
*
float64
`json:"top_p,omitempty"`
Truncation
string
`json:"truncation,omitempty"`
User
string
`json:"user,omitempty"`
MaxToolCalls
uint
`json:"max_tool_calls,omitempty"`
Prompt
json
.
RawMessage
`json:"prompt,omitempty"`
// SafetyIdentifier carries client identity for policy abuse detection.
// This field is filtered by default and can be enabled via channel setting allow_safety_identifier.
SafetyIdentifier
string
`json:"safety_identifier,omitempty"`
Stream
bool
`json:"stream,omitempty"`
StreamOptions
*
StreamOptions
`json:"stream_options,omitempty"`
Temperature
*
float64
`json:"temperature,omitempty"`
Text
json
.
RawMessage
`json:"text,omitempty"`
ToolChoice
json
.
RawMessage
`json:"tool_choice,omitempty"`
Tools
json
.
RawMessage
`json:"tools,omitempty"`
// 需要处理的参数很少,MCP 参数太多不确定,所以用 map
TopP
*
float64
`json:"top_p,omitempty"`
Truncation
string
`json:"truncation,omitempty"`
User
string
`json:"user,omitempty"`
MaxToolCalls
uint
`json:"max_tool_calls,omitempty"`
Prompt
json
.
RawMessage
`json:"prompt,omitempty"`
// qwen
EnableThinking
json
.
RawMessage
`json:"enable_thinking,omitempty"`
// perplexity
...
...
relay/common/override_test.go
View file @
bb7ad0ce
...
...
@@ -812,6 +812,39 @@ func TestRemoveDisabledFieldsSkipWhenGlobalPassThroughEnabled(t *testing.T) {
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
)
{
t
.
Helper
()
...
...
relay/common/relay_info.go
View file @
bb7ad0ce
...
...
@@ -700,6 +700,7 @@ func FailTaskInfo(reason string) *TaskInfo {
// RemoveDisabledFields 从请求 JSON 数据中移除渠道设置中禁用的字段
// service_tier: 服务层级字段,可能导致额外计费(OpenAI、Claude、Responses API 支持)
// inference_geo: Claude 数据驻留推理区域字段(仅 Claude 支持,默认过滤)
// store: 数据存储授权字段,涉及用户隐私(仅 OpenAI、Responses API 支持,默认允许透传,禁用后可能导致 Codex 无法使用)
// safety_identifier: 安全标识符,用于向 OpenAI 报告违规用户(仅 OpenAI 支持,涉及用户隐私)
// stream_options.include_obfuscation: 响应流混淆控制字段(仅 OpenAI Responses API 支持)
...
...
@@ -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 使用)
if
channelOtherSettings
.
DisableStore
{
if
_
,
exists
:=
data
[
"store"
];
exists
{
...
...
web/src/components/table/channels/modals/EditChannelModal.jsx
View file @
bb7ad0ce
...
...
@@ -171,6 +171,7 @@ const EditChannelModal = (props) => {
disable_store
:
false
,
// false = 允许透传(默认开启)
allow_safety_identifier
:
false
,
allow_include_obfuscation
:
false
,
allow_inference_geo
:
false
,
claude_beta_query
:
false
,
};
const
[
batch
,
setBatch
]
=
useState
(
false
);
...
...
@@ -637,6 +638,8 @@ const EditChannelModal = (props) => {
parsedSettings
.
allow_safety_identifier
||
false
;
data
.
allow_include_obfuscation
=
parsedSettings
.
allow_include_obfuscation
||
false
;
data
.
allow_inference_geo
=
parsedSettings
.
allow_inference_geo
||
false
;
data
.
claude_beta_query
=
parsedSettings
.
claude_beta_query
||
false
;
}
catch
(
error
)
{
console
.
error
(
'解析其他设置失败:'
,
error
);
...
...
@@ -649,6 +652,7 @@ const EditChannelModal = (props) => {
data
.
disable_store
=
false
;
data
.
allow_safety_identifier
=
false
;
data
.
allow_include_obfuscation
=
false
;
data
.
allow_inference_geo
=
false
;
data
.
claude_beta_query
=
false
;
}
}
else
{
...
...
@@ -660,6 +664,7 @@ const EditChannelModal = (props) => {
data
.
disable_store
=
false
;
data
.
allow_safety_identifier
=
false
;
data
.
allow_include_obfuscation
=
false
;
data
.
allow_inference_geo
=
false
;
data
.
claude_beta_query
=
false
;
}
...
...
@@ -1406,6 +1411,7 @@ const EditChannelModal = (props) => {
localInputs
.
allow_include_obfuscation
===
true
;
}
if
(
localInputs
.
type
===
14
)
{
settings
.
allow_inference_geo
=
localInputs
.
allow_inference_geo
===
true
;
settings
.
claude_beta_query
=
localInputs
.
claude_beta_query
===
true
;
}
}
...
...
@@ -1429,6 +1435,7 @@ const EditChannelModal = (props) => {
delete
localInputs
.
disable_store
;
delete
localInputs
.
allow_safety_identifier
;
delete
localInputs
.
allow_include_obfuscation
;
delete
localInputs
.
allow_inference_geo
;
delete
localInputs
.
claude_beta_query
;
let
res
;
...
...
@@ -3322,6 +3329,22 @@ const EditChannelModal = (props) => {
'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
>
...
...
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