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
eb06006d
Commit
eb06006d
authored
Jan 10, 2026
by
cyhhao
Browse files
Make Codex CLI passthrough
parent
7a06c487
Changes
3
Show whitespace changes
Inline
Side-by-side
backend/internal/handler/openai_gateway_handler.go
View file @
eb06006d
...
@@ -11,7 +11,6 @@ import (
...
@@ -11,7 +11,6 @@ import (
"time"
"time"
"github.com/Wei-Shaw/sub2api/internal/config"
"github.com/Wei-Shaw/sub2api/internal/config"
"github.com/Wei-Shaw/sub2api/internal/pkg/openai"
middleware2
"github.com/Wei-Shaw/sub2api/internal/server/middleware"
middleware2
"github.com/Wei-Shaw/sub2api/internal/server/middleware"
"github.com/Wei-Shaw/sub2api/internal/service"
"github.com/Wei-Shaw/sub2api/internal/service"
...
@@ -92,17 +91,7 @@ func (h *OpenAIGatewayHandler) Responses(c *gin.Context) {
...
@@ -92,17 +91,7 @@ func (h *OpenAIGatewayHandler) Responses(c *gin.Context) {
return
return
}
}
// For non-Codex CLI requests, set default instructions
userAgent
:=
c
.
GetHeader
(
"User-Agent"
)
userAgent
:=
c
.
GetHeader
(
"User-Agent"
)
if
!
openai
.
IsCodexCLIRequest
(
userAgent
)
{
reqBody
[
"instructions"
]
=
openai
.
DefaultInstructions
// Re-serialize body
body
,
err
=
json
.
Marshal
(
reqBody
)
if
err
!=
nil
{
h
.
errorResponse
(
c
,
http
.
StatusInternalServerError
,
"api_error"
,
"Failed to process request"
)
return
}
}
// Track if we've started streaming (for error handling)
// Track if we've started streaming (for error handling)
streamStarted
:=
false
streamStarted
:=
false
...
...
backend/internal/service/openai_codex_transform.go
View file @
eb06006d
...
@@ -135,7 +135,7 @@ func codexModeEnabled() bool {
...
@@ -135,7 +135,7 @@ func codexModeEnabled() bool {
}
}
}
}
func
applyCodexOAuthTransform
(
reqBody
map
[
string
]
any
,
codexMode
bool
)
codexTransformResult
{
func
applyCodexOAuthTransform
(
reqBody
map
[
string
]
any
)
codexTransformResult
{
result
:=
codexTransformResult
{}
result
:=
codexTransformResult
{}
model
:=
""
model
:=
""
...
@@ -151,16 +151,13 @@ func applyCodexOAuthTransform(reqBody map[string]any, codexMode bool) codexTrans
...
@@ -151,16 +151,13 @@ func applyCodexOAuthTransform(reqBody map[string]any, codexMode bool) codexTrans
result
.
NormalizedModel
=
normalizedModel
result
.
NormalizedModel
=
normalizedModel
}
}
if
v
,
ok
:=
reqBody
[
"store"
]
.
(
bool
);
!
ok
||
v
{
reqBody
[
"store"
]
=
false
reqBody
[
"store"
]
=
false
reqBody
[
"stream"
]
=
true
result
.
Modified
=
true
instructions
:=
getCodexInstructions
(
normalizedModel
)
if
instructions
!=
""
{
if
existing
,
ok
:=
reqBody
[
"instructions"
]
.
(
string
);
!
ok
||
existing
!=
instructions
{
reqBody
[
"instructions"
]
=
instructions
result
.
Modified
=
true
result
.
Modified
=
true
}
}
if
v
,
ok
:=
reqBody
[
"stream"
]
.
(
bool
);
!
ok
||
!
v
{
reqBody
[
"stream"
]
=
true
result
.
Modified
=
true
}
}
if
_
,
ok
:=
reqBody
[
"max_output_tokens"
];
ok
{
if
_
,
ok
:=
reqBody
[
"max_output_tokens"
];
ok
{
...
@@ -180,46 +177,27 @@ func applyCodexOAuthTransform(reqBody map[string]any, codexMode bool) codexTrans
...
@@ -180,46 +177,27 @@ func applyCodexOAuthTransform(reqBody map[string]any, codexMode bool) codexTrans
result
.
PromptCacheKey
=
strings
.
TrimSpace
(
v
)
result
.
PromptCacheKey
=
strings
.
TrimSpace
(
v
)
}
}
instructions
:=
strings
.
TrimSpace
(
getCodexInstructions
(
normalizedModel
))
existingInstructions
,
_
:=
reqBody
[
"instructions"
]
.
(
string
)
existingInstructions
=
strings
.
TrimSpace
(
existingInstructions
)
if
instructions
!=
""
{
if
existingInstructions
!=
""
&&
existingInstructions
!=
instructions
{
if
input
,
ok
:=
reqBody
[
"input"
]
.
([]
any
);
ok
{
if
input
,
ok
:=
reqBody
[
"input"
]
.
([]
any
);
ok
{
input
=
filterCodexInput
(
input
)
reqBody
[
"input"
]
=
prependSystemInstruction
(
input
,
existingInstructions
)
if
codexMode
{
cachedPrompt
:=
getOpenCodeCodexPrompt
()
input
=
filterOpenCodeSystemPromptsWithCachedPrompt
(
input
,
cachedPrompt
)
if
hasTools
(
reqBody
)
{
input
=
addCodexBridgeMessage
(
input
)
}
}
else
if
hasTools
(
reqBody
)
{
input
=
addToolRemapMessage
(
input
)
}
input
=
normalizeOrphanedToolOutputs
(
input
)
reqBody
[
"input"
]
=
input
result
.
Modified
=
true
result
.
Modified
=
true
}
}
effort
,
summary
:=
resolveCodexReasoning
(
reqBody
,
normalizedModel
)
if
effort
!=
""
||
summary
!=
""
{
reasoning
:=
ensureMap
(
reqBody
[
"reasoning"
])
if
effort
!=
""
{
reasoning
[
"effort"
]
=
effort
}
if
summary
!=
""
{
reasoning
[
"summary"
]
=
summary
}
}
reqBody
[
"reasoning"
]
=
reasoning
if
existingInstructions
!=
instructions
{
reqBody
[
"instructions"
]
=
instructions
result
.
Modified
=
true
result
.
Modified
=
true
}
}
textVerbosity
:=
resolveTextVerbosity
(
reqBody
)
if
textVerbosity
!=
""
{
text
:=
ensureMap
(
reqBody
[
"text"
])
text
[
"verbosity"
]
=
textVerbosity
reqBody
[
"text"
]
=
text
result
.
Modified
=
true
}
}
include
:=
resolveInclude
(
reqBody
)
if
input
,
ok
:=
reqBody
[
"input"
]
.
([]
any
);
ok
{
if
include
!=
nil
{
input
=
filterCodexInput
(
input
)
reqBody
[
"include"
]
=
include
input
=
normalizeOrphanedToolOutputs
(
input
)
reqBody
[
"input"
]
=
input
result
.
Modified
=
true
result
.
Modified
=
true
}
}
...
@@ -487,6 +465,19 @@ func filterCodexInput(input []any) []any {
...
@@ -487,6 +465,19 @@ func filterCodexInput(input []any) []any {
return
filtered
return
filtered
}
}
func
prependSystemInstruction
(
input
[]
any
,
instructions
string
)
[]
any
{
message
:=
map
[
string
]
any
{
"role"
:
"system"
,
"content"
:
[]
any
{
map
[
string
]
any
{
"type"
:
"input_text"
,
"text"
:
instructions
,
},
},
}
return
append
([]
any
{
message
},
input
...
)
}
func
filterOpenCodeSystemPromptsWithCachedPrompt
(
input
[]
any
,
cachedPrompt
string
)
[]
any
{
func
filterOpenCodeSystemPromptsWithCachedPrompt
(
input
[]
any
,
cachedPrompt
string
)
[]
any
{
if
len
(
input
)
==
0
{
if
len
(
input
)
==
0
{
return
input
return
input
...
...
backend/internal/service/openai_gateway_service.go
View file @
eb06006d
...
@@ -21,6 +21,7 @@ import (
...
@@ -21,6 +21,7 @@ import (
"time"
"time"
"github.com/Wei-Shaw/sub2api/internal/config"
"github.com/Wei-Shaw/sub2api/internal/config"
"github.com/Wei-Shaw/sub2api/internal/pkg/openai"
"github.com/Wei-Shaw/sub2api/internal/util/responseheaders"
"github.com/Wei-Shaw/sub2api/internal/util/responseheaders"
"github.com/Wei-Shaw/sub2api/internal/util/urlvalidator"
"github.com/Wei-Shaw/sub2api/internal/util/urlvalidator"
"github.com/gin-gonic/gin"
"github.com/gin-gonic/gin"
...
@@ -530,20 +531,28 @@ func (s *OpenAIGatewayService) Forward(ctx context.Context, c *gin.Context, acco
...
@@ -530,20 +531,28 @@ func (s *OpenAIGatewayService) Forward(ctx context.Context, c *gin.Context, acco
reqModel
,
_
:=
reqBody
[
"model"
]
.
(
string
)
reqModel
,
_
:=
reqBody
[
"model"
]
.
(
string
)
reqStream
,
_
:=
reqBody
[
"stream"
]
.
(
bool
)
reqStream
,
_
:=
reqBody
[
"stream"
]
.
(
bool
)
promptCacheKey
:=
""
promptCacheKey
:=
""
if
v
,
ok
:=
reqBody
[
"prompt_cache_key"
]
.
(
string
);
ok
{
promptCacheKey
=
strings
.
TrimSpace
(
v
)
}
// Track if body needs re-serialization
// Track if body needs re-serialization
bodyModified
:=
false
bodyModified
:=
false
originalModel
:=
reqModel
originalModel
:=
reqModel
// Apply model mapping
isCodexCLI
:=
openai
.
IsCodexCLIRequest
(
c
.
GetHeader
(
"User-Agent"
))
mappedModel
:=
account
.
GetMappedModel
(
reqModel
)
// Apply model mapping (skip for Codex CLI for transparent forwarding)
mappedModel
:=
reqModel
if
!
isCodexCLI
{
mappedModel
=
account
.
GetMappedModel
(
reqModel
)
if
mappedModel
!=
reqModel
{
if
mappedModel
!=
reqModel
{
reqBody
[
"model"
]
=
mappedModel
reqBody
[
"model"
]
=
mappedModel
bodyModified
=
true
bodyModified
=
true
}
}
}
if
account
.
Type
==
AccountTypeOAuth
{
if
account
.
Type
==
AccountTypeOAuth
&&
!
isCodexCLI
{
codexResult
:=
applyCodexOAuthTransform
(
reqBody
,
codexModeEnabled
()
)
codexResult
:=
applyCodexOAuthTransform
(
reqBody
)
if
codexResult
.
Modified
{
if
codexResult
.
Modified
{
bodyModified
=
true
bodyModified
=
true
}
}
...
...
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