From 1e024321c06b78e1b77e05229a7f63ab741ad8ab Mon Sep 17 00:00:00 2001 From: Guoguo <16666742+imguoguo@users.noreply.github.com> Date: Thu, 12 Mar 2026 16:10:29 +0800 Subject: [PATCH] refactor: update model name and add VolcEngine coding plan (#1412) * docs: swap header logo to webp, move meme logo to bottom Replace header logo with assets/logo.webp across all 6 README language variants and move the original meme logo (logo.jpg) to the bottom of each file. Co-Authored-By: Claude Opus 4.6 * docs: update GPT model names to gpt-5.4 and refine provider descriptions Update all 6 language README variants: - Correct GPT model references from gpt-5.2/gpt4 to gpt-5.4 - Refine provider descriptions in API Key comparison tables Co-Authored-By: Claude Opus 4.6 * chore: update default model to gpt-5.4, codex to gpt-5.3-codex Update OpenAI default model references from gpt-5.2 to gpt-5.4 across source code, config examples, tests, and docs. Set Codex default model to gpt-5.3-codex. Co-Authored-By: Claude Opus 4.6 --------- Co-authored-by: Claude Opus 4.6 --- README.fr.md | 61 ++++++++++++----- README.ja.md | 61 ++++++++++++----- README.md | 62 +++++++++++++----- README.pt-br.md | 61 ++++++++++++----- README.vi.md | 59 ++++++++++++----- README.zh.md | 62 +++++++++++++----- assets/logo.webp | Bin 0 -> 38262 bytes .../internal/ui/model.go | 4 +- cmd/picoclaw/internal/auth/helpers.go | 14 ++-- config/config.example.json | 14 ++-- docs/design/provider-refactoring.md | 12 ++-- docs/migration/model-list-migration.md | 14 ++-- pkg/config/config_test.go | 2 +- pkg/config/defaults.go | 18 +++-- pkg/config/migration.go | 4 +- pkg/config/migration_test.go | 14 ++-- pkg/providers/codex_cli_provider_test.go | 4 +- pkg/providers/codex_provider.go | 2 +- pkg/providers/codex_provider_test.go | 4 +- web/backend/api/gateway_test.go | 2 +- web/backend/api/models_test.go | 8 +-- web/backend/api/oauth.go | 4 +- web/backend/api/oauth_test.go | 4 +- workspace/skills/summarize/SKILL.md | 2 +- 24 files changed, 325 insertions(+), 167 deletions(-) create mode 100644 assets/logo.webp diff --git a/README.fr.md b/README.fr.md index 574402a3e..1d5a3a256 100644 --- a/README.fr.md +++ b/README.fr.md @@ -1,5 +1,5 @@
- PicoClaw + PicoClaw

PicoClaw : Assistant IA Ultra-Efficace en Go

@@ -206,9 +206,7 @@ docker compose -f docker/docker-compose.yml --profile gateway up -d ### 🚀 Démarrage Rapide > [!TIP] -> Configurez votre clé API dans `~/.picoclaw/config.json`. -> Obtenir des clés API : [OpenRouter](https://openrouter.ai/keys) (LLM) · [Zhipu](https://open.bigmodel.cn/usercenter/proj-mgmt/apikeys) (LLM) -> La recherche web est **optionnelle** — obtenez gratuitement l'[API Brave Search](https://brave.com/search/api) (2000 requêtes gratuites/mois) ou utilisez le repli automatique intégré. +> Configurez votre clé API dans `~/.picoclaw/config.json`. Obtenez des clés API : [Volcengine (CodingPlan)](https://console.volcengine.com) (LLM) · [OpenRouter](https://openrouter.ai/keys) (LLM) · [Zhipu](https://open.bigmodel.cn/usercenter/proj-mgmt/apikeys) (LLM). La recherche web est optionnelle — obtenez gratuitement l'[API Tavily](https://tavily.com) (1000 requêtes gratuites/mois) ou l'[API Brave Search](https://brave.com/search/api) (2000 requêtes gratuites/mois). **1. Initialiser** @@ -222,8 +220,13 @@ picoclaw onboard { "model_list": [ { - "model_name": "gpt4", - "model": "openai/gpt-5.2", + "model_name": "ark-code-latest", + "model": "volcengine/ark-code-latest", + "api_key": "sk-your-api-key" + }, + { + "model_name": "gpt-5.4", + "model": "openai/gpt-5.4", "api_key": "sk-your-openai-key", "request_timeout": 300, "api_base": "https://api.openai.com/v1" @@ -231,7 +234,7 @@ picoclaw onboard ], "agents": { "defaults": { - "model_name": "gpt4" + "model_name": "gpt-5.4" } }, "channels": { @@ -977,8 +980,9 @@ Cette conception permet également le **support multi-agent** avec une sélectio | **OpenRouter** | `openrouter/` | `https://openrouter.ai/api/v1` | OpenAI | [Obtenir Clé](https://openrouter.ai/keys) | | **VLLM** | `vllm/` | `http://localhost:8000/v1` | OpenAI | Local | | **Cerebras** | `cerebras/` | `https://api.cerebras.ai/v1` | OpenAI | [Obtenir Clé](https://cerebras.ai) | -| **Volcengine** | `volcengine/` | `https://ark.cn-beijing.volces.com/api/v3` | OpenAI | [Obtenir Clé](https://console.volcengine.com) | +| **VolcEngine (Doubao)** | `volcengine/` | `https://ark.cn-beijing.volces.com/api/v3` | OpenAI | [Obtenir Clé](https://console.volcengine.com) | | **ShengsuanYun** | `shengsuanyun/` | `https://router.shengsuanyun.com/api/v1` | OpenAI | - | +| **BytePlus** | `byteplus/` | `https://ark.ap-southeast.bytepluses.com/api/v3` | OpenAI | [Obtenir Clé](https://console.volcengine.com) | | **LongCat** | `longcat/` | `https://api.longcat.chat/openai` | OpenAI | [Obtenir une clé](https://longcat.chat/platform) | | **Antigravity** | `antigravity/` | Google Cloud | Custom | OAuth uniquement | | **GitHub Copilot** | `github-copilot/` | `localhost:4321` | gRPC | - | @@ -989,8 +993,13 @@ Cette conception permet également le **support multi-agent** avec une sélectio { "model_list": [ { - "model_name": "gpt-5.2", - "model": "openai/gpt-5.2", + "model_name": "ark-code-latest", + "model": "volcengine/ark-code-latest", + "api_key": "sk-your-api-key" + }, + { + "model_name": "gpt-5.4", + "model": "openai/gpt-5.4", "api_key": "sk-your-openai-key" }, { @@ -1006,7 +1015,7 @@ Cette conception permet également le **support multi-agent** avec une sélectio ], "agents": { "defaults": { - "model": "gpt-5.2" + "model": "gpt-5.4" } } } @@ -1017,8 +1026,17 @@ Cette conception permet également le **support multi-agent** avec une sélectio **OpenAI** ```json { - "model_name": "gpt-5.2", - "model": "openai/gpt-5.2", + "model_name": "gpt-5.4", + "model": "openai/gpt-5.4", + "api_key": "sk-..." +} +``` + +**VolcEngine (Doubao)** +```json +{ + "model_name": "ark-code-latest", + "model": "volcengine/ark-code-latest", "api_key": "sk-..." } ``` @@ -1061,14 +1079,14 @@ Configurez plusieurs points de terminaison pour le même nom de modèle—PicoCl { "model_list": [ { - "model_name": "gpt-5.2", - "model": "openai/gpt-5.2", + "model_name": "gpt-5.4", + "model": "openai/gpt-5.4", "api_base": "https://api1.example.com/v1", "api_key": "sk-key1" }, { - "model_name": "gpt-5.2", - "model": "openai/gpt-5.2", + "model_name": "gpt-5.4", + "model": "openai/gpt-5.4", "api_base": "https://api2.example.com/v1", "api_key": "sk-key2" } @@ -1200,6 +1218,13 @@ Cela se produit lorsqu'une autre instance du bot est en cours d'exécution. Assu | Service | Offre Gratuite | Cas d'Utilisation | | ---------------- | -------------------- | ------------------------------------- | | **OpenRouter** | 200K tokens/mois | Multiples modèles (Claude, GPT-4, etc.) | -| **Zhipu** | 200K tokens/mois | Idéal pour les utilisateurs chinois | +| **Volcengine CodingPlan** | 9,9¥/premier mois | Idéal pour les utilisateurs chinois, multiples modèles SOTA (Doubao, DeepSeek, etc.) | +| **Zhipu** | 200K tokens/mois | Convient aux utilisateurs chinois | | **Brave Search** | 2000 requêtes/mois | Fonctionnalité de recherche web | | **Groq** | Offre gratuite dispo | Inférence ultra-rapide (Llama, Mixtral) | + +--- + +
+ PicoClaw Meme +
diff --git a/README.ja.md b/README.ja.md index 1eb47cfdc..d41975294 100644 --- a/README.ja.md +++ b/README.ja.md @@ -1,5 +1,5 @@
-PicoClaw +PicoClaw

PicoClaw: Go で書かれた超効率 AI アシスタント

@@ -168,9 +168,7 @@ docker compose -f docker/docker-compose.yml --profile gateway up -d ### 🚀 クイックスタート(ネイティブ) > [!TIP] -> `~/.picoclaw/config.json` に API キーを設定してください。 -> API キーの取得先: [OpenRouter](https://openrouter.ai/keys) (LLM) · [Zhipu](https://open.bigmodel.cn/usercenter/proj-mgmt/apikeys) (LLM) -> Web 検索は **任意** です - 無料の [Tavily API](https://tavily.com) (月 1000 クエリ無料) または [Brave Search API](https://brave.com/search/api) (月 2000 クエリ無料) +> `~/.picoclaw/config.json` に API キーを設定してください。API キーの取得先: [Volcengine (CodingPlan)](https://console.volcengine.com) (LLM) · [OpenRouter](https://openrouter.ai/keys) (LLM) · [Zhipu](https://open.bigmodel.cn/usercenter/proj-mgmt/apikeys) (LLM)。Web 検索は **任意** です — 無料の [Tavily API](https://tavily.com) (月 1000 クエリ無料) または [Brave Search API](https://brave.com/search/api) (月 2000 クエリ無料)。 **1. 初期化** @@ -184,8 +182,13 @@ picoclaw onboard { "model_list": [ { - "model_name": "gpt4", - "model": "openai/gpt-5.2", + "model_name": "ark-code-latest", + "model": "volcengine/ark-code-latest", + "api_key": "sk-your-api-key" + }, + { + "model_name": "gpt-5.4", + "model": "openai/gpt-5.4", "api_key": "sk-your-openai-key", "request_timeout": 300, "api_base": "https://api.openai.com/v1" @@ -193,7 +196,7 @@ picoclaw onboard ], "agents": { "defaults": { - "model_name": "gpt4" + "model_name": "gpt-5.4" } }, "channels": { @@ -918,8 +921,9 @@ HEARTBEAT_OK 応答 ユーザーが直接結果を受け取る | **OpenRouter** | `openrouter/` | `https://openrouter.ai/api/v1` | OpenAI | [キーを取得](https://openrouter.ai/keys) | | **VLLM** | `vllm/` | `http://localhost:8000/v1` | OpenAI | ローカル | | **Cerebras** | `cerebras/` | `https://api.cerebras.ai/v1` | OpenAI | [キーを取得](https://cerebras.ai) | -| **Volcengine** | `volcengine/` | `https://ark.cn-beijing.volces.com/api/v3` | OpenAI | [キーを取得](https://console.volcengine.com) | +| **VolcEngine (Doubao)** | `volcengine/` | `https://ark.cn-beijing.volces.com/api/v3` | OpenAI | [キーを取得](https://console.volcengine.com) | | **ShengsuanYun** | `shengsuanyun/` | `https://router.shengsuanyun.com/api/v1` | OpenAI | - | +| **BytePlus** | `byteplus/` | `https://ark.ap-southeast.bytepluses.com/api/v3` | OpenAI | [キーを取得](https://console.volcengine.com) | | **LongCat** | `longcat/` | `https://api.longcat.chat/openai` | OpenAI | [キーを取得](https://longcat.chat/platform) | | **Antigravity** | `antigravity/` | Google Cloud | カスタム | OAuthのみ | | **GitHub Copilot** | `github-copilot/` | `localhost:4321` | gRPC | - | @@ -930,8 +934,13 @@ HEARTBEAT_OK 応答 ユーザーが直接結果を受け取る { "model_list": [ { - "model_name": "gpt-5.2", - "model": "openai/gpt-5.2", + "model_name": "ark-code-latest", + "model": "volcengine/ark-code-latest", + "api_key": "sk-your-api-key" + }, + { + "model_name": "gpt-5.4", + "model": "openai/gpt-5.4", "api_key": "sk-your-openai-key" }, { @@ -947,7 +956,7 @@ HEARTBEAT_OK 応答 ユーザーが直接結果を受け取る ], "agents": { "defaults": { - "model": "gpt-5.2" + "model": "gpt-5.4" } } } @@ -958,8 +967,17 @@ HEARTBEAT_OK 応答 ユーザーが直接結果を受け取る **OpenAI** ```json { - "model_name": "gpt-5.2", - "model": "openai/gpt-5.2", + "model_name": "gpt-5.4", + "model": "openai/gpt-5.4", + "api_key": "sk-..." +} +``` + +**VolcEngine (Doubao)** +```json +{ + "model_name": "ark-code-latest", + "model": "volcengine/ark-code-latest", "api_key": "sk-..." } ``` @@ -1002,14 +1020,14 @@ HEARTBEAT_OK 応答 ユーザーが直接結果を受け取る { "model_list": [ { - "model_name": "gpt-5.2", - "model": "openai/gpt-5.2", + "model_name": "gpt-5.4", + "model": "openai/gpt-5.4", "api_base": "https://api1.example.com/v1", "api_key": "sk-key1" }, { - "model_name": "gpt-5.2", - "model": "openai/gpt-5.2", + "model_name": "gpt-5.4", + "model": "openai/gpt-5.4", "api_base": "https://api2.example.com/v1", "api_key": "sk-key2" } @@ -1120,9 +1138,16 @@ Web 検索を有効にするには: | サービス | 無料枠 | ユースケース | |---------|--------|------------| | **OpenRouter** | 月 200K トークン | 複数モデル(Claude, GPT-4 など) | -| **Zhipu** | 月 200K トークン | 中国ユーザー向け最適 | +| **Volcengine CodingPlan** | 9.9元/初月 | 中国ユーザーに最適、複数のSOTAモデル(Doubao、DeepSeek等) | +| **Zhipu** | 月 200K トークン | 中国ユーザーに適している | | **Qwen** | 無料枠あり | 通義千問 (Qwen) | | **Brave Search** | 月 2000 クエリ | Web 検索機能 | | **Tavily** | 月 1000 クエリ | AI エージェント検索最適化 | | **Groq** | 無料枠あり | 高速推論(Llama, Mixtral) | | **Cerebras** | 無料枠あり | 高速推論(Llama, Qwen など) | + +--- + +
+ PicoClaw Meme +
diff --git a/README.md b/README.md index 55e9fb187..ebcd6dddf 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@
- PicoClaw + PicoClaw

PicoClaw: Ultra-Efficient AI Assistant in Go

@@ -227,9 +227,7 @@ docker compose -f docker/docker-compose.yml --profile gateway up -d ### 🚀 Quick Start > [!TIP] -> Set your API key in `~/.picoclaw/config.json`. -> Get API keys: [OpenRouter](https://openrouter.ai/keys) (LLM) · [Zhipu](https://open.bigmodel.cn/usercenter/proj-mgmt/apikeys) (LLM) -> Web Search is **optional** - get free [Tavily API](https://tavily.com) (1000 free queries/month), [SearXNG](https://github.com/searxng/searxng) (free, self-hosted) or [Brave Search API](https://brave.com/search/api) (2000 free queries/month) or use built-in auto fallback. +> Set your API Key in `~/.picoclaw/config.json`. Get API Keys: [Volcengine (CodingPlan)](https://console.volcengine.com) (LLM) · [OpenRouter](https://openrouter.ai/keys) (LLM) · [Zhipu](https://open.bigmodel.cn/usercenter/proj-mgmt/apikeys) (LLM). Web search is optional — get a free [Tavily API](https://tavily.com) (1000 free queries/month) or [Brave Search API](https://brave.com/search/api) (2000 free queries/month). **1. Initialize** @@ -244,7 +242,7 @@ picoclaw onboard "agents": { "defaults": { "workspace": "~/.picoclaw/workspace", - "model_name": "gpt4", + "model_name": "gpt-5.4", "max_tokens": 8192, "temperature": 0.7, "max_tool_iterations": 20 @@ -252,8 +250,13 @@ picoclaw onboard }, "model_list": [ { - "model_name": "gpt4", - "model": "openai/gpt-5.2", + "model_name": "ark-code-latest", + "model": "volcengine/ark-code-latest", + "api_key": "sk-your-api-key" + }, + { + "model_name": "gpt-5.4", + "model": "openai/gpt-5.4", "api_key": "your-api-key", "request_timeout": 300 }, @@ -1030,8 +1033,9 @@ This design also enables **multi-agent support** with flexible provider selectio | **LiteLLM Proxy** | `litellm/` | `http://localhost:4000/v1` | OpenAI | Your LiteLLM proxy key | | **VLLM** | `vllm/` | `http://localhost:8000/v1` | OpenAI | Local | | **Cerebras** | `cerebras/` | `https://api.cerebras.ai/v1` | OpenAI | [Get Key](https://cerebras.ai) | -| **火山引擎** | `volcengine/` | `https://ark.cn-beijing.volces.com/api/v3` | OpenAI | [Get Key](https://console.volcengine.com) | +| **VolcEngine (Doubao)** | `volcengine/` | `https://ark.cn-beijing.volces.com/api/v3` | OpenAI | [Get Key](https://console.volcengine.com) | | **神算云** | `shengsuanyun/` | `https://router.shengsuanyun.com/api/v1` | OpenAI | - | +| **BytePlus** | `byteplus/` | `https://ark.ap-southeast.bytepluses.com/api/v3` | OpenAI | [Get Key](https://console.volcengine.com) | | **Vivgrid** | `vivgrid/` | `https://api.vivgrid.com/v1` | OpenAI | [Get Key](https://vivgrid.com) | | **LongCat** | `longcat/` | `https://api.longcat.chat/openai` | OpenAI | [Get Key](https://longcat.chat/platform) | | **Antigravity** | `antigravity/` | Google Cloud | Custom | OAuth only | @@ -1043,8 +1047,13 @@ This design also enables **multi-agent support** with flexible provider selectio { "model_list": [ { - "model_name": "gpt-5.2", - "model": "openai/gpt-5.2", + "model_name": "ark-code-latest", + "model": "volcengine/ark-code-latest", + "api_key": "sk-your-api-key" + }, + { + "model_name": "gpt-5.4", + "model": "openai/gpt-5.4", "api_key": "sk-your-openai-key" }, { @@ -1060,7 +1069,7 @@ This design also enables **multi-agent support** with flexible provider selectio ], "agents": { "defaults": { - "model": "gpt-5.2" + "model": "gpt-5.4" } } } @@ -1072,8 +1081,18 @@ This design also enables **multi-agent support** with flexible provider selectio ```json { - "model_name": "gpt-5.2", - "model": "openai/gpt-5.2", + "model_name": "gpt-5.4", + "model": "openai/gpt-5.4", + "api_key": "sk-..." +} +``` + +**VolcEngine (Doubao)** + +```json +{ + "model_name": "ark-code-latest", + "model": "volcengine/ark-code-latest", "api_key": "sk-..." } ``` @@ -1152,14 +1171,14 @@ Configure multiple endpoints for the same model name—PicoClaw will automatical { "model_list": [ { - "model_name": "gpt-5.2", - "model": "openai/gpt-5.2", + "model_name": "gpt-5.4", + "model": "openai/gpt-5.4", "api_base": "https://api1.example.com/v1", "api_key": "sk-key1" }, { - "model_name": "gpt-5.2", - "model": "openai/gpt-5.2", + "model_name": "gpt-5.4", + "model": "openai/gpt-5.4", "api_base": "https://api2.example.com/v1", "api_key": "sk-key2" } @@ -1499,9 +1518,16 @@ This happens when another instance of the bot is running. Make sure only one `pi | Service | Free Tier | Use Case | | ---------------- | ------------------------ | ------------------------------------- | | **OpenRouter** | 200K tokens/month | Multiple models (Claude, GPT-4, etc.) | -| **Zhipu** | 200K tokens/month | Best for Chinese users | +| **Volcengine CodingPlan** | ¥9.9/first month | Best for Chinese users, multiple SOTA models (Doubao, DeepSeek, etc.) | +| **Zhipu** | 200K tokens/month | Suitable for Chinese users | | **Brave Search** | Paid ($5/1000 queries) | Web search functionality | | **SearXNG** | Unlimited (self-hosted) | Privacy-focused metasearch (70+ engines) | | **Groq** | Free tier available | Fast inference (Llama, Mixtral) | | **Cerebras** | Free tier available | Fast inference (Llama, Qwen, etc.) | | **LongCat** | Up to 5M tokens/day | Fast inference (free tier) | + +--- + +
+ PicoClaw Meme +
diff --git a/README.pt-br.md b/README.pt-br.md index 066d71d6a..474cb199c 100644 --- a/README.pt-br.md +++ b/README.pt-br.md @@ -1,5 +1,5 @@
-PicoClaw +PicoClaw

PicoClaw: Assistente de IA Ultra-Eficiente em Go

@@ -207,9 +207,7 @@ docker compose -f docker/docker-compose.yml --profile gateway up -d ### 🚀 Início Rápido > [!TIP] -> Configure sua API key em `~/.picoclaw/config.json`. -> Obtenha API keys: [OpenRouter](https://openrouter.ai/keys) (LLM) · [Zhipu](https://open.bigmodel.cn/usercenter/proj-mgmt/apikeys) (LLM) -> Busca web e **opcional** — obtenha a [Brave Search API](https://brave.com/search/api) gratuita (2000 consultas grátis/mês) ou use o fallback automático integrado. +> Configure sua API key em `~/.picoclaw/config.json`. Obtenha API keys: [Volcengine (CodingPlan)](https://console.volcengine.com) (LLM) · [OpenRouter](https://openrouter.ai/keys) (LLM) · [Zhipu](https://open.bigmodel.cn/usercenter/proj-mgmt/apikeys) (LLM). Busca web é **opcional** — obtenha a [API Tavily](https://tavily.com) gratuita (1000 consultas grátis/mês) ou a [Brave Search API](https://brave.com/search/api) (2000 consultas grátis/mês). **1. Inicializar** @@ -223,8 +221,13 @@ picoclaw onboard { "model_list": [ { - "model_name": "gpt4", - "model": "openai/gpt-5.2", + "model_name": "ark-code-latest", + "model": "volcengine/ark-code-latest", + "api_key": "sk-your-api-key" + }, + { + "model_name": "gpt-5.4", + "model": "openai/gpt-5.4", "api_key": "sk-your-openai-key", "request_timeout": 300, "api_base": "https://api.openai.com/v1" @@ -232,7 +235,7 @@ picoclaw onboard ], "agents": { "defaults": { - "model_name": "gpt4" + "model_name": "gpt-5.4" } }, "tools": { @@ -973,8 +976,9 @@ Este design também possibilita o **suporte multi-agent** com seleção flexíve | **OpenRouter** | `openrouter/` | `https://openrouter.ai/api/v1` | OpenAI | [Obter Chave](https://openrouter.ai/keys) | | **VLLM** | `vllm/` | `http://localhost:8000/v1` | OpenAI | Local | | **Cerebras** | `cerebras/` | `https://api.cerebras.ai/v1` | OpenAI | [Obter Chave](https://cerebras.ai) | -| **Volcengine** | `volcengine/` | `https://ark.cn-beijing.volces.com/api/v3` | OpenAI | [Obter Chave](https://console.volcengine.com) | +| **VolcEngine (Doubao)** | `volcengine/` | `https://ark.cn-beijing.volces.com/api/v3` | OpenAI | [Obter Chave](https://console.volcengine.com) | | **ShengsuanYun** | `shengsuanyun/` | `https://router.shengsuanyun.com/api/v1` | OpenAI | - | +| **BytePlus** | `byteplus/` | `https://ark.ap-southeast.bytepluses.com/api/v3` | OpenAI | [Obter Chave](https://console.volcengine.com) | | **LongCat** | `longcat/` | `https://api.longcat.chat/openai` | OpenAI | [Obter Chave](https://longcat.chat/platform) | | **Antigravity** | `antigravity/` | Google Cloud | Custom | Apenas OAuth | | **GitHub Copilot** | `github-copilot/` | `localhost:4321` | gRPC | - | @@ -985,8 +989,13 @@ Este design também possibilita o **suporte multi-agent** com seleção flexíve { "model_list": [ { - "model_name": "gpt-5.2", - "model": "openai/gpt-5.2", + "model_name": "ark-code-latest", + "model": "volcengine/ark-code-latest", + "api_key": "sk-your-api-key" + }, + { + "model_name": "gpt-5.4", + "model": "openai/gpt-5.4", "api_key": "sk-your-openai-key" }, { @@ -1002,7 +1011,7 @@ Este design também possibilita o **suporte multi-agent** com seleção flexíve ], "agents": { "defaults": { - "model": "gpt-5.2" + "model": "gpt-5.4" } } } @@ -1013,8 +1022,17 @@ Este design também possibilita o **suporte multi-agent** com seleção flexíve **OpenAI** ```json { - "model_name": "gpt-5.2", - "model": "openai/gpt-5.2", + "model_name": "gpt-5.4", + "model": "openai/gpt-5.4", + "api_key": "sk-..." +} +``` + +**VolcEngine (Doubao)** +```json +{ + "model_name": "ark-code-latest", + "model": "volcengine/ark-code-latest", "api_key": "sk-..." } ``` @@ -1057,14 +1075,14 @@ Configure vários endpoints para o mesmo nome de modelo—PicoClaw fará round-r { "model_list": [ { - "model_name": "gpt-5.2", - "model": "openai/gpt-5.2", + "model_name": "gpt-5.4", + "model": "openai/gpt-5.4", "api_base": "https://api1.example.com/v1", "api_key": "sk-key1" }, { - "model_name": "gpt-5.2", - "model": "openai/gpt-5.2", + "model_name": "gpt-5.4", + "model": "openai/gpt-5.4", "api_base": "https://api2.example.com/v1", "api_key": "sk-key2" } @@ -1196,7 +1214,14 @@ Isso acontece quando outra instância do bot está em execução. Certifique-se | Serviço | Plano Gratuito | Caso de Uso | | --- | --- | --- | | **OpenRouter** | 200K tokens/mês | Múltiplos modelos (Claude, GPT-4, etc.) | -| **Zhipu** | 200K tokens/mês | Melhor para usuários chineses | +| **Volcengine CodingPlan** | ¥9,9/primeiro mês | Ideal para usuários chineses, múltiplos modelos SOTA (Doubao, DeepSeek, etc.) | +| **Zhipu** | 200K tokens/mês | Adequado para usuários chineses | | **Brave Search** | 2000 consultas/mês | Funcionalidade de busca web | | **Groq** | Plano gratuito disponível | Inferência ultra-rápida (Llama, Mixtral) | | **Cerebras** | Plano gratuito disponível | Inferência ultra-rápida (Llama 3.3 70B) | + +--- + +
+ PicoClaw Meme +
diff --git a/README.vi.md b/README.vi.md index 66573a1c5..38eed4d4d 100644 --- a/README.vi.md +++ b/README.vi.md @@ -1,5 +1,5 @@
-PicoClaw +PicoClaw

PicoClaw: Trợ lý AI Siêu Nhẹ viết bằng Go

@@ -187,9 +187,7 @@ docker compose -f docker/docker-compose.yml --profile gateway up -d ### 🚀 Bắt đầu nhanh > [!TIP] -> Thiết lập API key trong `~/.picoclaw/config.json`. -> Lấy API key: [OpenRouter](https://openrouter.ai/keys) (LLM) · [Zhipu](https://open.bigmodel.cn/usercenter/proj-mgmt/apikeys) (LLM) -> Tìm kiếm web là **tùy chọn** — lấy [Brave Search API](https://brave.com/search/api) miễn phí (2000 truy vấn/tháng) hoặc dùng tính năng auto fallback tích hợp sẵn. +> Thiết lập API key trong `~/.picoclaw/config.json`. Lấy API key: [Volcengine (CodingPlan)](https://console.volcengine.com) (LLM) · [OpenRouter](https://openrouter.ai/keys) (LLM) · [Zhipu](https://open.bigmodel.cn/usercenter/proj-mgmt/apikeys) (LLM). Tìm kiếm web là **tùy chọn** — lấy [Tavily API](https://tavily.com) miễn phí (1000 truy vấn/tháng) hoặc [Brave Search API](https://brave.com/search/api) (2000 truy vấn/tháng). **1. Khởi tạo** @@ -203,8 +201,13 @@ picoclaw onboard { "model_list": [ { - "model_name": "gpt4", - "model": "openai/gpt-5.2", + "model_name": "ark-code-latest", + "model": "volcengine/ark-code-latest", + "api_key": "sk-your-api-key" + }, + { + "model_name": "gpt-5.4", + "model": "openai/gpt-5.4", "api_key": "sk-your-openai-key", "request_timeout": 300, "api_base": "https://api.openai.com/v1" @@ -942,8 +945,9 @@ Thiết kế này cũng cho phép **hỗ trợ đa tác nhân** với lựa ch | **OpenRouter** | `openrouter/` | `https://openrouter.ai/api/v1` | OpenAI | [Lấy Khóa](https://openrouter.ai/keys) | | **VLLM** | `vllm/` | `http://localhost:8000/v1` | OpenAI | Local | | **Cerebras** | `cerebras/` | `https://api.cerebras.ai/v1` | OpenAI | [Lấy Khóa](https://cerebras.ai) | -| **Volcengine** | `volcengine/` | `https://ark.cn-beijing.volces.com/api/v3` | OpenAI | [Lấy Khóa](https://console.volcengine.com) | +| **VolcEngine (Doubao)** | `volcengine/` | `https://ark.cn-beijing.volces.com/api/v3` | OpenAI | [Lấy Khóa](https://console.volcengine.com) | | **ShengsuanYun** | `shengsuanyun/` | `https://router.shengsuanyun.com/api/v1` | OpenAI | - | +| **BytePlus** | `byteplus/` | `https://ark.ap-southeast.bytepluses.com/api/v3` | OpenAI | [Lấy Khóa](https://console.volcengine.com) | | **LongCat** | `longcat/` | `https://api.longcat.chat/openai` | OpenAI | [Lấy Key](https://longcat.chat/platform) | | **Antigravity** | `antigravity/` | Google Cloud | Tùy chỉnh | Chỉ OAuth | | **GitHub Copilot** | `github-copilot/` | `localhost:4321` | gRPC | - | @@ -954,8 +958,13 @@ 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-5.2", - "model": "openai/gpt-5.2", + "model_name": "ark-code-latest", + "model": "volcengine/ark-code-latest", + "api_key": "sk-your-api-key" + }, + { + "model_name": "gpt-5.4", + "model": "openai/gpt-5.4", "api_key": "sk-your-openai-key" }, { @@ -971,7 +980,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-5.2" + "model": "gpt-5.4" } } } @@ -982,8 +991,17 @@ 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-5.2", - "model": "openai/gpt-5.2", + "model_name": "gpt-5.4", + "model": "openai/gpt-5.4", + "api_key": "sk-..." +} +``` + +**VolcEngine (Doubao)** +```json +{ + "model_name": "ark-code-latest", + "model": "volcengine/ark-code-latest", "api_key": "sk-..." } ``` @@ -1026,14 +1044,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-5.2", - "model": "openai/gpt-5.2", + "model_name": "gpt-5.4", + "model": "openai/gpt-5.4", "api_base": "https://api1.example.com/v1", "api_key": "sk-key1" }, { - "model_name": "gpt-5.2", - "model": "openai/gpt-5.2", + "model_name": "gpt-5.4", + "model": "openai/gpt-5.4", "api_base": "https://api2.example.com/v1", "api_key": "sk-key2" } @@ -1165,6 +1183,13 @@ Một số nhà cung cấp (như Zhipu) có bộ lọc nội dung nghiêm ngặt | Dịch vụ | Gói miễn phí | Trường hợp sử dụng | | --- | --- | --- | | **OpenRouter** | 200K tokens/tháng | Đa model (Claude, GPT-4, v.v.) | -| **Zhipu** | 200K tokens/tháng | Tốt nhất cho người dùng Trung Quốc | +| **Volcengine CodingPlan** | ¥9.9/tháng đầu | Tốt nhất cho người dùng Trung Quốc, nhiều mô hình SOTA (Doubao, DeepSeek, v.v.) | +| **Zhipu** | 200K tokens/tháng | Phù hợp cho người dùng Trung Quốc | | **Brave Search** | 2000 truy vấn/tháng | Chức năng tìm kiếm web | | **Groq** | Có gói miễn phí | Suy luận siêu nhanh (Llama, Mixtral) | + +--- + +
+ PicoClaw Meme +
diff --git a/README.zh.md b/README.zh.md index a3a4c7f5f..6395b1e7b 100644 --- a/README.zh.md +++ b/README.zh.md @@ -1,5 +1,5 @@
-PicoClaw +PicoClaw

PicoClaw: 基于Go语言的超高效 AI 助手

@@ -208,9 +208,7 @@ docker compose -f docker/docker-compose.yml --profile gateway up -d ### 🚀 快速开始 > [!TIP] -> 在 `~/.picoclaw/config.json` 中设置您的 API Key。 -> 获取 API Key: [OpenRouter](https://openrouter.ai/keys) (LLM) · [Zhipu (智谱)](https://open.bigmodel.cn/usercenter/proj-mgmt/apikeys) (LLM) -> 网络搜索是 **可选的** - 获取免费的 [Tavily API](https://tavily.com) (每月 1000 次免费查询) 或 [Brave Search API](https://brave.com/search/api) (每月 2000 次免费查询) +> 在 `~/.picoclaw/config.json` 中设置您的 API Key。获取 API Key: [火山引擎 (CodingPlan)](https://console.volcengine.com) (LLM) · [OpenRouter](https://openrouter.ai/keys) (LLM) · [Zhipu (智谱)](https://open.bigmodel.cn/usercenter/proj-mgmt/apikeys) (LLM)。网络搜索是 **可选的** — 获取免费的 [Tavily API](https://tavily.com) (每月 1000 次免费查询) 或 [Brave Search API](https://brave.com/search/api) (每月 2000 次免费查询)。 **1. 初始化 (Initialize)** @@ -226,7 +224,7 @@ picoclaw onboard "agents": { "defaults": { "workspace": "~/.picoclaw/workspace", - "model_name": "gpt4", + "model_name": "gpt-5.4", "max_tokens": 8192, "temperature": 0.7, "max_tool_iterations": 20 @@ -234,8 +232,13 @@ picoclaw onboard }, "model_list": [ { - "model_name": "gpt4", - "model": "openai/gpt-5.2", + "model_name": "ark-code-latest", + "model": "volcengine/ark-code-latest", + "api_key": "sk-your-api-key" + }, + { + "model_name": "gpt-5.4", + "model": "openai/gpt-5.4", "api_key": "your-api-key", "request_timeout": 300 }, @@ -514,8 +517,9 @@ Agent 读取 HEARTBEAT.md | **OpenRouter** | `openrouter/` | `https://openrouter.ai/api/v1` | OpenAI | [获取密钥](https://openrouter.ai/keys) | | **VLLM** | `vllm/` | `http://localhost:8000/v1` | OpenAI | 本地 | | **Cerebras** | `cerebras/` | `https://api.cerebras.ai/v1` | OpenAI | [获取密钥](https://cerebras.ai) | -| **火山引擎** | `volcengine/` | `https://ark.cn-beijing.volces.com/api/v3` | OpenAI | [获取密钥](https://console.volcengine.com) | +| **火山引擎(Doubao)** | `volcengine/` | `https://ark.cn-beijing.volces.com/api/v3` | OpenAI | [获取密钥](https://console.volcengine.com) | | **神算云** | `shengsuanyun/` | `https://router.shengsuanyun.com/api/v1` | OpenAI | - | +| **BytePlus** | `byteplus/` | `https://ark.ap-southeast.bytepluses.com/api/v3` | OpenAI | [获取密钥](https://console.volcengine.com) | | **LongCat** | `longcat/` | `https://api.longcat.chat/openai` | OpenAI | [获取密钥](https://longcat.chat/platform) | | **Antigravity** | `antigravity/` | Google Cloud | 自定义 | 仅 OAuth | | **GitHub Copilot** | `github-copilot/` | `localhost:4321` | gRPC | - | @@ -526,8 +530,13 @@ Agent 读取 HEARTBEAT.md { "model_list": [ { - "model_name": "gpt-5.2", - "model": "openai/gpt-5.2", + "model_name": "ark-code-latest", + "model": "volcengine/ark-code-latest", + "api_key": "sk-your-api-key" + }, + { + "model_name": "gpt-5.4", + "model": "openai/gpt-5.4", "api_key": "sk-your-openai-key" }, { @@ -543,7 +552,7 @@ Agent 读取 HEARTBEAT.md ], "agents": { "defaults": { - "model": "gpt-5.2" + "model": "gpt-5.4" } } } @@ -555,8 +564,18 @@ Agent 读取 HEARTBEAT.md ```json { - "model_name": "gpt-5.2", - "model": "openai/gpt-5.2", + "model_name": "gpt-5.4", + "model": "openai/gpt-5.4", + "api_key": "sk-..." +} +``` + +**火山引擎(Doubao)** + +```json +{ + "model_name": "ark-code-latest", + "model": "volcengine/ark-code-latest", "api_key": "sk-..." } ``` @@ -622,14 +641,14 @@ Agent 读取 HEARTBEAT.md { "model_list": [ { - "model_name": "gpt-5.2", - "model": "openai/gpt-5.2", + "model_name": "gpt-5.4", + "model": "openai/gpt-5.4", "api_base": "https://api1.example.com/v1", "api_key": "sk-key1" }, { - "model_name": "gpt-5.2", - "model": "openai/gpt-5.2", + "model_name": "gpt-5.4", + "model": "openai/gpt-5.4", "api_base": "https://api2.example.com/v1", "api_key": "sk-key2" } @@ -875,8 +894,15 @@ Discord: [https://discord.gg/V4sAZ9XWpN](https://discord.gg/V4sAZ9XWpN) | 服务 | 免费层级 | 适用场景 | | --- | --- | --- | | **OpenRouter** | 200K tokens/月 | 多模型聚合 (Claude, GPT-4 等) | -| **智谱 (Zhipu)** | 200K tokens/月 | 最适合中国用户 | +| **火山引擎 CodingPlan** | 9.9 元/首月 | 最适合国内用户,多种 SOTA 模型(豆包、DeepSeek 等) | +| **智谱 (Zhipu)** | 200K tokens/月 | 适合中国用户 | | **Brave Search** | 2000 次查询/月 | 网络搜索功能 | | **Tavily** | 1000 次查询/月 | AI Agent 搜索优化 | | **Groq** | 提供免费层级 | 极速推理 (Llama, Mixtral) | | **LongCat** | 最多 5M tokens/天 | 推理速度快 (免费额度) | + +--- + +
+ PicoClaw Meme +
diff --git a/assets/logo.webp b/assets/logo.webp new file mode 100644 index 0000000000000000000000000000000000000000..9333f7e1bb1d82eb4e291d0b757a4ac5ec17b8d1 GIT binary patch literal 38262 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 Ke82?8pa1}lUAL70 literal 0 HcmV?d00001 diff --git a/cmd/picoclaw-launcher-tui/internal/ui/model.go b/cmd/picoclaw-launcher-tui/internal/ui/model.go index 47ca5a355..698502058 100644 --- a/cmd/picoclaw-launcher-tui/internal/ui/model.go +++ b/cmd/picoclaw-launcher-tui/internal/ui/model.go @@ -49,7 +49,7 @@ func (s *appState) modelMenu() tview.Primitive { Action: func() { newName := s.nextAvailableModelName("new-model") s.addModel( - picoclawconfig.ModelConfig{ModelName: newName, Model: "openai/gpt-5.2"}, + picoclawconfig.ModelConfig{ModelName: newName, Model: "openai/gpt-5.4"}, ) s.push( fmt.Sprintf("model-%d", len(s.config.ModelList)-1), @@ -291,7 +291,7 @@ func refreshModelMenuFromState(menu *Menu, s *appState) { Action: func() { newName := s.nextAvailableModelName("new-model") s.addModel( - picoclawconfig.ModelConfig{ModelName: newName, Model: "openai/gpt-5.2"}, + picoclawconfig.ModelConfig{ModelName: newName, Model: "openai/gpt-5.4"}, ) s.push(fmt.Sprintf("model-%d", len(s.config.ModelList)-1), s.modelForm(len(s.config.ModelList)-1)) }, diff --git a/cmd/picoclaw/internal/auth/helpers.go b/cmd/picoclaw/internal/auth/helpers.go index a0a229167..4bf132685 100644 --- a/cmd/picoclaw/internal/auth/helpers.go +++ b/cmd/picoclaw/internal/auth/helpers.go @@ -72,14 +72,14 @@ func authLoginOpenAI(useDeviceCode bool) error { // 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", + ModelName: "gpt-5.4", + Model: "openai/gpt-5.4", AuthMethod: "oauth", }) } // Update default model to use OpenAI - appCfg.Agents.Defaults.ModelName = "gpt-5.2" + appCfg.Agents.Defaults.ModelName = "gpt-5.4" if err = config.SaveConfig(internal.GetConfigPath(), appCfg); err != nil { return fmt.Errorf("could not update config: %w", err) @@ -90,7 +90,7 @@ func authLoginOpenAI(useDeviceCode bool) error { if cred.AccountID != "" { fmt.Printf("Account: %s\n", cred.AccountID) } - fmt.Println("Default model set to: gpt-5.2") + fmt.Println("Default model set to: gpt-5.4") return nil } @@ -318,13 +318,13 @@ func authLoginPasteToken(provider string) error { } if !found { appCfg.ModelList = append(appCfg.ModelList, config.ModelConfig{ - ModelName: "gpt-5.2", - Model: "openai/gpt-5.2", + ModelName: "gpt-5.4", + Model: "openai/gpt-5.4", AuthMethod: "token", }) } // Update default model - appCfg.Agents.Defaults.ModelName = "gpt-5.2" + appCfg.Agents.Defaults.ModelName = "gpt-5.4" } if err := config.SaveConfig(internal.GetConfigPath(), appCfg); err != nil { return fmt.Errorf("could not update config: %w", err) diff --git a/config/config.example.json b/config/config.example.json index 1eea37683..b259df6f6 100644 --- a/config/config.example.json +++ b/config/config.example.json @@ -3,7 +3,7 @@ "defaults": { "workspace": "~/.picoclaw/workspace", "restrict_to_workspace": true, - "model_name": "gpt4", + "model_name": "gpt-5.4", "max_tokens": 8192, "temperature": 0.7, "max_tool_iterations": 20, @@ -13,8 +13,8 @@ }, "model_list": [ { - "model_name": "gpt4", - "model": "openai/gpt-5.2", + "model_name": "gpt-5.4", + "model": "openai/gpt-5.4", "api_key": "sk-your-openai-key", "api_base": "https://api.openai.com/v1" }, @@ -41,14 +41,14 @@ "api_key": "your-longcat-api-key" }, { - "model_name": "loadbalanced-gpt4", - "model": "openai/gpt-5.2", + "model_name": "loadbalanced-gpt-5.4", + "model": "openai/gpt-5.4", "api_key": "sk-key1", "api_base": "https://api1.example.com/v1" }, { - "model_name": "loadbalanced-gpt4", - "model": "openai/gpt-5.2", + "model_name": "loadbalanced-gpt-5.4", + "model": "openai/gpt-5.4", "api_key": "sk-key2", "api_base": "https://api2.example.com/v1" } diff --git a/docs/design/provider-refactoring.md b/docs/design/provider-refactoring.md index a214d9857..38f379c50 100644 --- a/docs/design/provider-refactoring.md +++ b/docs/design/provider-refactoring.md @@ -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-5.2`, `anthropic/claude-sonnet-4.6` +2. **Protocol prefix**: Use `protocol/model_name` format, e.g., `openai/gpt-5.4`, `anthropic/claude-sonnet-4.6` 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-5.2", - "model": "openai/gpt-5.2", + "model_name": "gpt-5.4", + "model": "openai/gpt-5.4", "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-5.2 + Model string `json:"model"` // protocol/model, e.g., openai/gpt-5.4 // 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-5.2", + "model": "gpt-5.4", "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-5.2 + model: openai/gpt-5.4 api_key: xxx - model_name: my-custom litellm_params: diff --git a/docs/migration/model-list-migration.md b/docs/migration/model-list-migration.md index 0d4af719c..eed228d4d 100644 --- a/docs/migration/model-list-migration.md +++ b/docs/migration/model-list-migration.md @@ -40,7 +40,7 @@ The new `model_list` configuration offers several advantages: "agents": { "defaults": { "provider": "openai", - "model": "gpt-5.2" + "model": "gpt-5.4" } } } @@ -53,7 +53,7 @@ The new `model_list` configuration offers several advantages: "model_list": [ { "model_name": "gpt4", - "model": "openai/gpt-5.2", + "model": "openai/gpt-5.4", "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-5.2` | +| `openai/` | OpenAI API (default) | `openai/gpt-5.4` | | `anthropic/` | Anthropic API | `anthropic/claude-opus-4` | | `antigravity/` | Google via Antigravity OAuth | `antigravity/gemini-2.0-flash` | | `gemini/` | Google Gemini API | `gemini/gemini-2.0-flash-exp` | @@ -109,7 +109,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-5.2`) | +| `model` | Yes | Protocol and model identifier (e.g., `openai/gpt-5.4`) | | `api_base` | No | API endpoint URL | | `api_key` | No* | API authentication key | | `proxy` | No | HTTP proxy URL | @@ -130,19 +130,19 @@ Configure multiple endpoints for the same model to distribute load: "model_list": [ { "model_name": "gpt4", - "model": "openai/gpt-5.2", + "model": "openai/gpt-5.4", "api_key": "sk-key1", "api_base": "https://api1.example.com/v1" }, { "model_name": "gpt4", - "model": "openai/gpt-5.2", + "model": "openai/gpt-5.4", "api_key": "sk-key2", "api_base": "https://api2.example.com/v1" }, { "model_name": "gpt4", - "model": "openai/gpt-5.2", + "model": "openai/gpt-5.4", "api_key": "sk-key3", "api_base": "https://api3.example.com/v1" } diff --git a/pkg/config/config_test.go b/pkg/config/config_test.go index ad89d6d2e..1c93028c7 100644 --- a/pkg/config/config_test.go +++ b/pkg/config/config_test.go @@ -444,7 +444,7 @@ func TestLoadConfig_WebToolsProxy(t *testing.T) { configPath := filepath.Join(tmpDir, "config.json") configJSON := `{ "agents": {"defaults":{"workspace":"./workspace","model":"gpt4","max_tokens":8192,"max_tool_iterations":20}}, - "model_list": [{"model_name":"gpt4","model":"openai/gpt-5.2","api_key":"x"}], + "model_list": [{"model_name":"gpt4","model":"openai/gpt-5.4","api_key":"x"}], "tools": {"web":{"proxy":"http://127.0.0.1:7890"}} }` if err := os.WriteFile(configPath, []byte(configJSON), 0o600); err != nil { diff --git a/pkg/config/defaults.go b/pkg/config/defaults.go index 492b22e3a..2a3e66043 100644 --- a/pkg/config/defaults.go +++ b/pkg/config/defaults.go @@ -194,8 +194,8 @@ func DefaultConfig() *Config { // OpenAI - https://platform.openai.com/api-keys { - ModelName: "gpt-5.2", - Model: "openai/gpt-5.2", + ModelName: "gpt-5.4", + Model: "openai/gpt-5.4", APIBase: "https://api.openai.com/v1", APIKey: "", }, @@ -256,8 +256,8 @@ func DefaultConfig() *Config { APIKey: "", }, { - ModelName: "openrouter-gpt-5.2", - Model: "openrouter/openai/gpt-5.2", + ModelName: "openrouter-gpt-5.4", + Model: "openrouter/openai/gpt-5.4", APIBase: "https://openrouter.ai/api/v1", APIKey: "", }, @@ -287,6 +287,12 @@ func DefaultConfig() *Config { }, // Volcengine (火山引擎) - https://console.volcengine.com/ark + { + ModelName: "ark-code-latest", + Model: "volcengine/ark-code-latest", + APIBase: "https://ark.cn-beijing.volces.com/api/v3", + APIKey: "", + }, { ModelName: "doubao-pro", Model: "volcengine/doubao-pro-32k", @@ -311,8 +317,8 @@ func DefaultConfig() *Config { // GitHub Copilot - https://github.com/settings/tokens { - ModelName: "copilot-gpt-5.2", - Model: "github-copilot/gpt-5.2", + ModelName: "copilot-gpt-5.4", + Model: "github-copilot/gpt-5.4", APIBase: "http://localhost:4321", AuthMethod: "oauth", }, diff --git a/pkg/config/migration.go b/pkg/config/migration.go index 8e693506b..af6391651 100644 --- a/pkg/config/migration.go +++ b/pkg/config/migration.go @@ -61,7 +61,7 @@ func ConvertProvidersToModelList(cfg *Config) []ModelConfig { } return ModelConfig{ ModelName: "openai", - Model: "openai/gpt-5.2", + Model: "openai/gpt-5.4", APIKey: p.OpenAI.APIKey, APIBase: p.OpenAI.APIBase, Proxy: p.OpenAI.Proxy, @@ -335,7 +335,7 @@ func ConvertProvidersToModelList(cfg *Config) []ModelConfig { } return ModelConfig{ ModelName: "github-copilot", - Model: "github-copilot/gpt-5.2", + Model: "github-copilot/gpt-5.4", APIBase: p.GitHubCopilot.APIBase, ConnectMode: p.GitHubCopilot.ConnectMode, }, true diff --git a/pkg/config/migration_test.go b/pkg/config/migration_test.go index 807d93e49..0665ededa 100644 --- a/pkg/config/migration_test.go +++ b/pkg/config/migration_test.go @@ -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-5.2" { - t.Errorf("Model = %q, want %q", result[0].Model, "openai/gpt-5.2") + if result[0].Model != "openai/gpt-5.4" { + t.Errorf("Model = %q, want %q", result[0].Model, "openai/gpt-5.4") } if result[0].APIKey != "sk-test-key" { t.Errorf("APIKey = %q, want %q", result[0].APIKey, "sk-test-key") @@ -384,8 +384,8 @@ func TestConvertProvidersToModelList_MultipleProviders_PreservesUserModel(t *tes for _, mc := range result { switch mc.ModelName { case "openai": - if mc.Model != "openai/gpt-5.2" { - t.Errorf("OpenAI Model = %q, want %q (default)", mc.Model, "openai/gpt-5.2") + if mc.Model != "openai/gpt-5.4" { + t.Errorf("OpenAI Model = %q, want %q (default)", mc.Model, "openai/gpt-5.4") } case "deepseek": if mc.Model != "deepseek/deepseek-reasoner" { @@ -558,9 +558,9 @@ func TestConvertProvidersToModelList_NoProviderField_NoModel(t *testing.T) { // Tests for buildModelWithProtocol helper function func TestBuildModelWithProtocol_NoPrefix(t *testing.T) { - result := buildModelWithProtocol("openai", "gpt-5.2") - if result != "openai/gpt-5.2" { - t.Errorf("buildModelWithProtocol(openai, gpt-5.2) = %q, want %q", result, "openai/gpt-5.2") + result := buildModelWithProtocol("openai", "gpt-5.4") + if result != "openai/gpt-5.4" { + t.Errorf("buildModelWithProtocol(openai, gpt-5.4) = %q, want %q", result, "openai/gpt-5.4") } } diff --git a/pkg/providers/codex_cli_provider_test.go b/pkg/providers/codex_cli_provider_test.go index 414e0844d..0f66e25f4 100644 --- a/pkg/providers/codex_cli_provider_test.go +++ b/pkg/providers/codex_cli_provider_test.go @@ -490,7 +490,7 @@ echo '{"type":"turn.completed"}'` } messages := []Message{{Role: "user", Content: "test"}} - _, err := p.Chat(context.Background(), messages, nil, "gpt-5.2-codex", nil) + _, err := p.Chat(context.Background(), messages, nil, "gpt-5.3-codex", nil) if err != nil { t.Fatalf("Chat() error: %v", err) } @@ -502,7 +502,7 @@ echo '{"type":"turn.completed"}'` } args := string(argsData) - if !strings.Contains(args, "-m gpt-5.2-codex") { + if !strings.Contains(args, "-m gpt-5.3-codex") { t.Errorf("args should contain model flag, got: %s", args) } if !strings.Contains(args, "-C /tmp/test-workspace") { diff --git a/pkg/providers/codex_provider.go b/pkg/providers/codex_provider.go index 47618300a..cf5c2d876 100644 --- a/pkg/providers/codex_provider.go +++ b/pkg/providers/codex_provider.go @@ -16,7 +16,7 @@ import ( ) const ( - codexDefaultModel = "gpt-5.2" + codexDefaultModel = "gpt-5.3-codex" codexDefaultInstructions = "You are Codex, a coding assistant." ) diff --git a/pkg/providers/codex_provider_test.go b/pkg/providers/codex_provider_test.go index 4157e53e9..dd5ad2637 100644 --- a/pkg/providers/codex_provider_test.go +++ b/pkg/providers/codex_provider_test.go @@ -568,7 +568,7 @@ func TestCodexProvider_ChatRoundTrip_ModelFallbackFromUnsupported(t *testing.T) provider.client = createOpenAITestClient(server.URL, "test-token", "acc-123") messages := []Message{{Role: "user", Content: "Hello"}} - resp, err := provider.Chat(t.Context(), messages, nil, "gpt-5.2", nil) + resp, err := provider.Chat(t.Context(), messages, nil, "gpt-5.3-codex", nil) if err != nil { t.Fatalf("Chat() error: %v", err) } @@ -599,7 +599,7 @@ func TestResolveCodexModel(t *testing.T) { wantFallback: true, }, {name: "non-openai prefixed", input: "glm-4.7", wantModel: codexDefaultModel, wantFallback: true}, - {name: "openai prefix", input: "openai/gpt-5.2", wantModel: "gpt-5.2", wantFallback: false}, + {name: "openai prefix", input: "openai/gpt-5.3-codex", wantModel: "gpt-5.3-codex", wantFallback: false}, {name: "direct gpt", input: "gpt-4o", wantModel: "gpt-4o", wantFallback: false}, } diff --git a/web/backend/api/gateway_test.go b/web/backend/api/gateway_test.go index 84d784a5a..d4265776a 100644 --- a/web/backend/api/gateway_test.go +++ b/web/backend/api/gateway_test.go @@ -247,7 +247,7 @@ func TestGatewayStartReady_OAuthModelRequiresStoredCredential(t *testing.T) { } cfg.ModelList = []config.ModelConfig{{ ModelName: "openai-oauth", - Model: "openai/gpt-5.2", + Model: "openai/gpt-5.4", AuthMethod: "oauth", }} cfg.Agents.Defaults.ModelName = "openai-oauth" diff --git a/web/backend/api/models_test.go b/web/backend/api/models_test.go index 7061eb3f7..2377b5b66 100644 --- a/web/backend/api/models_test.go +++ b/web/backend/api/models_test.go @@ -62,7 +62,7 @@ func TestHandleListModels_ConfiguredStatusUsesRuntimeProbesForLocalModels(t *tes cfg.ModelList = []config.ModelConfig{ { ModelName: "openai-oauth", - Model: "openai/gpt-5.2", + Model: "openai/gpt-5.4", AuthMethod: "oauth", }, { @@ -81,8 +81,8 @@ func TestHandleListModels_ConfiguredStatusUsesRuntimeProbesForLocalModels(t *tes APIKey: "remote-key", }, { - ModelName: "copilot-gpt-5.2", - Model: "github-copilot/gpt-5.2", + ModelName: "copilot-gpt-5.4", + Model: "github-copilot/gpt-5.4", APIBase: "http://127.0.0.1:4321", AuthMethod: "oauth", }, @@ -128,7 +128,7 @@ func TestHandleListModels_ConfiguredStatusUsesRuntimeProbesForLocalModels(t *tes if !got["vllm-remote"] { t.Fatalf("remote vllm model configured = false, want true with api_key") } - if !got["copilot-gpt-5.2"] { + if !got["copilot-gpt-5.4"] { t.Fatalf("copilot model configured = false, want true when local bridge probe succeeds") } if len(openAIProbes) != 1 || openAIProbes[0] != "http://127.0.0.1:8000/v1|custom-model" { diff --git a/web/backend/api/oauth.go b/web/backend/api/oauth.go index 04cd595f2..919b47fbc 100644 --- a/web/backend/api/oauth.go +++ b/web/backend/api/oauth.go @@ -791,8 +791,8 @@ func defaultModelConfigForProvider(provider, authMethod string) config.ModelConf switch provider { case oauthProviderOpenAI: return config.ModelConfig{ - ModelName: "gpt-5.2", - Model: "openai/gpt-5.2", + ModelName: "gpt-5.4", + Model: "openai/gpt-5.4", AuthMethod: authMethod, } case oauthProviderAnthropic: diff --git a/web/backend/api/oauth_test.go b/web/backend/api/oauth_test.go index 2103e1efc..7d63abbd4 100644 --- a/web/backend/api/oauth_test.go +++ b/web/backend/api/oauth_test.go @@ -168,8 +168,8 @@ func TestOAuthLogoutClearsCredentialAndConfig(t *testing.T) { } cfg.Providers.OpenAI.AuthMethod = "oauth" cfg.ModelList = append(cfg.ModelList, config.ModelConfig{ - ModelName: "gpt-5.2", - Model: "openai/gpt-5.2", + ModelName: "gpt-5.4", + Model: "openai/gpt-5.4", AuthMethod: "oauth", }) if err = config.SaveConfig(configPath, cfg); err != nil { diff --git a/workspace/skills/summarize/SKILL.md b/workspace/skills/summarize/SKILL.md index 766ab5d0b..ca7008e7a 100644 --- a/workspace/skills/summarize/SKILL.md +++ b/workspace/skills/summarize/SKILL.md @@ -59,7 +59,7 @@ Default model is `google/gemini-3-flash-preview` if none is set. Optional config file: `~/.summarize/config.json` ```json -{ "model": "openai/gpt-5.2" } +{ "model": "openai/gpt-5.4" } ``` Optional services: