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
Unverified
Commit
6b659fd6
authored
Sep 05, 2026
by
CaIon
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fix(relay): preserve reasoning effort without implicit remapping
parent
7c044d7c
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
125 additions
and
40 deletions
+125
-40
relay/channel/deepseek/adaptor.go
+10
-0
relay/channel/openai/adaptor.go
+30
-5
relay/channel/volcengine/adaptor.go
+1
-0
relay/channel/xai/adaptor.go
+4
-2
relay/common/relay_info.go
+4
-3
relay/helper/model_modifier.go
+2
-2
relay/helper/reasoning_suffix.go
+3
-0
relaykit/relayconvert/internal/shared/claude/reasoning.go
+11
-6
relaykit/relayconvert/internal/shared/gemini/request.go
+7
-6
relaykit/relayconvert/reasoning/intent.go
+6
-16
relaykit/relayconvert/reasoning/intent_test.go
+47
-0
No files found.
relay/channel/deepseek/adaptor.go
View file @
6b659fd6
...
...
@@ -15,6 +15,7 @@ import (
"github.com/QuantumNous/new-api/relay/constant"
"github.com/QuantumNous/new-api/relaykit/dto"
"github.com/QuantumNous/new-api/relaykit/types"
"github.com/QuantumNous/new-api/setting/model_setting"
"github.com/QuantumNous/new-api/setting/reasoning"
"github.com/gin-gonic/gin"
)
...
...
@@ -98,6 +99,9 @@ func applyDeepSeekV4OpenAIThinkingSuffix(info *relaycommon.RelayInfo, request *d
if
info
!=
nil
&&
info
.
ChannelMeta
!=
nil
&&
info
.
UpstreamModelName
!=
""
{
modelName
=
info
.
UpstreamModelName
}
if
model_setting
.
ShouldPreserveThinkingSuffix
(
modelName
)
||
info
!=
nil
&&
model_setting
.
ShouldPreserveThinkingSuffix
(
info
.
OriginModelName
)
{
return
nil
}
baseModel
,
thinkingType
,
effort
,
ok
:=
reasoning
.
ParseDeepSeekV4ThinkingSuffix
(
modelName
)
if
!
ok
{
return
nil
...
...
@@ -125,6 +129,9 @@ func applyDeepSeekV4ClaudeThinkingSuffix(info *relaycommon.RelayInfo, request *d
if
info
!=
nil
&&
info
.
ChannelMeta
!=
nil
&&
info
.
UpstreamModelName
!=
""
{
modelName
=
info
.
UpstreamModelName
}
if
model_setting
.
ShouldPreserveThinkingSuffix
(
modelName
)
||
info
!=
nil
&&
model_setting
.
ShouldPreserveThinkingSuffix
(
info
.
OriginModelName
)
{
return
nil
}
baseModel
,
thinkingType
,
effort
,
ok
:=
reasoning
.
ParseDeepSeekV4ThinkingSuffix
(
modelName
)
if
!
ok
{
return
nil
...
...
@@ -170,6 +177,9 @@ func applyDeepSeekV4ResponsesThinkingSuffix(info *relaycommon.RelayInfo, request
if
info
!=
nil
&&
info
.
ChannelMeta
!=
nil
&&
info
.
UpstreamModelName
!=
""
{
modelName
=
info
.
UpstreamModelName
}
if
model_setting
.
ShouldPreserveThinkingSuffix
(
modelName
)
||
info
!=
nil
&&
model_setting
.
ShouldPreserveThinkingSuffix
(
info
.
OriginModelName
)
{
return
}
baseModel
,
thinkingType
,
effort
,
ok
:=
reasoning
.
ParseDeepSeekV4ThinkingSuffix
(
modelName
)
if
ok
{
if
thinkingType
==
"disabled"
{
...
...
relay/channel/openai/adaptor.go
View file @
6b659fd6
...
...
@@ -249,6 +249,18 @@ func (a *Adaptor) ConvertOpenAIRequest(c *gin.Context, info *relaycommon.RelayIn
if
info
.
ChannelType
!=
constant
.
ChannelTypeOpenAI
&&
info
.
ChannelType
!=
constant
.
ChannelTypeAzure
{
request
.
StreamOptions
=
nil
}
// Nested reasoning is an OpenRouter-compatible input dialect and needs
// projection even without a protocol conversion hop. Native top-level
// reasoning_effort stays untouched unless a modifier or conversion applies.
// OpenRouter retains its own dialect normalization below.
preserveSuffix
:=
model_setting
.
ShouldPreserveThinkingSuffix
(
info
.
OriginModelName
)
||
model_setting
.
ShouldPreserveThinkingSuffix
(
info
.
UpstreamModelName
)
upstreamEffort
,
_
:=
reasoning
.
ParseOpenAIReasoningEffortFromModelSuffix
(
info
.
UpstreamModelName
)
originEffort
,
_
:=
reasoning
.
ParseOpenAIReasoningEffortFromModelSuffix
(
info
.
OriginModelName
)
renderReasoning
:=
len
(
request
.
Reasoning
)
>
0
||
len
(
info
.
RequestConversionChain
)
>
1
||
request
.
ReasoningConversion
!=
nil
||
info
.
ReasoningState
()
!=
nil
||
!
preserveSuffix
&&
(
upstreamEffort
!=
""
||
originEffort
!=
""
)
if
info
.
ChannelType
!=
constant
.
ChannelTypeOpenRouter
&&
!
renderReasoning
{
info
.
SetReasoningEffort
(
request
.
ReasoningEffort
)
}
if
info
.
ChannelType
==
constant
.
ChannelTypeOpenRouter
{
initialIntent
,
err
:=
kitreasoning
.
FromOpenAIChat
(
request
)
if
err
!=
nil
{
...
...
@@ -273,7 +285,6 @@ func (a *Adaptor) ConvertOpenAIRequest(c *gin.Context, info *relaycommon.RelayIn
request
.
Usage
=
json
.
RawMessage
(
`{"include":true}`
)
}
// 合并 effort 尾巴产生的意图
preserveSuffix
:=
model_setting
.
ShouldPreserveThinkingSuffix
(
info
.
OriginModelName
)
||
model_setting
.
ShouldPreserveThinkingSuffix
(
info
.
UpstreamModelName
)
mergeEffortSuffix
:=
func
(
modelName
string
)
error
{
rawEffort
,
_
:=
reasoning
.
ParseOpenAIReasoningEffortFromModelSuffix
(
modelName
)
if
rawEffort
==
""
{
...
...
@@ -374,8 +385,7 @@ func (a *Adaptor) ConvertOpenAIRequest(c *gin.Context, info *relaycommon.RelayIn
}
}
if
info
.
ChannelType
!=
constant
.
ChannelTypeOpenRouter
{
preserveSuffix
:=
model_setting
.
ShouldPreserveThinkingSuffix
(
info
.
OriginModelName
)
||
model_setting
.
ShouldPreserveThinkingSuffix
(
info
.
UpstreamModelName
)
if
info
.
ChannelType
!=
constant
.
ChannelTypeOpenRouter
&&
renderReasoning
{
effort
,
baseModel
:=
reasoning
.
ParseOpenAIReasoningEffortFromModelSuffix
(
info
.
UpstreamModelName
)
if
preserveSuffix
{
effort
=
""
...
...
@@ -412,7 +422,7 @@ func (a *Adaptor) ConvertOpenAIRequest(c *gin.Context, info *relaycommon.RelayIn
info
.
UpstreamModelName
=
baseModel
request
.
Model
=
baseModel
}
if
canonicalEffort
:=
kitreasoning
.
OpenAIEffort
(
kitreasoning
.
EffectiveEffort
(
currentIntent
)
);
canonicalEffort
!=
""
{
if
canonicalEffort
:=
kitreasoning
.
EffectiveEffort
(
currentIntent
);
canonicalEffort
!=
""
{
request
.
ReasoningEffort
=
string
(
canonicalEffort
)
info
.
SetReasoningEffort
(
string
(
canonicalEffort
))
}
...
...
@@ -666,6 +676,21 @@ func (a *Adaptor) ConvertOpenAIResponsesRequest(c *gin.Context, info *relaycommo
if
preserveSuffix
{
effort
=
""
}
originEffort
:=
""
if
info
!=
nil
&&
!
preserveSuffix
{
originEffort
,
_
=
reasoning
.
ParseOpenAIReasoningEffortFromModelSuffix
(
info
.
OriginModelName
)
}
crossProtocol
:=
info
!=
nil
&&
len
(
info
.
RequestConversionChain
)
>
1
if
(
info
==
nil
||
info
.
ChannelType
!=
constant
.
ChannelTypeOpenRouter
)
&&
!
crossProtocol
&&
effort
==
""
&&
originEffort
==
""
&&
request
.
ReasoningConversion
==
nil
&&
info
.
ReasoningState
()
==
nil
{
if
info
!=
nil
{
rawEffort
:=
""
if
request
.
Reasoning
!=
nil
{
rawEffort
=
request
.
Reasoning
.
Effort
}
info
.
SetReasoningEffort
(
rawEffort
)
}
return
request
,
nil
}
currentIntent
,
err
:=
kitreasoning
.
FromOpenAIResponses
(
&
request
)
if
err
!=
nil
{
return
nil
,
kitreasoning
.
AsClientError
(
err
)
...
...
@@ -700,7 +725,7 @@ func (a *Adaptor) ConvertOpenAIResponsesRequest(c *gin.Context, info *relaycommo
info
.
UpstreamModelName
=
originModel
}
}
if
canonicalEffort
:=
kitreasoning
.
OpenAIEffort
(
kitreasoning
.
EffectiveEffort
(
currentIntent
)
);
canonicalEffort
!=
""
{
if
canonicalEffort
:=
kitreasoning
.
EffectiveEffort
(
currentIntent
);
canonicalEffort
!=
""
{
if
request
.
Reasoning
==
nil
{
request
.
Reasoning
=
&
dto
.
Reasoning
{}
}
...
...
relay/channel/volcengine/adaptor.go
View file @
6b659fd6
...
...
@@ -308,6 +308,7 @@ func (a *Adaptor) ConvertOpenAIRequest(c *gin.Context, info *relaycommon.RelayIn
}
if
!
model_setting
.
ShouldPreserveThinkingSuffix
(
info
.
OriginModelName
)
&&
!
model_setting
.
ShouldPreserveThinkingSuffix
(
info
.
UpstreamModelName
)
&&
strings
.
HasSuffix
(
info
.
UpstreamModelName
,
"-thinking"
)
&&
strings
.
HasPrefix
(
info
.
UpstreamModelName
,
"deepseek"
)
{
info
.
UpstreamModelName
=
strings
.
TrimSuffix
(
info
.
UpstreamModelName
,
"-thinking"
)
...
...
relay/channel/xai/adaptor.go
View file @
6b659fd6
...
...
@@ -11,6 +11,7 @@ import (
relaycommon
"github.com/QuantumNous/new-api/relay/common"
"github.com/QuantumNous/new-api/relaykit/dto"
"github.com/QuantumNous/new-api/relaykit/types"
"github.com/QuantumNous/new-api/setting/model_setting"
"github.com/QuantumNous/new-api/relay/constant"
...
...
@@ -78,10 +79,11 @@ func (a *Adaptor) ConvertOpenAIRequest(c *gin.Context, info *relaycommon.RelayIn
request
.
MaxCompletionTokens
=
request
.
MaxTokens
request
.
MaxTokens
=
nil
}
if
strings
.
HasSuffix
(
request
.
Model
,
"-high"
)
{
preserveSuffix
:=
model_setting
.
ShouldPreserveThinkingSuffix
(
info
.
OriginModelName
)
||
model_setting
.
ShouldPreserveThinkingSuffix
(
request
.
Model
)
if
!
preserveSuffix
&&
strings
.
HasSuffix
(
request
.
Model
,
"-high"
)
{
request
.
ReasoningEffort
=
"high"
request
.
Model
=
strings
.
TrimSuffix
(
request
.
Model
,
"-high"
)
}
else
if
strings
.
HasSuffix
(
request
.
Model
,
"-low"
)
{
}
else
if
!
preserveSuffix
&&
strings
.
HasSuffix
(
request
.
Model
,
"-low"
)
{
request
.
ReasoningEffort
=
"low"
request
.
Model
=
strings
.
TrimSuffix
(
request
.
Model
,
"-low"
)
}
...
...
relay/common/relay_info.go
View file @
6b659fd6
...
...
@@ -496,9 +496,10 @@ func reasoningEffortFromRequest(request dto.Request) string {
}
case
*
dto
.
GeminiChatRequest
:
if
req
!=
nil
&&
req
.
GenerationConfig
.
ThinkingConfig
!=
nil
{
intent
,
err
:=
kitreasoning
.
FromGemini
(
req
)
if
err
==
nil
{
effort
=
string
(
kitreasoning
.
EffectiveEffort
(
intent
))
config
:=
req
.
GenerationConfig
.
ThinkingConfig
effort
=
config
.
ThinkingLevel
if
effort
==
""
&&
config
.
ThinkingBudget
!=
nil
{
effort
=
string
(
kitreasoning
.
EffortFromBudget
(
*
config
.
ThinkingBudget
))
}
}
}
...
...
relay/helper/model_modifier.go
View file @
6b659fd6
...
...
@@ -211,7 +211,7 @@ func applyModelControls(req dto.Request, parsed parsedModelModifiers) error {
delete
(
reasoningConfig
,
"max_tokens"
)
request
.
ReasoningEffort
=
""
if
parsed
.
intent
.
Effort
!=
""
{
request
.
ReasoningEffort
=
string
(
reasoning
.
OpenAIEffort
(
parsed
.
intent
.
Effort
)
)
request
.
ReasoningEffort
=
string
(
parsed
.
intent
.
Effort
)
}
}
if
len
(
reasoningConfig
)
==
0
{
...
...
@@ -237,7 +237,7 @@ func applyModelControls(req dto.Request, parsed parsedModelModifiers) error {
if
request
.
Reasoning
==
nil
{
request
.
Reasoning
=
&
dto
.
Reasoning
{}
}
request
.
Reasoning
.
Effort
=
string
(
reasoning
.
OpenAIEffort
(
parsed
.
intent
.
Effort
)
)
request
.
Reasoning
.
Effort
=
string
(
parsed
.
intent
.
Effort
)
}
else
if
request
.
Reasoning
!=
nil
&&
parsed
.
intent
.
BudgetTokens
==
nil
{
request
.
Reasoning
.
Effort
=
""
}
...
...
relay/helper/reasoning_suffix.go
View file @
6b659fd6
...
...
@@ -106,6 +106,9 @@ func ApplyReasoningModelSuffix(c *gin.Context, info *relaycommon.RelayInfo, outb
if
info
.
Request
!=
nil
{
info
.
Request
.
SetModelName
(
info
.
UpstreamModelName
)
}
if
selected
.
hasThinking
{
info
.
SetReasoningEffort
(
string
(
reasoning
.
EffectiveEffort
(
selected
.
intent
)))
}
for
i
:=
range
diagnostics
{
diagnostics
[
i
]
.
From
=
info
.
RelayFormat
}
...
...
relaykit/relayconvert/internal/shared/claude/reasoning.go
View file @
6b659fd6
...
...
@@ -35,14 +35,19 @@ func ApplyReasoning(ctx context.Context, req *dto.ClaudeRequest, info convmeta.M
// accounting metadata, but do not run the capability renderer or rewrite
// provider-native controls.
if
!
crossProtocol
&&
source
.
IsEmpty
()
&&
suffix
.
IsEmpty
()
{
native
,
err
:=
reasoning
.
FromClaude
(
req
)
if
err
!=
nil
{
return
err
}
if
info
!=
nil
{
if
effort
:=
reasoning
.
EffectiveEffort
(
native
);
effort
!=
""
{
info
.
SetReasoningEffort
(
string
(
effort
))
effort
:=
req
.
GetEfforts
()
if
effort
==
""
&&
req
.
Thinking
!=
nil
{
switch
{
case
req
.
Thinking
.
Type
==
"disabled"
:
effort
=
string
(
reasoning
.
EffortNone
)
case
req
.
Thinking
.
BudgetTokens
!=
nil
:
effort
=
string
(
reasoning
.
EffortFromBudget
(
*
req
.
Thinking
.
BudgetTokens
))
case
req
.
Thinking
.
Type
==
"enabled"
||
req
.
Thinking
.
Type
==
"adaptive"
:
effort
=
string
(
reasoning
.
EffortHigh
)
}
}
info
.
SetReasoningEffort
(
effort
)
}
return
nil
}
...
...
relaykit/relayconvert/internal/shared/gemini/request.go
View file @
6b659fd6
...
...
@@ -106,14 +106,15 @@ func ApplyThinkingConfig(geminiRequest *dto.GeminiChatRequest, info convmeta.Met
// modifier, read portable effort metadata without running the capability
// renderer or rewriting provider-native controls.
if
!
crossProtocol
&&
suffix
.
IsEmpty
()
{
native
,
err
:=
reasoning
.
FromGemini
(
geminiRequest
)
if
err
!=
nil
{
return
err
}
if
info
!=
nil
{
if
effort
:=
reasoning
.
EffectiveEffort
(
native
);
effort
!=
""
{
info
.
SetReasoningEffort
(
string
(
effort
))
effort
:=
""
if
config
:=
geminiRequest
.
GenerationConfig
.
ThinkingConfig
;
config
!=
nil
{
effort
=
config
.
ThinkingLevel
if
effort
==
""
&&
config
.
ThinkingBudget
!=
nil
{
effort
=
string
(
reasoning
.
EffortFromBudget
(
*
config
.
ThinkingBudget
))
}
}
info
.
SetReasoningEffort
(
effort
)
}
return
nil
}
...
...
relaykit/relayconvert/reasoning/intent.go
View file @
6b659fd6
...
...
@@ -363,8 +363,8 @@ func FromOpenAIChat(req *dto.GeneralOpenAIRequest) (Intent, error) {
BudgetSource
:
SourcePivot
,
}
if
req
.
ReasoningEffort
!=
""
{
p
rojectedEffort
:=
OpenAIEffort
(
EffectiveEffort
(
pivot
)
)
if
Effort
(
req
.
ReasoningEffort
)
==
p
rojected
Effort
{
p
ivotEffort
:=
EffectiveEffort
(
pivot
)
if
Effort
(
req
.
ReasoningEffort
)
==
p
ivot
Effort
{
intent
.
Effort
=
""
intent
.
Mode
=
ModeUnset
}
...
...
@@ -384,7 +384,7 @@ func ApplyToOpenAIChat(req *dto.GeneralOpenAIRequest, intent Intent) error {
return
err
}
if
effort
:=
OpenAIEffort
(
EffectiveEffort
(
intent
)
);
effort
!=
""
{
if
effort
:=
EffectiveEffort
(
intent
);
effort
!=
""
{
req
.
ReasoningEffort
=
string
(
effort
)
}
...
...
@@ -412,7 +412,7 @@ func ApplyToOpenAIResponses(req *dto.OpenAIResponsesRequest, intent Intent) erro
return
err
}
if
effort
:=
OpenAIEffort
(
EffectiveEffort
(
intent
)
);
effort
!=
""
{
if
effort
:=
EffectiveEffort
(
intent
);
effort
!=
""
{
summary
:=
"detailed"
if
effort
==
EffortNone
||
(
intent
.
IncludeThoughts
!=
nil
&&
!*
intent
.
IncludeThoughts
)
{
summary
=
""
...
...
@@ -436,16 +436,6 @@ func ApplyToOpenAIResponses(req *dto.OpenAIResponsesRequest, intent Intent) erro
return
nil
}
// OpenAIEffort maps the canonical cross-provider vocabulary to the public
// OpenAI reasoning_effort vocabulary. Claude/OpenRouter "max" has no direct
// OpenAI equivalent and is represented by xhigh at that wire boundary.
func
OpenAIEffort
(
effort
Effort
)
Effort
{
if
effort
==
EffortMax
{
return
EffortXHigh
}
return
effort
}
func
FromOpenAIResponses
(
req
*
dto
.
OpenAIResponsesRequest
)
(
Intent
,
error
)
{
if
req
==
nil
{
return
Intent
{},
nil
...
...
@@ -481,8 +471,8 @@ func FromOpenAIResponses(req *dto.OpenAIResponsesRequest) (Intent, error) {
BudgetSource
:
SourcePivot
,
}
if
req
.
Reasoning
!=
nil
&&
req
.
Reasoning
.
Effort
!=
""
{
p
rojectedEffort
:=
OpenAIEffort
(
EffectiveEffort
(
pivot
)
)
if
Effort
(
req
.
Reasoning
.
Effort
)
==
p
rojected
Effort
{
p
ivotEffort
:=
EffectiveEffort
(
pivot
)
if
Effort
(
req
.
Reasoning
.
Effort
)
==
p
ivot
Effort
{
intent
.
Effort
=
""
intent
.
Mode
=
ModeUnset
}
...
...
relaykit/relayconvert/reasoning/intent_test.go
View file @
6b659fd6
...
...
@@ -3,6 +3,7 @@ package reasoning
import
(
"testing"
"github.com/QuantumNous/new-api/relaykit/dto"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
...
...
@@ -123,3 +124,49 @@ func TestIntentStateRoundTrip(t *testing.T) {
func
boolPtr
(
v
bool
)
*
bool
{
return
&
v
}
func
TestOpenAIPivotRetainsExactStrengthAndBudget
(
t
*
testing
.
T
)
{
budget
,
include
:=
16384
,
false
for
_
,
effort
:=
range
[]
Effort
{
EffortMax
,
EffortXHigh
}
{
t
.
Run
(
string
(
effort
),
func
(
t
*
testing
.
T
)
{
intent
:=
Intent
{
Mode
:
ModeEnabled
,
Effort
:
effort
,
BudgetTokens
:
&
budget
,
IncludeThoughts
:
&
include
}
chat
:=
&
dto
.
GeneralOpenAIRequest
{}
require
.
NoError
(
t
,
ApplyToOpenAIChat
(
chat
,
intent
))
assert
.
Equal
(
t
,
string
(
effort
),
chat
.
ReasoningEffort
)
restored
,
err
:=
FromOpenAIChat
(
chat
)
require
.
NoError
(
t
,
err
)
assert
.
Equal
(
t
,
effort
,
restored
.
Effort
)
require
.
NotNil
(
t
,
restored
.
BudgetTokens
)
assert
.
Equal
(
t
,
budget
,
*
restored
.
BudgetTokens
)
require
.
NotNil
(
t
,
restored
.
IncludeThoughts
)
assert
.
False
(
t
,
*
restored
.
IncludeThoughts
)
responses
:=
&
dto
.
OpenAIResponsesRequest
{}
require
.
NoError
(
t
,
ApplyToOpenAIResponses
(
responses
,
restored
))
require
.
NotNil
(
t
,
responses
.
Reasoning
)
assert
.
Equal
(
t
,
string
(
effort
),
responses
.
Reasoning
.
Effort
)
restored
,
err
=
FromOpenAIResponses
(
responses
)
require
.
NoError
(
t
,
err
)
assert
.
Equal
(
t
,
effort
,
restored
.
Effort
)
require
.
NotNil
(
t
,
restored
.
BudgetTokens
)
assert
.
Equal
(
t
,
budget
,
*
restored
.
BudgetTokens
)
require
.
NotNil
(
t
,
restored
.
IncludeThoughts
)
assert
.
False
(
t
,
*
restored
.
IncludeThoughts
)
})
}
}
func
TestOpenAIPivotDoesNotTreatMaxAndXHighAsEquivalent
(
t
*
testing
.
T
)
{
intent
:=
Intent
{
Mode
:
ModeEnabled
,
Effort
:
EffortMax
}
chat
:=
&
dto
.
GeneralOpenAIRequest
{}
require
.
NoError
(
t
,
ApplyToOpenAIChat
(
chat
,
intent
))
chat
.
ReasoningEffort
=
"xhigh"
_
,
err
:=
FromOpenAIChat
(
chat
)
require
.
ErrorIs
(
t
,
err
,
ErrEffortConflict
)
responses
:=
&
dto
.
OpenAIResponsesRequest
{}
require
.
NoError
(
t
,
ApplyToOpenAIResponses
(
responses
,
intent
))
responses
.
Reasoning
.
Effort
=
"xhigh"
_
,
err
=
FromOpenAIResponses
(
responses
)
require
.
ErrorIs
(
t
,
err
,
ErrEffortConflict
)
}
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