mirror of
https://github.com/sipeed/picoclaw.git
synced 2026-06-12 18:08:54 +00:00
fix(auth): preserve model_list and use gpt-5.2 for Codex API
Auth fixes: - Fix OpenAI/Anthropic OAuth and token login to update ModelList - Fix logout to clear AuthMethod in ModelList - Add helper functions: isOpenAIModel, isAnthropicModel, isAntigravityModel - Fix slice bounds panic in isAntigravityModel using strings.HasPrefix - All auth operations now preserve existing model_list configuration Factory provider fixes: - Add OAuth support for openai protocol in CreateProviderFromConfig - CodexAuthProvider is now used when auth_method is oauth/token Default model updates: - OpenAI login: set default model to gpt-5.2 - Anthropic login: set default model to claude-sonnet-4 - Antigravity login: set default model to gemini-flash (remove provider field) Model changes: - Change default OpenAI model from gpt-4o to gpt-5.2 - gpt-5.2 is compatible with Codex API (chatgpt.com backend) - Update all README files, config examples, and migration code Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
+9
-9
@@ -833,8 +833,8 @@ Cette conception permet également le **support multi-agent** avec une sélectio
|
||||
{
|
||||
"model_list": [
|
||||
{
|
||||
"model_name": "gpt-4o",
|
||||
"model": "openai/gpt-4o",
|
||||
"model_name": "gpt-5.2",
|
||||
"model": "openai/gpt-5.2",
|
||||
"api_key": "sk-your-openai-key"
|
||||
},
|
||||
{
|
||||
@@ -850,7 +850,7 @@ Cette conception permet également le **support multi-agent** avec une sélectio
|
||||
],
|
||||
"agents": {
|
||||
"defaults": {
|
||||
"model": "gpt-4o"
|
||||
"model": "gpt-5.2"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -861,8 +861,8 @@ Cette conception permet également le **support multi-agent** avec une sélectio
|
||||
**OpenAI**
|
||||
```json
|
||||
{
|
||||
"model_name": "gpt-4o",
|
||||
"model": "openai/gpt-4o",
|
||||
"model_name": "gpt-5.2",
|
||||
"model": "openai/gpt-5.2",
|
||||
"api_key": "sk-..."
|
||||
}
|
||||
```
|
||||
@@ -894,14 +894,14 @@ Configurez plusieurs points de terminaison pour le même nom de modèle—PicoCl
|
||||
{
|
||||
"model_list": [
|
||||
{
|
||||
"model_name": "gpt-4o",
|
||||
"model": "openai/gpt-4o",
|
||||
"model_name": "gpt-5.2",
|
||||
"model": "openai/gpt-5.2",
|
||||
"api_base": "https://api1.example.com/v1",
|
||||
"api_key": "sk-key1"
|
||||
},
|
||||
{
|
||||
"model_name": "gpt-4o",
|
||||
"model": "openai/gpt-4o",
|
||||
"model_name": "gpt-5.2",
|
||||
"model": "openai/gpt-5.2",
|
||||
"api_base": "https://api2.example.com/v1",
|
||||
"api_key": "sk-key2"
|
||||
}
|
||||
|
||||
+9
-9
@@ -769,8 +769,8 @@ HEARTBEAT_OK 応答 ユーザーが直接結果を受け取る
|
||||
{
|
||||
"model_list": [
|
||||
{
|
||||
"model_name": "gpt-4o",
|
||||
"model": "openai/gpt-4o",
|
||||
"model_name": "gpt-5.2",
|
||||
"model": "openai/gpt-5.2",
|
||||
"api_key": "sk-your-openai-key"
|
||||
},
|
||||
{
|
||||
@@ -786,7 +786,7 @@ HEARTBEAT_OK 応答 ユーザーが直接結果を受け取る
|
||||
],
|
||||
"agents": {
|
||||
"defaults": {
|
||||
"model": "gpt-4o"
|
||||
"model": "gpt-5.2"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -797,8 +797,8 @@ HEARTBEAT_OK 応答 ユーザーが直接結果を受け取る
|
||||
**OpenAI**
|
||||
```json
|
||||
{
|
||||
"model_name": "gpt-4o",
|
||||
"model": "openai/gpt-4o",
|
||||
"model_name": "gpt-5.2",
|
||||
"model": "openai/gpt-5.2",
|
||||
"api_key": "sk-..."
|
||||
}
|
||||
```
|
||||
@@ -830,14 +830,14 @@ HEARTBEAT_OK 応答 ユーザーが直接結果を受け取る
|
||||
{
|
||||
"model_list": [
|
||||
{
|
||||
"model_name": "gpt-4o",
|
||||
"model": "openai/gpt-4o",
|
||||
"model_name": "gpt-5.2",
|
||||
"model": "openai/gpt-5.2",
|
||||
"api_base": "https://api1.example.com/v1",
|
||||
"api_key": "sk-key1"
|
||||
},
|
||||
{
|
||||
"model_name": "gpt-4o",
|
||||
"model": "openai/gpt-4o",
|
||||
"model_name": "gpt-5.2",
|
||||
"model": "openai/gpt-5.2",
|
||||
"api_base": "https://api2.example.com/v1",
|
||||
"api_key": "sk-key2"
|
||||
}
|
||||
|
||||
@@ -218,7 +218,7 @@ picoclaw onboard
|
||||
"model_list": [
|
||||
{
|
||||
"model_name": "gpt4",
|
||||
"model": "openai/gpt-4o",
|
||||
"model": "openai/gpt-5.2",
|
||||
"api_key": "your-api-key"
|
||||
},
|
||||
{
|
||||
@@ -728,8 +728,8 @@ This design also enables **multi-agent support** with flexible provider selectio
|
||||
{
|
||||
"model_list": [
|
||||
{
|
||||
"model_name": "gpt-4o",
|
||||
"model": "openai/gpt-4o",
|
||||
"model_name": "gpt-5.2",
|
||||
"model": "openai/gpt-5.2",
|
||||
"api_key": "sk-your-openai-key"
|
||||
},
|
||||
{
|
||||
@@ -745,7 +745,7 @@ This design also enables **multi-agent support** with flexible provider selectio
|
||||
],
|
||||
"agents": {
|
||||
"defaults": {
|
||||
"model": "gpt-4o"
|
||||
"model": "gpt-5.2"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -756,8 +756,8 @@ This design also enables **multi-agent support** with flexible provider selectio
|
||||
**OpenAI**
|
||||
```json
|
||||
{
|
||||
"model_name": "gpt-4o",
|
||||
"model": "openai/gpt-4o",
|
||||
"model_name": "gpt-5.2",
|
||||
"model": "openai/gpt-5.2",
|
||||
"api_key": "sk-..."
|
||||
}
|
||||
```
|
||||
@@ -816,14 +816,14 @@ Configure multiple endpoints for the same model name—PicoClaw will automatical
|
||||
{
|
||||
"model_list": [
|
||||
{
|
||||
"model_name": "gpt-4o",
|
||||
"model": "openai/gpt-4o",
|
||||
"model_name": "gpt-5.2",
|
||||
"model": "openai/gpt-5.2",
|
||||
"api_base": "https://api1.example.com/v1",
|
||||
"api_key": "sk-key1"
|
||||
},
|
||||
{
|
||||
"model_name": "gpt-4o",
|
||||
"model": "openai/gpt-4o",
|
||||
"model_name": "gpt-5.2",
|
||||
"model": "openai/gpt-5.2",
|
||||
"api_base": "https://api2.example.com/v1",
|
||||
"api_key": "sk-key2"
|
||||
}
|
||||
|
||||
+9
-9
@@ -834,8 +834,8 @@ Este design também possibilita o **suporte multi-agent** com seleção flexíve
|
||||
{
|
||||
"model_list": [
|
||||
{
|
||||
"model_name": "gpt-4o",
|
||||
"model": "openai/gpt-4o",
|
||||
"model_name": "gpt-5.2",
|
||||
"model": "openai/gpt-5.2",
|
||||
"api_key": "sk-your-openai-key"
|
||||
},
|
||||
{
|
||||
@@ -851,7 +851,7 @@ Este design também possibilita o **suporte multi-agent** com seleção flexíve
|
||||
],
|
||||
"agents": {
|
||||
"defaults": {
|
||||
"model": "gpt-4o"
|
||||
"model": "gpt-5.2"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -862,8 +862,8 @@ Este design também possibilita o **suporte multi-agent** com seleção flexíve
|
||||
**OpenAI**
|
||||
```json
|
||||
{
|
||||
"model_name": "gpt-4o",
|
||||
"model": "openai/gpt-4o",
|
||||
"model_name": "gpt-5.2",
|
||||
"model": "openai/gpt-5.2",
|
||||
"api_key": "sk-..."
|
||||
}
|
||||
```
|
||||
@@ -895,14 +895,14 @@ Configure vários endpoints para o mesmo nome de modelo—PicoClaw fará round-r
|
||||
{
|
||||
"model_list": [
|
||||
{
|
||||
"model_name": "gpt-4o",
|
||||
"model": "openai/gpt-4o",
|
||||
"model_name": "gpt-5.2",
|
||||
"model": "openai/gpt-5.2",
|
||||
"api_base": "https://api1.example.com/v1",
|
||||
"api_key": "sk-key1"
|
||||
},
|
||||
{
|
||||
"model_name": "gpt-4o",
|
||||
"model": "openai/gpt-4o",
|
||||
"model_name": "gpt-5.2",
|
||||
"model": "openai/gpt-5.2",
|
||||
"api_base": "https://api2.example.com/v1",
|
||||
"api_key": "sk-key2"
|
||||
}
|
||||
|
||||
+9
-9
@@ -811,8 +811,8 @@ Thiết kế này cũng cho phép **hỗ trợ đa tác nhân** với lựa ch
|
||||
{
|
||||
"model_list": [
|
||||
{
|
||||
"model_name": "gpt-4o",
|
||||
"model": "openai/gpt-4o",
|
||||
"model_name": "gpt-5.2",
|
||||
"model": "openai/gpt-5.2",
|
||||
"api_key": "sk-your-openai-key"
|
||||
},
|
||||
{
|
||||
@@ -828,7 +828,7 @@ Thiết kế này cũng cho phép **hỗ trợ đa tác nhân** với lựa ch
|
||||
],
|
||||
"agents": {
|
||||
"defaults": {
|
||||
"model": "gpt-4o"
|
||||
"model": "gpt-5.2"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -839,8 +839,8 @@ Thiết kế này cũng cho phép **hỗ trợ đa tác nhân** với lựa ch
|
||||
**OpenAI**
|
||||
```json
|
||||
{
|
||||
"model_name": "gpt-4o",
|
||||
"model": "openai/gpt-4o",
|
||||
"model_name": "gpt-5.2",
|
||||
"model": "openai/gpt-5.2",
|
||||
"api_key": "sk-..."
|
||||
}
|
||||
```
|
||||
@@ -872,14 +872,14 @@ Thiết kế này cũng cho phép **hỗ trợ đa tác nhân** với lựa ch
|
||||
{
|
||||
"model_list": [
|
||||
{
|
||||
"model_name": "gpt-4o",
|
||||
"model": "openai/gpt-4o",
|
||||
"model_name": "gpt-5.2",
|
||||
"model": "openai/gpt-5.2",
|
||||
"api_base": "https://api1.example.com/v1",
|
||||
"api_key": "sk-key1"
|
||||
},
|
||||
{
|
||||
"model_name": "gpt-4o",
|
||||
"model": "openai/gpt-4o",
|
||||
"model_name": "gpt-5.2",
|
||||
"model": "openai/gpt-5.2",
|
||||
"api_base": "https://api2.example.com/v1",
|
||||
"api_key": "sk-key2"
|
||||
}
|
||||
|
||||
+10
-10
@@ -227,7 +227,7 @@ picoclaw onboard
|
||||
"model_list": [
|
||||
{
|
||||
"model_name": "gpt4",
|
||||
"model": "openai/gpt-4o",
|
||||
"model": "openai/gpt-5.2",
|
||||
"api_key": "your-api-key"
|
||||
},
|
||||
{
|
||||
@@ -605,8 +605,8 @@ Agent 读取 HEARTBEAT.md
|
||||
{
|
||||
"model_list": [
|
||||
{
|
||||
"model_name": "gpt-4o",
|
||||
"model": "openai/gpt-4o",
|
||||
"model_name": "gpt-5.2",
|
||||
"model": "openai/gpt-5.2",
|
||||
"api_key": "sk-your-openai-key"
|
||||
},
|
||||
{
|
||||
@@ -622,7 +622,7 @@ Agent 读取 HEARTBEAT.md
|
||||
],
|
||||
"agents": {
|
||||
"defaults": {
|
||||
"model": "gpt-4o"
|
||||
"model": "gpt-5.2"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -633,8 +633,8 @@ Agent 读取 HEARTBEAT.md
|
||||
**OpenAI**
|
||||
```json
|
||||
{
|
||||
"model_name": "gpt-4o",
|
||||
"model": "openai/gpt-4o",
|
||||
"model_name": "gpt-5.2",
|
||||
"model": "openai/gpt-5.2",
|
||||
"api_key": "sk-..."
|
||||
}
|
||||
```
|
||||
@@ -693,14 +693,14 @@ Agent 读取 HEARTBEAT.md
|
||||
{
|
||||
"model_list": [
|
||||
{
|
||||
"model_name": "gpt-4o",
|
||||
"model": "openai/gpt-4o",
|
||||
"model_name": "gpt-5.2",
|
||||
"model": "openai/gpt-5.2",
|
||||
"api_base": "https://api1.example.com/v1",
|
||||
"api_key": "sk-key1"
|
||||
},
|
||||
{
|
||||
"model_name": "gpt-4o",
|
||||
"model": "openai/gpt-4o",
|
||||
"model_name": "gpt-5.2",
|
||||
"model": "openai/gpt-5.2",
|
||||
"api_base": "https://api2.example.com/v1",
|
||||
"api_key": "sk-key2"
|
||||
}
|
||||
|
||||
+129
-5
@@ -9,6 +9,7 @@ import (
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/sipeed/picoclaw/pkg/auth"
|
||||
@@ -118,7 +119,31 @@ func authLoginOpenAI(useDeviceCode bool) {
|
||||
|
||||
appCfg, err := loadConfig()
|
||||
if err == nil {
|
||||
// Update Providers (legacy format)
|
||||
appCfg.Providers.OpenAI.AuthMethod = "oauth"
|
||||
|
||||
// Update or add openai in ModelList
|
||||
foundOpenAI := false
|
||||
for i := range appCfg.ModelList {
|
||||
if isOpenAIModel(appCfg.ModelList[i].Model) {
|
||||
appCfg.ModelList[i].AuthMethod = "oauth"
|
||||
foundOpenAI = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// If no openai in ModelList, add it
|
||||
if !foundOpenAI {
|
||||
appCfg.ModelList = append(appCfg.ModelList, config.ModelConfig{
|
||||
ModelName: "gpt-5.2",
|
||||
Model: "openai/gpt-5.2",
|
||||
AuthMethod: "oauth",
|
||||
})
|
||||
}
|
||||
|
||||
// Update default model to use OpenAI
|
||||
appCfg.Agents.Defaults.Model = "gpt-5.2"
|
||||
|
||||
if err := config.SaveConfig(getConfigPath(), appCfg); err != nil {
|
||||
fmt.Printf("Warning: could not update config: %v\n", err)
|
||||
}
|
||||
@@ -128,6 +153,7 @@ func authLoginOpenAI(useDeviceCode bool) {
|
||||
if cred.AccountID != "" {
|
||||
fmt.Printf("Account: %s\n", cred.AccountID)
|
||||
}
|
||||
fmt.Println("Default model set to: gpt-5.2")
|
||||
}
|
||||
|
||||
func authLoginGoogleAntigravity() {
|
||||
@@ -167,20 +193,38 @@ func authLoginGoogleAntigravity() {
|
||||
|
||||
appCfg, err := loadConfig()
|
||||
if err == nil {
|
||||
// Update Providers (legacy format, for backward compatibility)
|
||||
appCfg.Providers.Antigravity.AuthMethod = "oauth"
|
||||
if appCfg.Agents.Defaults.Provider == "" {
|
||||
appCfg.Agents.Defaults.Provider = "antigravity"
|
||||
|
||||
// Update or add antigravity in ModelList
|
||||
foundAntigravity := false
|
||||
for i := range appCfg.ModelList {
|
||||
if isAntigravityModel(appCfg.ModelList[i].Model) {
|
||||
appCfg.ModelList[i].AuthMethod = "oauth"
|
||||
foundAntigravity = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if appCfg.Agents.Defaults.Provider == "antigravity" || appCfg.Agents.Defaults.Provider == "google-antigravity" {
|
||||
appCfg.Agents.Defaults.Model = "gemini-3-flash"
|
||||
|
||||
// If no antigravity in ModelList, add it
|
||||
if !foundAntigravity {
|
||||
appCfg.ModelList = append(appCfg.ModelList, config.ModelConfig{
|
||||
ModelName: "gemini-flash",
|
||||
Model: "antigravity/gemini-3-flash",
|
||||
AuthMethod: "oauth",
|
||||
})
|
||||
}
|
||||
|
||||
// Update default model
|
||||
appCfg.Agents.Defaults.Model = "gemini-flash"
|
||||
|
||||
if err := config.SaveConfig(getConfigPath(), appCfg); err != nil {
|
||||
fmt.Printf("Warning: could not update config: %v\n", err)
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Println("\n✓ Google Antigravity login successful!")
|
||||
fmt.Println("Config updated: provider=antigravity, model=gemini-3-flash")
|
||||
fmt.Println("Default model set to: gemini-flash")
|
||||
fmt.Println("Try it: picoclaw agent -m \"Hello world\"")
|
||||
}
|
||||
|
||||
@@ -229,8 +273,44 @@ func authLoginPasteToken(provider string) {
|
||||
switch provider {
|
||||
case "anthropic":
|
||||
appCfg.Providers.Anthropic.AuthMethod = "token"
|
||||
// Update ModelList
|
||||
found := false
|
||||
for i := range appCfg.ModelList {
|
||||
if isAnthropicModel(appCfg.ModelList[i].Model) {
|
||||
appCfg.ModelList[i].AuthMethod = "token"
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
appCfg.ModelList = append(appCfg.ModelList, config.ModelConfig{
|
||||
ModelName: "claude-sonnet-4",
|
||||
Model: "anthropic/claude-sonnet-4-20250514",
|
||||
AuthMethod: "token",
|
||||
})
|
||||
}
|
||||
// Update default model
|
||||
appCfg.Agents.Defaults.Model = "claude-sonnet-4"
|
||||
case "openai":
|
||||
appCfg.Providers.OpenAI.AuthMethod = "token"
|
||||
// Update ModelList
|
||||
found := false
|
||||
for i := range appCfg.ModelList {
|
||||
if isOpenAIModel(appCfg.ModelList[i].Model) {
|
||||
appCfg.ModelList[i].AuthMethod = "token"
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
appCfg.ModelList = append(appCfg.ModelList, config.ModelConfig{
|
||||
ModelName: "gpt-5.2",
|
||||
Model: "openai/gpt-5.2",
|
||||
AuthMethod: "token",
|
||||
})
|
||||
}
|
||||
// Update default model
|
||||
appCfg.Agents.Defaults.Model = "gpt-5.2"
|
||||
}
|
||||
if err := config.SaveConfig(getConfigPath(), appCfg); err != nil {
|
||||
fmt.Printf("Warning: could not update config: %v\n", err)
|
||||
@@ -238,6 +318,7 @@ func authLoginPasteToken(provider string) {
|
||||
}
|
||||
|
||||
fmt.Printf("Token saved for %s!\n", provider)
|
||||
fmt.Printf("Default model set to: %s\n", appCfg.Agents.Defaults.Model)
|
||||
}
|
||||
|
||||
func authLogoutCmd() {
|
||||
@@ -262,6 +343,24 @@ func authLogoutCmd() {
|
||||
|
||||
appCfg, err := loadConfig()
|
||||
if err == nil {
|
||||
// Clear AuthMethod in ModelList
|
||||
for i := range appCfg.ModelList {
|
||||
switch provider {
|
||||
case "openai":
|
||||
if isOpenAIModel(appCfg.ModelList[i].Model) {
|
||||
appCfg.ModelList[i].AuthMethod = ""
|
||||
}
|
||||
case "anthropic":
|
||||
if isAnthropicModel(appCfg.ModelList[i].Model) {
|
||||
appCfg.ModelList[i].AuthMethod = ""
|
||||
}
|
||||
case "google-antigravity", "antigravity":
|
||||
if isAntigravityModel(appCfg.ModelList[i].Model) {
|
||||
appCfg.ModelList[i].AuthMethod = ""
|
||||
}
|
||||
}
|
||||
}
|
||||
// Clear AuthMethod in Providers (legacy)
|
||||
switch provider {
|
||||
case "openai":
|
||||
appCfg.Providers.OpenAI.AuthMethod = ""
|
||||
@@ -282,6 +381,11 @@ func authLogoutCmd() {
|
||||
|
||||
appCfg, err := loadConfig()
|
||||
if err == nil {
|
||||
// Clear all AuthMethods in ModelList
|
||||
for i := range appCfg.ModelList {
|
||||
appCfg.ModelList[i].AuthMethod = ""
|
||||
}
|
||||
// Clear all AuthMethods in Providers (legacy)
|
||||
appCfg.Providers.OpenAI.AuthMethod = ""
|
||||
appCfg.Providers.Anthropic.AuthMethod = ""
|
||||
appCfg.Providers.Antigravity.AuthMethod = ""
|
||||
@@ -384,3 +488,23 @@ func authModelsCmd() {
|
||||
fmt.Printf(" %s %s\n", status, name)
|
||||
}
|
||||
}
|
||||
|
||||
// isAntigravityModel checks if a model string belongs to antigravity provider
|
||||
func isAntigravityModel(model string) bool {
|
||||
return model == "antigravity" ||
|
||||
model == "google-antigravity" ||
|
||||
strings.HasPrefix(model, "antigravity/") ||
|
||||
strings.HasPrefix(model, "google-antigravity/")
|
||||
}
|
||||
|
||||
// isOpenAIModel checks if a model string belongs to openai provider
|
||||
func isOpenAIModel(model string) bool {
|
||||
return model == "openai" ||
|
||||
strings.HasPrefix(model, "openai/")
|
||||
}
|
||||
|
||||
// isAnthropicModel checks if a model string belongs to anthropic provider
|
||||
func isAnthropicModel(model string) bool {
|
||||
return model == "anthropic" ||
|
||||
strings.HasPrefix(model, "anthropic/")
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
"model_list": [
|
||||
{
|
||||
"model_name": "gpt4",
|
||||
"model": "openai/gpt-4o",
|
||||
"model": "openai/gpt-5.2",
|
||||
"api_key": "sk-your-openai-key",
|
||||
"api_base": "https://api.openai.com/v1"
|
||||
},
|
||||
@@ -34,13 +34,13 @@
|
||||
},
|
||||
{
|
||||
"model_name": "loadbalanced-gpt4",
|
||||
"model": "openai/gpt-4o",
|
||||
"model": "openai/gpt-5.2",
|
||||
"api_key": "sk-key1",
|
||||
"api_base": "https://api1.example.com/v1"
|
||||
},
|
||||
{
|
||||
"model_name": "loadbalanced-gpt4",
|
||||
"model": "openai/gpt-4o",
|
||||
"model": "openai/gpt-5.2",
|
||||
"api_key": "sk-key2",
|
||||
"api_base": "https://api2.example.com/v1"
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@ Problem: Agent needs to know both `provider` and `model`, adding complexity.
|
||||
Inspired by [LiteLLM](https://docs.litellm.ai/docs/proxy/configs) design:
|
||||
|
||||
1. **Model-centric**: Users care about models, not providers
|
||||
2. **Protocol prefix**: Use `protocol/model_name` format, e.g., `openai/gpt-4o`, `anthropic/claude-3-sonnet`
|
||||
2. **Protocol prefix**: Use `protocol/model_name` format, e.g., `openai/gpt-5.2`, `anthropic/claude-3-sonnet`
|
||||
3. **Configuration-driven**: Adding new Providers only requires config changes, no code changes
|
||||
|
||||
### 2.2 New Configuration Structure
|
||||
@@ -81,8 +81,8 @@ Inspired by [LiteLLM](https://docs.litellm.ai/docs/proxy/configs) design:
|
||||
"api_key": "sk-xxx"
|
||||
},
|
||||
{
|
||||
"model_name": "gpt-4o",
|
||||
"model": "openai/gpt-4o",
|
||||
"model_name": "gpt-5.2",
|
||||
"model": "openai/gpt-5.2",
|
||||
"api_key": "sk-xxx"
|
||||
},
|
||||
{
|
||||
@@ -128,7 +128,7 @@ type Config struct {
|
||||
type ModelConfig struct {
|
||||
// Required
|
||||
ModelName string `json:"model_name"` // user-facing name (alias)
|
||||
Model string `json:"model"` // protocol/model, e.g., openai/gpt-4o
|
||||
Model string `json:"model"` // protocol/model, e.g., openai/gpt-5.2
|
||||
|
||||
// Common config
|
||||
APIBase string `json:"api_base,omitempty"`
|
||||
@@ -180,7 +180,7 @@ Identify protocol via prefix in `model` field:
|
||||
"model": "deepseek-chat"
|
||||
},
|
||||
"coder": {
|
||||
"model": "gpt-4o",
|
||||
"model": "gpt-5.2",
|
||||
"system_prompt": "You are a coding assistant..."
|
||||
},
|
||||
"translator": {
|
||||
@@ -200,7 +200,7 @@ Each Agent only needs to specify `model` (corresponds to `model_name` in `model_
|
||||
model_list:
|
||||
- model_name: gpt-4o
|
||||
litellm_params:
|
||||
model: openai/gpt-4o
|
||||
model: openai/gpt-5.2
|
||||
api_key: xxx
|
||||
- model_name: my-custom
|
||||
litellm_params:
|
||||
|
||||
@@ -40,7 +40,7 @@ The new `model_list` configuration offers several advantages:
|
||||
"agents": {
|
||||
"defaults": {
|
||||
"provider": "openai",
|
||||
"model": "gpt-4o"
|
||||
"model": "gpt-5.2"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -53,7 +53,7 @@ The new `model_list` configuration offers several advantages:
|
||||
"model_list": [
|
||||
{
|
||||
"model_name": "gpt4",
|
||||
"model": "openai/gpt-4o",
|
||||
"model": "openai/gpt-5.2",
|
||||
"api_key": "sk-your-openai-key",
|
||||
"api_base": "https://api.openai.com/v1"
|
||||
},
|
||||
@@ -82,7 +82,7 @@ The `model` field uses a protocol prefix format: `[protocol/]model-identifier`
|
||||
|
||||
| Prefix | Description | Example |
|
||||
|--------|-------------|---------|
|
||||
| `openai/` | OpenAI API (default) | `openai/gpt-4o` |
|
||||
| `openai/` | OpenAI API (default) | `openai/gpt-5.2` |
|
||||
| `anthropic/` | Anthropic API | `anthropic/claude-3-opus` |
|
||||
| `antigravity/` | Google via Antigravity OAuth | `antigravity/gemini-2.0-flash` |
|
||||
| `claude-cli/` | Claude CLI (local) | `claude-cli/claude-3-sonnet` |
|
||||
@@ -101,7 +101,7 @@ The `model` field uses a protocol prefix format: `[protocol/]model-identifier`
|
||||
| Field | Required | Description |
|
||||
|-------|----------|-------------|
|
||||
| `model_name` | Yes | User-facing alias for the model |
|
||||
| `model` | Yes | Protocol and model identifier (e.g., `openai/gpt-4o`) |
|
||||
| `model` | Yes | Protocol and model identifier (e.g., `openai/gpt-5.2`) |
|
||||
| `api_base` | No | API endpoint URL |
|
||||
| `api_key` | No* | API authentication key |
|
||||
| `proxy` | No | HTTP proxy URL |
|
||||
@@ -121,19 +121,19 @@ Configure multiple endpoints for the same model to distribute load:
|
||||
"model_list": [
|
||||
{
|
||||
"model_name": "gpt4",
|
||||
"model": "openai/gpt-4o",
|
||||
"model": "openai/gpt-5.2",
|
||||
"api_key": "sk-key1",
|
||||
"api_base": "https://api1.example.com/v1"
|
||||
},
|
||||
{
|
||||
"model_name": "gpt4",
|
||||
"model": "openai/gpt-4o",
|
||||
"model": "openai/gpt-5.2",
|
||||
"api_key": "sk-key2",
|
||||
"api_base": "https://api2.example.com/v1"
|
||||
},
|
||||
{
|
||||
"model_name": "gpt4",
|
||||
"model": "openai/gpt-4o",
|
||||
"model": "openai/gpt-5.2",
|
||||
"api_key": "sk-key3",
|
||||
"api_base": "https://api3.example.com/v1"
|
||||
}
|
||||
|
||||
@@ -105,8 +105,8 @@ func DefaultConfig() *Config {
|
||||
|
||||
// OpenAI - https://platform.openai.com/api-keys
|
||||
{
|
||||
ModelName: "gpt-4o",
|
||||
Model: "openai/gpt-4o",
|
||||
ModelName: "gpt-5.2",
|
||||
Model: "openai/gpt-5.2",
|
||||
APIBase: "https://api.openai.com/v1",
|
||||
APIKey: "",
|
||||
},
|
||||
@@ -161,8 +161,8 @@ func DefaultConfig() *Config {
|
||||
|
||||
// OpenRouter (100+ models) - https://openrouter.ai/keys
|
||||
{
|
||||
ModelName: "openrouter-gpt-4o",
|
||||
Model: "openrouter/openai/gpt-4o",
|
||||
ModelName: "openrouter-gpt-5.2",
|
||||
Model: "openrouter/openai/gpt-5.2",
|
||||
APIBase: "https://openrouter.ai/api/v1",
|
||||
APIKey: "",
|
||||
},
|
||||
@@ -208,8 +208,8 @@ func DefaultConfig() *Config {
|
||||
|
||||
// GitHub Copilot - https://github.com/settings/tokens
|
||||
{
|
||||
ModelName: "copilot-gpt-4o",
|
||||
Model: "github-copilot/gpt-4o",
|
||||
ModelName: "copilot-gpt-5.2",
|
||||
Model: "github-copilot/gpt-5.2",
|
||||
APIBase: "http://localhost:4321",
|
||||
AuthMethod: "oauth",
|
||||
},
|
||||
|
||||
@@ -50,7 +50,7 @@ func ConvertProvidersToModelList(cfg *Config) []ModelConfig {
|
||||
}
|
||||
return ModelConfig{
|
||||
ModelName: "openai",
|
||||
Model: "openai/gpt-4o",
|
||||
Model: "openai/gpt-5.2",
|
||||
APIKey: p.OpenAI.APIKey,
|
||||
APIBase: p.OpenAI.APIBase,
|
||||
Proxy: p.OpenAI.Proxy,
|
||||
@@ -276,7 +276,7 @@ func ConvertProvidersToModelList(cfg *Config) []ModelConfig {
|
||||
}
|
||||
return ModelConfig{
|
||||
ModelName: "github-copilot",
|
||||
Model: "github-copilot/gpt-4o",
|
||||
Model: "github-copilot/gpt-5.2",
|
||||
APIBase: p.GitHubCopilot.APIBase,
|
||||
ConnectMode: p.GitHubCopilot.ConnectMode,
|
||||
}, true
|
||||
|
||||
@@ -31,8 +31,8 @@ func TestConvertProvidersToModelList_OpenAI(t *testing.T) {
|
||||
if result[0].ModelName != "openai" {
|
||||
t.Errorf("ModelName = %q, want %q", result[0].ModelName, "openai")
|
||||
}
|
||||
if result[0].Model != "openai/gpt-4o" {
|
||||
t.Errorf("Model = %q, want %q", result[0].Model, "openai/gpt-4o")
|
||||
if result[0].Model != "openai/gpt-5.2" {
|
||||
t.Errorf("Model = %q, want %q", result[0].Model, "openai/gpt-5.2")
|
||||
}
|
||||
if result[0].APIKey != "sk-test-key" {
|
||||
t.Errorf("APIKey = %q, want %q", result[0].APIKey, "sk-test-key")
|
||||
@@ -331,8 +331,8 @@ func TestConvertProvidersToModelList_MultipleProviders_PreservesUserModel(t *tes
|
||||
for _, mc := range result {
|
||||
switch mc.ModelName {
|
||||
case "openai":
|
||||
if mc.Model != "openai/gpt-4o" {
|
||||
t.Errorf("OpenAI Model = %q, want %q (default)", mc.Model, "openai/gpt-4o")
|
||||
if mc.Model != "openai/gpt-5.2" {
|
||||
t.Errorf("OpenAI Model = %q, want %q (default)", mc.Model, "openai/gpt-5.2")
|
||||
}
|
||||
case "deepseek":
|
||||
if mc.Model != "deepseek/deepseek-reasoner" {
|
||||
|
||||
@@ -67,10 +67,29 @@ func CreateProviderFromConfig(cfg *config.ModelConfig) (LLMProvider, string, err
|
||||
protocol, modelID := ExtractProtocol(cfg.Model)
|
||||
|
||||
switch protocol {
|
||||
case "openai", "openrouter", "groq", "zhipu", "gemini", "nvidia",
|
||||
case "openai":
|
||||
// OpenAI with OAuth/token auth (Codex-style)
|
||||
if cfg.AuthMethod == "oauth" || cfg.AuthMethod == "token" {
|
||||
provider, err := createCodexAuthProvider()
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
return provider, modelID, nil
|
||||
}
|
||||
// OpenAI with API key
|
||||
if cfg.APIKey == "" && cfg.APIBase == "" {
|
||||
return nil, "", fmt.Errorf("api_key or api_base is required for HTTP-based protocol %q", protocol)
|
||||
}
|
||||
apiBase := cfg.APIBase
|
||||
if apiBase == "" {
|
||||
apiBase = getDefaultAPIBase(protocol)
|
||||
}
|
||||
return NewHTTPProviderWithMaxTokensField(cfg.APIKey, apiBase, cfg.Proxy, cfg.MaxTokensField), modelID, nil
|
||||
|
||||
case "openrouter", "groq", "zhipu", "gemini", "nvidia",
|
||||
"ollama", "moonshot", "shengsuanyun", "deepseek", "cerebras",
|
||||
"volcengine", "vllm", "qwen":
|
||||
// All OpenAI-compatible HTTP providers
|
||||
// All other OpenAI-compatible HTTP providers
|
||||
if cfg.APIKey == "" && cfg.APIBase == "" {
|
||||
return nil, "", fmt.Errorf("api_key or api_base is required for HTTP-based protocol %q", protocol)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user