Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
陈曦
sub2api
Commits
0a9c17b9
Commit
0a9c17b9
authored
Jan 09, 2026
by
shaw
Browse files
Merge PR #213: feat(openai): 支持 OpenAI Responses API 标准内容格式
parents
799b0106
f6a9a0a4
Changes
1
Hide whitespace changes
Inline
Side-by-side
backend/internal/service/openai_gateway_service.go
View file @
0a9c17b9
...
@@ -540,10 +540,19 @@ func (s *OpenAIGatewayService) Forward(ctx context.Context, c *gin.Context, acco
...
@@ -540,10 +540,19 @@ func (s *OpenAIGatewayService) Forward(ctx context.Context, c *gin.Context, acco
bodyModified
=
true
bodyModified
=
true
}
}
// For OAuth accounts using ChatGPT internal API, add store: false
// For OAuth accounts using ChatGPT internal API:
// 1. Add store: false
// 2. Normalize input format for Codex API compatibility
if
account
.
Type
==
AccountTypeOAuth
{
if
account
.
Type
==
AccountTypeOAuth
{
reqBody
[
"store"
]
=
false
reqBody
[
"store"
]
=
false
bodyModified
=
true
bodyModified
=
true
// Normalize input format: convert AI SDK multi-part content format to simplified format
// AI SDK sends: {"content": [{"type": "input_text", "text": "..."}]}
// Codex API expects: {"content": "..."}
if
normalizeInputForCodexAPI
(
reqBody
)
{
bodyModified
=
true
}
}
}
// Re-serialize body only if modified
// Re-serialize body only if modified
...
@@ -1085,6 +1094,101 @@ func (s *OpenAIGatewayService) replaceModelInResponseBody(body []byte, fromModel
...
@@ -1085,6 +1094,101 @@ func (s *OpenAIGatewayService) replaceModelInResponseBody(body []byte, fromModel
return
newBody
return
newBody
}
}
// normalizeInputForCodexAPI converts AI SDK multi-part content format to simplified format
// that the ChatGPT internal Codex API expects.
//
// AI SDK sends content as an array of typed objects:
//
// {"content": [{"type": "input_text", "text": "hello"}]}
//
// ChatGPT Codex API expects content as a simple string:
//
// {"content": "hello"}
//
// This function modifies reqBody in-place and returns true if any modification was made.
func
normalizeInputForCodexAPI
(
reqBody
map
[
string
]
any
)
bool
{
input
,
ok
:=
reqBody
[
"input"
]
if
!
ok
{
return
false
}
// Handle case where input is a simple string (already compatible)
if
_
,
isString
:=
input
.
(
string
);
isString
{
return
false
}
// Handle case where input is an array of messages
inputArray
,
ok
:=
input
.
([]
any
)
if
!
ok
{
return
false
}
modified
:=
false
for
_
,
item
:=
range
inputArray
{
message
,
ok
:=
item
.
(
map
[
string
]
any
)
if
!
ok
{
continue
}
content
,
ok
:=
message
[
"content"
]
if
!
ok
{
continue
}
// If content is already a string, no conversion needed
if
_
,
isString
:=
content
.
(
string
);
isString
{
continue
}
// If content is an array (AI SDK format), convert to string
contentArray
,
ok
:=
content
.
([]
any
)
if
!
ok
{
continue
}
// Extract text from content array
var
textParts
[]
string
for
_
,
part
:=
range
contentArray
{
partMap
,
ok
:=
part
.
(
map
[
string
]
any
)
if
!
ok
{
continue
}
// Handle different content types
partType
,
_
:=
partMap
[
"type"
]
.
(
string
)
switch
partType
{
case
"input_text"
,
"text"
:
// Extract text from input_text or text type
if
text
,
ok
:=
partMap
[
"text"
]
.
(
string
);
ok
{
textParts
=
append
(
textParts
,
text
)
}
case
"input_image"
,
"image"
:
// For images, we need to preserve the original format
// as ChatGPT Codex API may support images in a different way
// For now, skip image parts (they will be lost in conversion)
// TODO: Consider preserving image data or handling it separately
continue
case
"input_file"
,
"file"
:
// Similar to images, file inputs may need special handling
continue
default
:
// For unknown types, try to extract text if available
if
text
,
ok
:=
partMap
[
"text"
]
.
(
string
);
ok
{
textParts
=
append
(
textParts
,
text
)
}
}
}
// Convert content array to string
if
len
(
textParts
)
>
0
{
message
[
"content"
]
=
strings
.
Join
(
textParts
,
"
\n
"
)
modified
=
true
}
}
return
modified
}
// OpenAIRecordUsageInput input for recording usage
// OpenAIRecordUsageInput input for recording usage
type
OpenAIRecordUsageInput
struct
{
type
OpenAIRecordUsageInput
struct
{
Result
*
OpenAIForwardResult
Result
*
OpenAIForwardResult
...
...
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