mirror of
https://github.com/Wei-Shaw/sub2api.git
synced 2026-10-14 12:02:27 +08:00
fix(codex-models): 非 GPT 模型的 Codex 提示词模板去掉 GPT 身份声明,避免 Antigravity 429
模型目录对所有模型都用 openai.CodexBaseInstructionsForModel 填 instructions_template, gemini / claude 等因此下发 "You are Codex, a coding agent based on GPT-5."。Codex 把它作为 instructions 发出,Antigravity 对「Codex 提示词 + GPT-5 身份」返回 429 RESOURCE_EXHAUSTED, 并让账号进入限流冷却。 OpenAI GPT 模型保持原模板;其他模型族(含 gpt-oss)去掉 "based on GPT-N" / "You are GPT-N" 身份声明,提示词其余部分不变。 Refs #7307
This commit is contained in:
@@ -11,6 +11,7 @@ import (
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
@@ -443,7 +444,7 @@ func newConfiguredCodexModelDescriptor(modelID string) configuredCodexModelDescr
|
||||
Priority: configuredCodexModelPriority,
|
||||
AdditionalSpeedTiers: []string{},
|
||||
ServiceTiers: []configuredCodexServiceTier{},
|
||||
ModelMessages: configuredCodexModelMessages{InstructionsTemplate: openai.CodexBaseInstructionsForModel(modelID)},
|
||||
ModelMessages: configuredCodexModelMessages{InstructionsTemplate: codexInstructionsTemplateForModel(modelID)},
|
||||
SupportsReasoningSummaryParameter: true,
|
||||
DefaultReasoningSummary: "auto",
|
||||
WebSearchToolType: "text",
|
||||
@@ -636,6 +637,47 @@ func configuredCodexGPTReasoningLevels(modelID string) []configuredCodexReasonin
|
||||
return levels
|
||||
}
|
||||
|
||||
// codexGPTIdentityPatterns match the GPT self-identification that the bundled
|
||||
// Codex prompts open with:
|
||||
// - "You are Codex, a coding agent based on GPT-5." / "…an agent based on GPT-6." / "You are Codex, based on GPT-5."
|
||||
// - "You are GPT-5.1 running in the Codex CLI, …"
|
||||
var codexGPTIdentityPatterns = []struct {
|
||||
re *regexp.Regexp
|
||||
repl string
|
||||
}{
|
||||
{regexp.MustCompile(`,?\s*based on GPT-\d+(?:\.\d+)?(?:-[A-Za-z0-9]+)*`), ""},
|
||||
{regexp.MustCompile(`\bYou are GPT-\d+(?:\.\d+)?(?:-[A-Za-z0-9]+)*`), "You are Codex"},
|
||||
}
|
||||
|
||||
// codexInstructionsTemplateForModel returns the Codex base prompt advertised for
|
||||
// modelID in the models manifest.
|
||||
//
|
||||
// OpenAI GPT models keep the bundled prompt verbatim. Every other family the
|
||||
// manifest can list (Gemini, Claude, DeepSeek, Grok, gpt-oss, custom aliases)
|
||||
// gets the same prompt without the GPT self-identification: the claim is false
|
||||
// for those models, and Google's Antigravity backend answers requests whose
|
||||
// system prompt is the Codex prompt carrying a "GPT-5" identity with
|
||||
// 429 RESOURCE_EXHAUSTED — which also puts the account into rate-limit
|
||||
// cooldown. Codex sends this template as `instructions` for the selected model.
|
||||
func codexInstructionsTemplateForModel(modelID string) string {
|
||||
base := openai.CodexBaseInstructionsForModel(modelID)
|
||||
if codexModelKeepsGPTIdentity(modelID) {
|
||||
return base
|
||||
}
|
||||
for _, p := range codexGPTIdentityPatterns {
|
||||
base = p.re.ReplaceAllString(base, p.repl)
|
||||
}
|
||||
return base
|
||||
}
|
||||
|
||||
// codexModelKeepsGPTIdentity reports whether modelID is an OpenAI GPT model
|
||||
// whose Codex prompt may claim a GPT identity. gpt-oss models are open-weight
|
||||
// and typically served by non-OpenAI providers, so they do not.
|
||||
func codexModelKeepsGPTIdentity(modelID string) bool {
|
||||
return isOpenAICodexGPTModel(modelID) &&
|
||||
!strings.HasPrefix(canonicalizeOpenAIModelAliasSpelling(modelID), "gpt-oss")
|
||||
}
|
||||
|
||||
func isOpenAICodexGPTModel(modelID string) bool {
|
||||
normalized := canonicalizeOpenAIModelAliasSpelling(modelID)
|
||||
if normalized == "" || strings.HasPrefix(normalized, "gpt-image") {
|
||||
|
||||
@@ -3703,3 +3703,59 @@ func TestFetchCodexModelsManifestOAuthSharedAcrossGroupsWithIndependentFiltering
|
||||
require.Equal(t, []string{"model-b"}, got[92])
|
||||
require.EqualValues(t, 1, calls.Load(), "同一账号两个分组同时请求时只发一次上游请求")
|
||||
}
|
||||
|
||||
// Scenario: 非 OpenAI GPT 模型的 Codex 提示词不声称自己是 GPT。
|
||||
// Antigravity(Google) 对「Codex 提示词 + GPT-5 身份」直接回 429 RESOURCE_EXHAUSTED。
|
||||
func TestBuildCodexModelsManifestStripsGPTIdentityForNonGPTModels(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
nonGPT := []string{
|
||||
"gemini-3-flash", "claude-sonnet-4-6", "deepseek-v4-flash", "grok-4.3",
|
||||
"gpt-oss-120b-medium", "company-coding-model", "company-codex-alias",
|
||||
}
|
||||
body, err := BuildCodexModelsManifest(nonGPT)
|
||||
require.NoError(t, err)
|
||||
|
||||
var manifest struct {
|
||||
Models []struct {
|
||||
Slug string `json:"slug"`
|
||||
ModelMessages struct {
|
||||
InstructionsTemplate string `json:"instructions_template"`
|
||||
} `json:"model_messages"`
|
||||
} `json:"models"`
|
||||
}
|
||||
require.NoError(t, json.Unmarshal(body, &manifest))
|
||||
require.Len(t, manifest.Models, len(nonGPT))
|
||||
for _, m := range manifest.Models {
|
||||
tmpl := m.ModelMessages.InstructionsTemplate
|
||||
require.NotContains(t, tmpl, "GPT-", m.Slug)
|
||||
require.True(t, strings.HasPrefix(tmpl, "You are Codex"), "%s: %.60q", m.Slug, tmpl)
|
||||
// Only the identity clause is removed; the rest of the bundled prompt is kept.
|
||||
base := openai.CodexBaseInstructionsForModel(m.Slug)
|
||||
require.Less(t, len(base)-len(tmpl), 32, m.Slug)
|
||||
}
|
||||
}
|
||||
|
||||
// Scenario: OpenAI GPT 模型的 Codex 提示词保持原样。
|
||||
func TestBuildCodexModelsManifestKeepsGPTIdentityForGPTModels(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
for _, model := range []string{"gpt-5.5", "gpt-6-astra", "gpt-5.2", "gpt-5.3-codex-spark"} {
|
||||
require.Equal(t, openai.CodexBaseInstructionsForModel(model), codexInstructionsTemplateForModel(model), model)
|
||||
}
|
||||
}
|
||||
|
||||
// Scenario: 每份内置 Codex 提示词的身份声明都能被识别并去掉。
|
||||
func TestCodexGPTIdentityPatternsCoverBundledPrompts(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
for _, model := range []string{"gpt-5.1", "gpt-5.2", "gpt-5.5", "gpt-6-astra", "gpt-5-codex"} {
|
||||
tmpl := openai.CodexBaseInstructionsForModel(model)
|
||||
require.Contains(t, tmpl, "GPT-", "bundled prompt for %s changed; update this test", model)
|
||||
for _, p := range codexGPTIdentityPatterns {
|
||||
tmpl = p.re.ReplaceAllString(tmpl, p.repl)
|
||||
}
|
||||
require.NotContains(t, tmpl, "GPT-", model)
|
||||
require.True(t, strings.HasPrefix(tmpl, "You are Codex"), "%s: %.60q", model, tmpl)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user