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
3e5bc637
authored
Aug 26, 2025
by
CaIon
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fix: Invalid type for 'input[x].summary': expected an array of objects, but got null instead
parent
f249cf9a
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
73 additions
and
28 deletions
+73
-28
common/json.go
+22
-0
dto/openai_request.go
+40
-25
relay/channel/openai/adaptor.go
+8
-2
relay/channel/openai/relay_responses.go
+2
-0
relay/common/relay_info.go
+1
-1
No files found.
common/json.go
View file @
3e5bc637
...
@@ -20,3 +20,25 @@ func DecodeJson(reader *bytes.Reader, v any) error {
...
@@ -20,3 +20,25 @@ func DecodeJson(reader *bytes.Reader, v any) error {
func
Marshal
(
v
any
)
([]
byte
,
error
)
{
func
Marshal
(
v
any
)
([]
byte
,
error
)
{
return
json
.
Marshal
(
v
)
return
json
.
Marshal
(
v
)
}
}
func
GetJsonType
(
data
json
.
RawMessage
)
string
{
data
=
bytes
.
TrimSpace
(
data
)
if
len
(
data
)
==
0
{
return
"unknown"
}
firstChar
:=
bytes
.
TrimSpace
(
data
)[
0
]
switch
firstChar
{
case
'{'
:
return
"object"
case
'['
:
return
"array"
case
'"'
:
return
"string"
case
't'
,
'f'
:
return
"boolean"
case
'n'
:
return
"null"
default
:
return
"number"
}
}
dto/openai_request.go
View file @
3e5bc637
...
@@ -760,27 +760,27 @@ type WebSearchOptions struct {
...
@@ -760,27 +760,27 @@ type WebSearchOptions struct {
// https://platform.openai.com/docs/api-reference/responses/create
// https://platform.openai.com/docs/api-reference/responses/create
type
OpenAIResponsesRequest
struct
{
type
OpenAIResponsesRequest
struct
{
Model
string
`json:"model"`
Model
string
`json:"model"`
Input
any
`json:"input,omitempty"`
Input
json
.
RawMessage
`json:"input,omitempty"`
Include
json
.
RawMessage
`json:"include,omitempty"`
Include
json
.
RawMessage
`json:"include,omitempty"`
Instructions
json
.
RawMessage
`json:"instructions,omitempty"`
Instructions
json
.
RawMessage
`json:"instructions,omitempty"`
MaxOutputTokens
uint
`json:"max_output_tokens,omitempty"`
MaxOutputTokens
uint
`json:"max_output_tokens,omitempty"`
Metadata
json
.
RawMessage
`json:"metadata,omitempty"`
Metadata
json
.
RawMessage
`json:"metadata,omitempty"`
ParallelToolCalls
bool
`json:"parallel_tool_calls,omitempty"`
ParallelToolCalls
bool
`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"`
ServiceTier
string
`json:"service_tier,omitempty"`
ServiceTier
string
`json:"service_tier,omitempty"`
Store
bool
`json:"store,omitempty"`
Store
bool
`json:"store,omitempty"`
Stream
bool
`json:"stream,omitempty"`
Stream
bool
`json:"stream,omitempty"`
Temperature
float64
`json:"temperature,omitempty"`
Temperature
float64
`json:"temperature,omitempty"`
Text
json
.
RawMessage
`json:"text,omitempty"`
Text
json
.
RawMessage
`json:"text,omitempty"`
ToolChoice
json
.
RawMessage
`json:"tool_choice,omitempty"`
ToolChoice
json
.
RawMessage
`json:"tool_choice,omitempty"`
Tools
[]
map
[
string
]
any
`json:"tools,omitempty"`
// 需要处理的参数很少,MCP 参数太多不确定,所以用 map
Tools
json
.
RawMessage
`json:"tools,omitempty"`
// 需要处理的参数很少,MCP 参数太多不确定,所以用 map
TopP
float64
`json:"top_p,omitempty"`
TopP
float64
`json:"top_p,omitempty"`
Truncation
string
`json:"truncation,omitempty"`
Truncation
string
`json:"truncation,omitempty"`
User
string
`json:"user,omitempty"`
User
string
`json:"user,omitempty"`
MaxToolCalls
uint
`json:"max_tool_calls,omitempty"`
MaxToolCalls
uint
`json:"max_tool_calls,omitempty"`
Prompt
json
.
RawMessage
`json:"prompt,omitempty"`
Prompt
json
.
RawMessage
`json:"prompt,omitempty"`
}
}
func
(
r
*
OpenAIResponsesRequest
)
GetTokenCountMeta
()
*
types
.
TokenCountMeta
{
func
(
r
*
OpenAIResponsesRequest
)
GetTokenCountMeta
()
*
types
.
TokenCountMeta
{
...
@@ -832,8 +832,7 @@ func (r *OpenAIResponsesRequest) GetTokenCountMeta() *types.TokenCountMeta {
...
@@ -832,8 +832,7 @@ func (r *OpenAIResponsesRequest) GetTokenCountMeta() *types.TokenCountMeta {
}
}
if
len
(
r
.
Tools
)
>
0
{
if
len
(
r
.
Tools
)
>
0
{
toolStr
,
_
:=
common
.
Marshal
(
r
.
Tools
)
texts
=
append
(
texts
,
string
(
r
.
Tools
))
texts
=
append
(
texts
,
string
(
toolStr
))
}
}
return
&
types
.
TokenCountMeta
{
return
&
types
.
TokenCountMeta
{
...
@@ -853,6 +852,14 @@ func (r *OpenAIResponsesRequest) SetModelName(modelName string) {
...
@@ -853,6 +852,14 @@ func (r *OpenAIResponsesRequest) SetModelName(modelName string) {
}
}
}
}
func
(
r
*
OpenAIResponsesRequest
)
GetToolsMap
()
[]
map
[
string
]
any
{
var
toolsMap
[]
map
[
string
]
any
if
len
(
r
.
Tools
)
>
0
{
_
=
common
.
Unmarshal
(
r
.
Tools
,
&
toolsMap
)
}
return
toolsMap
}
type
Reasoning
struct
{
type
Reasoning
struct
{
Effort
string
`json:"effort,omitempty"`
Effort
string
`json:"effort,omitempty"`
Summary
string
`json:"summary,omitempty"`
Summary
string
`json:"summary,omitempty"`
...
@@ -879,13 +886,21 @@ func (r *OpenAIResponsesRequest) ParseInput() []MediaInput {
...
@@ -879,13 +886,21 @@ func (r *OpenAIResponsesRequest) ParseInput() []MediaInput {
var
inputs
[]
MediaInput
var
inputs
[]
MediaInput
// Try string first
// Try string first
if
str
,
ok
:=
r
.
Input
.
(
string
);
ok
{
// if str, ok := common.GetJsonType(r.Input); ok {
// inputs = append(inputs, MediaInput{Type: "input_text", Text: str})
// return inputs
// }
if
common
.
GetJsonType
(
r
.
Input
)
==
"string"
{
var
str
string
_
=
common
.
Unmarshal
(
r
.
Input
,
&
str
)
inputs
=
append
(
inputs
,
MediaInput
{
Type
:
"input_text"
,
Text
:
str
})
inputs
=
append
(
inputs
,
MediaInput
{
Type
:
"input_text"
,
Text
:
str
})
return
inputs
return
inputs
}
}
// Try array of parts
// Try array of parts
if
array
,
ok
:=
r
.
Input
.
([]
any
);
ok
{
if
common
.
GetJsonType
(
r
.
Input
)
==
"array"
{
var
array
[]
any
_
=
common
.
Unmarshal
(
r
.
Input
,
&
array
)
for
_
,
itemAny
:=
range
array
{
for
_
,
itemAny
:=
range
array
{
// Already parsed MediaInput
// Already parsed MediaInput
if
media
,
ok
:=
itemAny
.
(
MediaInput
);
ok
{
if
media
,
ok
:=
itemAny
.
(
MediaInput
);
ok
{
...
...
relay/channel/openai/adaptor.go
View file @
3e5bc637
...
@@ -537,8 +537,14 @@ func detectImageMimeType(filename string) string {
...
@@ -537,8 +537,14 @@ func detectImageMimeType(filename string) string {
func
(
a
*
Adaptor
)
ConvertOpenAIResponsesRequest
(
c
*
gin
.
Context
,
info
*
relaycommon
.
RelayInfo
,
request
dto
.
OpenAIResponsesRequest
)
(
any
,
error
)
{
func
(
a
*
Adaptor
)
ConvertOpenAIResponsesRequest
(
c
*
gin
.
Context
,
info
*
relaycommon
.
RelayInfo
,
request
dto
.
OpenAIResponsesRequest
)
(
any
,
error
)
{
// 转换模型推理力度后缀
// 转换模型推理力度后缀
effort
,
originModel
:=
parseReasoningEffortFromModelSuffix
(
request
.
Model
)
effort
,
originModel
:=
parseReasoningEffortFromModelSuffix
(
request
.
Model
)
if
effort
!=
""
&&
request
.
Reasoning
!=
nil
{
if
effort
!=
""
{
request
.
Reasoning
.
Effort
=
effort
if
request
.
Reasoning
==
nil
{
request
.
Reasoning
=
&
dto
.
Reasoning
{
Effort
:
effort
,
}
}
else
{
request
.
Reasoning
.
Effort
=
effort
}
request
.
Model
=
originModel
request
.
Model
=
originModel
}
}
return
request
,
nil
return
request
,
nil
...
...
relay/channel/openai/relay_responses.go
View file @
3e5bc637
...
@@ -92,6 +92,8 @@ func OaiResponsesStreamHandler(c *gin.Context, info *relaycommon.RelayInfo, resp
...
@@ -92,6 +92,8 @@ func OaiResponsesStreamHandler(c *gin.Context, info *relaycommon.RelayInfo, resp
}
}
}
}
}
}
}
else
{
logger
.
LogError
(
c
,
"failed to unmarshal stream response: "
+
err
.
Error
())
}
}
return
true
return
true
})
})
...
...
relay/common/relay_info.go
View file @
3e5bc637
...
@@ -313,7 +313,7 @@ func GenRelayInfoResponses(c *gin.Context, request *dto.OpenAIResponsesRequest)
...
@@ -313,7 +313,7 @@ func GenRelayInfoResponses(c *gin.Context, request *dto.OpenAIResponsesRequest)
BuiltInTools
:
make
(
map
[
string
]
*
BuildInToolInfo
),
BuiltInTools
:
make
(
map
[
string
]
*
BuildInToolInfo
),
}
}
if
len
(
request
.
Tools
)
>
0
{
if
len
(
request
.
Tools
)
>
0
{
for
_
,
tool
:=
range
request
.
Tools
{
for
_
,
tool
:=
range
request
.
GetToolsMap
()
{
toolType
:=
common
.
Interface2String
(
tool
[
"type"
])
toolType
:=
common
.
Interface2String
(
tool
[
"type"
])
info
.
ResponsesUsageInfo
.
BuiltInTools
[
toolType
]
=
&
BuildInToolInfo
{
info
.
ResponsesUsageInfo
.
BuiltInTools
[
toolType
]
=
&
BuildInToolInfo
{
ToolName
:
toolType
,
ToolName
:
toolType
,
...
...
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