constants.go 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. // Package openai provides helpers and types for OpenAI API integration.
  2. package openai
  3. import (
  4. _ "embed"
  5. "strings"
  6. )
  7. // Model represents an OpenAI model
  8. type Model struct {
  9. ID string `json:"id"`
  10. Object string `json:"object"`
  11. Created int64 `json:"created"`
  12. OwnedBy string `json:"owned_by"`
  13. Type string `json:"type"`
  14. DisplayName string `json:"display_name"`
  15. }
  16. // DefaultModels OpenAI models list
  17. var DefaultModels = []Model{
  18. {ID: "gpt-5.6-sol", Object: "model", Created: 1780876800, OwnedBy: "openai", Type: "model", DisplayName: "GPT-5.6 Sol"},
  19. {ID: "gpt-6", Object: "model", Created: 1788480000, OwnedBy: "openai", Type: "model", DisplayName: "GPT-6 (Astra)"},
  20. {ID: "gpt-5.6", Object: "model", Created: 1780876800, OwnedBy: "openai", Type: "model", DisplayName: "GPT-5.6 (Sol)"},
  21. {ID: "gpt-5.6-terra", Object: "model", Created: 1780876800, OwnedBy: "openai", Type: "model", DisplayName: "GPT-5.6 Terra"},
  22. {ID: "gpt-5.6-luna", Object: "model", Created: 1780876800, OwnedBy: "openai", Type: "model", DisplayName: "GPT-5.6 Luna"},
  23. {ID: "gpt-6-astra", Object: "model", Created: 1788480000, OwnedBy: "openai", Type: "model", DisplayName: "GPT-6 Astra"},
  24. {ID: "gpt-5.5", Object: "model", Created: 1776873600, OwnedBy: "openai", Type: "model", DisplayName: "GPT-5.5"},
  25. {ID: "gpt-5.4", Object: "model", Created: 1738368000, OwnedBy: "openai", Type: "model", DisplayName: "GPT-5.4"},
  26. {ID: "gpt-5.4-mini", Object: "model", Created: 1738368000, OwnedBy: "openai", Type: "model", DisplayName: "GPT-5.4 Mini"},
  27. {ID: "gpt-5.3-codex-spark", Object: "model", Created: 1735689600, OwnedBy: "openai", Type: "model", DisplayName: "GPT-5.3 Codex Spark"},
  28. {ID: "codex-auto-review", Object: "model", Created: 1776902400, OwnedBy: "openai", Type: "model", DisplayName: "Codex Auto Review"},
  29. {ID: "gpt-5.2", Object: "model", Created: 1733875200, OwnedBy: "openai", Type: "model", DisplayName: "GPT-5.2"},
  30. {ID: "gpt-image-1", Object: "model", Created: 1733875200, OwnedBy: "openai", Type: "model", DisplayName: "GPT Image 1"},
  31. {ID: "gpt-image-1.5", Object: "model", Created: 1735689600, OwnedBy: "openai", Type: "model", DisplayName: "GPT Image 1.5"},
  32. {ID: "gpt-image-2", Object: "model", Created: 1738368000, OwnedBy: "openai", Type: "model", DisplayName: "GPT Image 2"},
  33. {ID: "gpt-image-2.5-flare", Object: "model", Created: 1788825600, OwnedBy: "openai", Type: "model", DisplayName: "GPT Image 2.5 Flare"},
  34. {ID: "gpt-image-2.5-sunburst", Object: "model", Created: 1788825600, OwnedBy: "openai", Type: "model", DisplayName: "GPT Image 2.5 Sunburst"},
  35. }
  36. // DefaultModelIDs returns the default model ID list
  37. func DefaultModelIDs() []string {
  38. ids := make([]string, len(DefaultModels))
  39. for i, m := range DefaultModels {
  40. ids[i] = m.ID
  41. }
  42. return ids
  43. }
  44. // DefaultTestModel default model for testing OpenAI accounts
  45. const DefaultTestModel = "gpt-5.4"
  46. // CodexUsageProbeModel is the model used for OAuth Codex usage probes.
  47. const CodexUsageProbeModel = "codex-auto-review"
  48. // DefaultInstructions default instructions for non-Codex CLI requests.
  49. // 内容为真实 Codex CLI 的 GPT-5-Codex base prompt(codex 系模型默认)。
  50. //
  51. //go:embed instructions.txt
  52. var DefaultInstructions string
  53. // instructionsGPT51 / instructionsGPT52 / instructionsGPT55 / instructionsGPT6Astra
  54. // 为对应非 codex 模型的真实 Codex 编码 agent base prompt,用于模型感知的 instructions 选择。
  55. // GPT-5.5 同时作为 GPT-5 系列的 fallback(覆盖 5.3 / 5.4 等未单独维护 prompt 的版本)。
  56. //
  57. //go:embed instructions_gpt5_1.txt
  58. var instructionsGPT51 string
  59. //go:embed instructions_gpt5_2.txt
  60. var instructionsGPT52 string
  61. //go:embed instructions_gpt5_5.txt
  62. var instructionsGPT55 string
  63. // Source: openai/codex codex-rs/models-manager/models.json at 121f91fd5d9d.
  64. //
  65. //go:embed instructions_gpt6_astra.txt
  66. var instructionsGPT6Astra string
  67. // latestCodexInstructions 返回当前已知最新版本的 Codex base instructions,
  68. // 当前为 GPT-5.5;若 5.5 prompt 意外为空则回退到 DefaultInstructions 保证非空。
  69. func latestCodexInstructions() string {
  70. if v := strings.TrimSpace(instructionsGPT55); v != "" {
  71. return instructionsGPT55
  72. }
  73. return DefaultInstructions
  74. }
  75. // CanonicalizeOpenAIModelAliasSpelling normalizes provider prefixes, case,
  76. // separators, and known compact spellings used by OpenAI model aliases.
  77. func CanonicalizeOpenAIModelAliasSpelling(model string) string {
  78. model = strings.TrimSpace(model)
  79. if slash := strings.LastIndexByte(model, '/'); slash >= 0 {
  80. model = strings.TrimSpace(model[slash+1:])
  81. }
  82. model = strings.ToLower(model)
  83. if model == "" {
  84. return ""
  85. }
  86. normalized := strings.ReplaceAll(model, "_", "-")
  87. normalized = strings.Join(strings.Fields(normalized), "-")
  88. for strings.Contains(normalized, "--") {
  89. normalized = strings.ReplaceAll(normalized, "--", "-")
  90. }
  91. if strings.HasPrefix(normalized, "gpt5") {
  92. normalized = "gpt-5" + strings.TrimPrefix(normalized, "gpt5")
  93. }
  94. if !strings.HasPrefix(normalized, "gpt-") && !strings.Contains(normalized, "codex") {
  95. return ""
  96. }
  97. replacements := []struct {
  98. from string
  99. to string
  100. }{
  101. {"gpt-5.4mini", "gpt-5.4-mini"},
  102. {"gpt-5.4nano", "gpt-5.4-nano"},
  103. {"gpt-5.3-codexspark", "gpt-5.3-codex-spark"},
  104. {"gpt-5.3codexspark", "gpt-5.3-codex-spark"},
  105. {"gpt-5.3codex", "gpt-5.3-codex"},
  106. }
  107. for _, replacement := range replacements {
  108. normalized = strings.ReplaceAll(normalized, replacement.from, replacement.to)
  109. }
  110. return normalized
  111. }
  112. // CodexBaseInstructionsForModel 按模型返回最匹配的真实 Codex base instructions:
  113. // - gpt-6 / gpt-6-astra(含供应商前缀与日期变体)→ GPT-6 Astra prompt
  114. // - 含 "codex" 的模型(gpt-5-codex / gpt-5.x-codex / codex-max / spark 等)→ GPT-5-Codex prompt
  115. // - gpt-5.5 系非 codex 模型 → GPT-5.5 prompt
  116. // - gpt-5.2 系非 codex 模型 → GPT-5.2 prompt
  117. // - gpt-5.1 系非 codex 模型 → GPT-5.1 prompt
  118. // - 其它(含 gpt-5.3 / gpt-5.4 / 裸 gpt-5 / 未知模型)→ 回退到最新版本(当前 GPT-5.5)
  119. //
  120. // 任一专用 prompt 意外为空时回退链最终落到 DefaultInstructions,保证返回非空。
  121. func CodexBaseInstructionsForModel(model string) string {
  122. canonical := CanonicalizeOpenAIModelAliasSpelling(model)
  123. switch {
  124. case canonical == "gpt-6" || canonical == "gpt-6-astra" || strings.HasPrefix(canonical, "gpt-6-astra-"):
  125. if v := strings.TrimSpace(instructionsGPT6Astra); v != "" {
  126. return instructionsGPT6Astra
  127. }
  128. case strings.Contains(canonical, "codex"):
  129. return DefaultInstructions
  130. case strings.HasPrefix(canonical, "gpt-5.5"):
  131. return latestCodexInstructions()
  132. case strings.HasPrefix(canonical, "gpt-5.2"):
  133. if v := strings.TrimSpace(instructionsGPT52); v != "" {
  134. return instructionsGPT52
  135. }
  136. case strings.HasPrefix(canonical, "gpt-5.1"):
  137. if v := strings.TrimSpace(instructionsGPT51); v != "" {
  138. return instructionsGPT51
  139. }
  140. }
  141. return latestCodexInstructions()
  142. }