diff --git a/README.ja.md b/README.ja.md index 5845aeb7c..9705ac33a 100644 --- a/README.ja.md +++ b/README.ja.md @@ -160,8 +160,8 @@ docker compose --profile gateway up -d ### 🚀 クイックスタート(ネイティブ) > [!TIP] -> `~/.picoclaw/config.json`、`~/.picoclaw/config.yaml`、`~/.picoclaw/config.toml`、または `~/.picoclaw/config.ini` に API キーを設定してください。 -> PicoClaw は複数の設定フォーマットをサポート:**JSON**(デフォルト)、**YAML**、**TOML**、**INI** ([spf13/viper](https://github.com/spf13/viper) 経由)。 +> `~/.picoclaw/config.json`、`~/.picoclaw/config.yaml`、または `~/.picoclaw/config.toml` に API キーを設定してください。 +> PicoClaw は複数の設定フォーマットをサポート:**JSON**(デフォルト)、**YAML**、**TOML** ([spf13/viper](https://github.com/spf13/viper) 経由)。 > API キーの取得先: [OpenRouter](https://openrouter.ai/keys) (LLM) · [Zhipu](https://open.bigmodel.cn/usercenter/proj-mgmt/apikeys) (LLM) > Web 検索は **任意** です - 無料の [Brave Search API](https://brave.com/search/api) (月 2000 クエリ無料) @@ -171,13 +171,12 @@ docker compose --profile gateway up -d picoclaw onboard ``` -**2. 設定** (`~/.picoclaw/config.json`、`~/.picoclaw/config.yaml`、`~/.picoclaw/config.toml`、または `~/.picoclaw/config.ini`) +**2. 設定** (`~/.picoclaw/config.json`、`~/.picoclaw/config.yaml`、または `~/.picoclaw/config.toml`) [spf13/viper](https://github.com/spf13/viper) 経由で複数の設定フォーマットをサポート。以下のいずれかを選択: - `config.json` - JSON フォーマット(デフォルト) - `config.yaml` または `config.yml` - YAML フォーマット - `config.toml` - TOML フォーマット -- `config.ini` - INI フォーマット ```json { diff --git a/README.md b/README.md index f129c14e7..582e6cb24 100644 --- a/README.md +++ b/README.md @@ -160,7 +160,7 @@ cd picoclaw # 2. Set your API keys cp config/config.example.json config/config.json -vim config/config.json # Set DISCORD_BOT_TOKEN, API keys, etc. (or use config.yaml/config.toml/config.ini) +vim config/config.json # Set DISCORD_BOT_TOKEN, API keys, etc. (or use config.yaml/config.toml) # 3. Build & Start docker compose --profile gateway up -d @@ -192,8 +192,8 @@ docker compose --profile gateway up -d ### 🚀 Quick Start > [!TIP] -> Set your API key in `~/.picoclaw/config.json`, `~/.picoclaw/config.yaml`, `~/.picoclaw/config.toml`, or `~/.picoclaw/config.ini`. -> PicoClaw supports multiple configuration formats: **JSON** (default), **YAML**, **TOML**, **INI** via [spf13/viper](https://github.com/spf13/viper). +> Set your API key in `~/.picoclaw/config.json`, `~/.picoclaw/config.yaml`, or `~/.picoclaw/config.toml`. +> PicoClaw supports multiple configuration formats: **JSON** (default), **YAML**, **TOML** via [spf13/viper](https://github.com/spf13/viper). > 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 [Brave Search API](https://brave.com/search/api) (2000 free queries/month) or use built-in auto fallback. @@ -203,13 +203,12 @@ docker compose --profile gateway up -d picoclaw onboard ``` -# 2. Configure (`~/.picoclaw/config.json`, `~/.picoclaw/config.yaml`, `~/.picoclaw/config.toml`, or `~/.picoclaw/config.ini`) +# 2. Configure (`~/.picoclaw/config.json`, `~/.picoclaw/config.yaml`, or `~/.picoclaw/config.toml`) PicoClaw supports multiple configuration formats via [spf13/viper](https://github.com/spf13/viper). Choose any one: - `config.json` - JSON format (default, most common) - `config.yaml` or `config.yml` - YAML format - `config.toml` - TOML format -- `config.ini` - INI format ```json { diff --git a/README.pt-br.md b/README.pt-br.md index 26f78c3d0..a33c815c1 100644 --- a/README.pt-br.md +++ b/README.pt-br.md @@ -167,7 +167,7 @@ cd picoclaw # 2. Configure suas API keys cp config/config.example.json config/config.json -vim config/config.json # Configure DISCORD_BOT_TOKEN, API keys, etc. (ou use config.yaml/config.yaml/config.toml/config.ini) +vim config/config.json # Configure DISCORD_BOT_TOKEN, API keys, etc. (ou use config.yaml/config.toml) # 3. Build & Iniciar docker compose --profile gateway up -d @@ -199,8 +199,8 @@ docker compose --profile gateway up -d ### 🚀 Início Rápido > [!TIP] -> Configure sua API key em `~/.picoclaw/config.json`, `~/.picoclaw/config.yaml`, `~/.picoclaw/config.toml` ou `~/.picoclaw/config.ini`. -> PicoClaw suporta múltiplos formatos de configuração: **JSON** (padrão), **YAML**, **TOML**, **INI** via [spf13/viper](https://github.com/spf13/viper). +> Configure sua API key em `~/.picoclaw/config.json`, `~/.picoclaw/config.yaml` ou `~/.picoclaw/config.toml`. +> PicoClaw suporta múltiplos formatos de configuração: **JSON** (padrão), **YAML**, **TOML** via [spf13/viper](https://github.com/spf13/viper). > 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. @@ -210,13 +210,12 @@ docker compose --profile gateway up -d picoclaw onboard ``` -**2. Configurar** (`~/.picoclaw/config.json`, `~/.picoclaw/config.yaml`, `~/.picoclaw/config.toml` ou `~/.picoclaw/config.ini`) +**2. Configurar** (`~/.picoclaw/config.json`, `~/.picoclaw/config.yaml` ou `~/.picoclaw/config.toml`) PicoClaw suporta múltiplos formatos via [spf13/viper](https://github.com/spf13/viper). Escolha qualquer um: - `config.json` - Formato JSON (padrão) - `config.yaml` ou `config.yml` - Formato YAML - `config.toml` - Formato TOML -- `config.ini` - Formato INI ```json { diff --git a/README.vi.md b/README.vi.md index a6bf4d596..7ea2a87b4 100644 --- a/README.vi.md +++ b/README.vi.md @@ -147,7 +147,7 @@ cd picoclaw # 2. Thiết lập API key cp config/config.example.json config/config.json -vim config/config.json # Thiết lập DISCORD_BOT_TOKEN, API keys, v.v. (hoặc dùng config.yaml/config.toml/config.ini) +vim config/config.json # Thiết lập DISCORD_BOT_TOKEN, API keys, v.v. (hoặc dùng config.yaml/config.toml) # 3. Build & Khởi động docker compose --profile gateway up -d @@ -180,11 +180,11 @@ docker compose --profile gateway up -d ### Cấu hình -Bạn có thể cấu hình PicoClaw bằng cách chỉnh sửa file cấu hình ở các định dạng sau: `config.json`, `config.yaml`, `config.toml`, hoặc `config.ini`. Tất cả các định dạng này đều được hỗ trợ. +Bạn có thể cấu hình PicoClaw bằng cách chỉnh sửa file cấu hình ở các định dạng sau: `config.json`, `config.yaml`, hoặc `config.toml`. > [!TIP] -> Thiết lập API key trong `~/.picoclaw/config.json`, `~/.picoclaw/config.yaml`, `~/.picoclaw/config.toml` hoặc `~/.picoclaw/config.ini`. -> PicoClaw hỗ trợ nhiều định dạng cấu hình: **JSON** (mặc định), **YAML**, **TOML**, **INI** via [spf13/viper](https://github.com/spf13/viper). +> Thiết lập API key trong `~/.picoclaw/config.json`, `~/.picoclaw/config.yaml` hoặc `~/.picoclaw/config.toml`. +> PicoClaw hỗ trợ nhiều định dạng cấu hình: **JSON** (mặc định), **YAML**, **TOML** via [spf13/viper](https://github.com/spf13/viper). > 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. @@ -194,13 +194,12 @@ Bạn có thể cấu hình PicoClaw bằng cách chỉnh sửa file cấu hình picoclaw onboard ``` -**2. Cấu hình** (`~/.picoclaw/config.json`, `~/.picoclaw/config.yaml`, `~/.picoclaw/config.toml` hoặc `~/.picoclaw/config.ini`) +**2. Cấu hình** (`~/.picoclaw/config.json`, `~/.picoclaw/config.yaml` hoặc `~/.picoclaw/config.toml`) PicoClaw hỗ trợ nhiều định dạng via [spf13/viper](https://github.com/spf13/viper). Chọn bất kỳ một: - `config.json` - Định dạng JSON (mặc định) - `config.yaml` hoặc `config.yml` - Định dạng YAML - `config.toml` - Định dạng TOML -- `config.ini` - Định dạng INI ```json { diff --git a/README.zh.md b/README.zh.md index 770a4dfba..5d3af50ca 100644 --- a/README.zh.md +++ b/README.zh.md @@ -165,7 +165,7 @@ cd picoclaw # 2. 设置 API Key cp config/config.example.json config/config.json -vim config/config.json # 或使用 config.yaml/config.toml/config.ini 设置 DISCORD_BOT_TOKEN, API keys 等 +vim config/config.json # 或使用 config.yaml/config.toml 设置 DISCORD_BOT_TOKEN, API keys 等 # 3. 构建并启动 docker compose --profile gateway up -d @@ -200,8 +200,8 @@ docker compose --profile gateway up -d ### 🚀 快速开始 > [!TIP] -> 在 `~/.picoclaw/config.json`、`~/.picoclaw/config.yaml`、`~/.picoclaw/config.toml` 或 `~/.picoclaw/config.ini` 中设置您的 API Key。 -> PicoClaw 支持多种配置格式:**JSON**(默认)、**YAML**、**TOML**、**INI**,通过 [spf13/viper](https://github.com/spf13/viper) 驱动。 +> 在 `~/.picoclaw/config.json`、`~/.picoclaw/config.yaml` 或 `~/.picoclaw/config.toml` 中设置您的 API Key。 +> PicoClaw 支持多种配置格式:**JSON**(默认)、**YAML**、**TOML**,通过 [spf13/viper](https://github.com/spf13/viper) 驱动。 > 获取 API Key: [OpenRouter](https://openrouter.ai/keys) (LLM) · [Zhipu (智谱)](https://open.bigmodel.cn/usercenter/proj-mgmt/apikeys) (LLM) > 网络搜索是 **可选的** - 获取免费的 [Brave Search API](https://brave.com/search/api) (每月 2000 次免费查询) @@ -212,13 +212,12 @@ picoclaw onboard ``` -**2. 配置 (Configure)** (`~/.picoclaw/config.json`、`~/.picoclaw/config.yaml`、`~/.picoclaw/config.toml` 或 `~/.picoclaw/config.ini`) +**2. 配置 (Configure)** (`~/.picoclaw/config.json`、`~/.picoclaw/config.yaml` 或 `~/.picoclaw/config.toml`) 通过 [spf13/viper](https://github.com/spf13/viper) 支持多种配置格式,选择其中任意一种即可: - `config.json` - JSON 格式(默认) - `config.yaml` 或 `config.yml` - YAML 格式 - `config.toml` - TOML 格式 -- `config.ini` - INI 格式 ```json { @@ -748,4 +747,4 @@ Discord: [https://discord.gg/V4sAZ9XWpN](https://discord.gg/V4sAZ9XWpN) | **OpenRouter** | 200K tokens/月 | 多模型聚合 (Claude, GPT-4 等) | | **智谱 (Zhipu)** | 200K tokens/月 | 最适合中国用户 | | **Brave Search** | 2000 次查询/月 | 网络搜索功能 | -| **Groq** | 提供免费层级 | 极速推理 (Llama, Mixtral) | \ No newline at end of file +| **Groq** | 提供免费层级 | 极速推理 (Llama, Mixtral) | diff --git a/config/config.example.ini b/config/config.example.ini deleted file mode 100644 index 6fcf8b8b9..000000000 --- a/config/config.example.ini +++ /dev/null @@ -1,129 +0,0 @@ -; PicoClaw Configuration Example - INI Format -; This is an alternative to config.json for users who prefer INI format - -[agents.defaults] -workspace=~/.picoclaw/workspace -restrict_to_workspace=true -model=glm-4.7 -max_tokens=8192 -temperature=0.7 -max_tool_iterations=20 - -[channels.telegram] -enabled=false -token=YOUR_TELEGRAM_BOT_TOKEN -proxy= -allow_from=YOUR_USER_ID - -[channels.discord] -enabled=false -token=YOUR_DISCORD_BOT_TOKEN -allow_from= - -[channels.slack] -enabled=false -token=YOUR_SLACK_BOT_TOKEN -allow_from= - -[channels.feishu] -enabled=false -token=YOUR_FEISHU_BOT_TOKEN -secret=YOUR_FEISHU_SECRET -allow_from= - -[channels.dingtalk] -enabled=false -token=YOUR_DINGTALK_BOT_TOKEN -secret=YOUR_DINGTALK_SECRET -allow_from= - -[channels.qq] -enabled=false -account=YOUR_QQ_ACCOUNT -token=YOUR_QQ_BOT_TOKEN -allow_from= - -[channels.whatsapp] -enabled=false -phone_number=YOUR_PHONE_NUMBER -allow_from= - -[channels.line] -enabled=false -token=YOUR_LINE_CHANNEL_ACCESS_TOKEN -secret=YOUR_LINE_CHANNEL_SECRET -allow_from= - -[channels.onebot] -enabled=false -ws_url= -allow_from= - -[channels.maixcam] -enabled=false -host=0.0.0.0 -port=18790 -allow_from= - -[providers.anthropic] -enabled=false -api_key=YOUR_ANTHROPIC_API_KEY -api_base=https://api.anthropic.com - -[providers.openai] -enabled=false -api_key=YOUR_OPENAI_API_KEY -api_base=https://api.openai.com/v1 - -[providers.openrouter] -enabled=false -api_key=YOUR_OPENROUTER_API_KEY -api_base=https://openrouter.ai/api/v1 - -[providers.zhipu] -enabled=false -api_key=YOUR_ZHIPU_API_KEY -api_base=https://open.bigmodel.cn/api/paas/v4 - -[providers.gemini] -enabled=false -api_key=YOUR_GEMINI_API_KEY -api_base=https://generativelanguage.googleapis.com/v1beta/openai/ - -[providers.groq] -enabled=false -api_key=YOUR_GROQ_API_KEY -api_base=https://api.groq.com/openai/v1 - -[providers.vllm] -enabled=false -api_key=YOUR_VLLM_API_KEY -api_base=http://localhost:8000/v1 - -[providers.shengsuan_yun] -enabled=false -api_key=YOUR_SHENGSUAN_YUN_API_KEY -api_base=https://api.shengsuan.cloud/v1 - -[gateway] -enabled=true -host=0.0.0.0 -port=8080 -cors_enabled=true -cors_origins=* - -[tools] -enabled=true - -[heartbeat] -enabled=true -interval=60 -timeout=5 - -[devices] -enabled=true - -[session] -storage=memory -; For persistent storage, set to "sqlite" and provide database_path -; database_path=~/.picoclaw/session.db diff --git a/pkg/config/config.go b/pkg/config/config.go index 817ebff11..808991d5c 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -64,7 +64,6 @@ var configFileNames = []string{ "config.yaml", "config.yml", "config.toml", - "config.ini", } type AgentsConfig struct { @@ -534,8 +533,6 @@ func SaveConfig(path string, cfg *Config) error { configType = "yaml" case ".toml": configType = "toml" - case ".ini": - configType = "ini" case ".json", "": configType = "json" if ext == "" { diff --git a/pkg/config/config_test.go b/pkg/config/config_test.go index 712d8f678..07ad97836 100644 --- a/pkg/config/config_test.go +++ b/pkg/config/config_test.go @@ -300,6 +300,85 @@ func TestSaveConfig_FilePermissions(t *testing.T) { } } +func TestSaveConfig_AllSupportedFormats(t *testing.T) { + tests := []struct { + name string + fileName string + expectedOut string + }{ + { + name: "json", + fileName: "config.json", + expectedOut: "config.json", + }, + { + name: "yaml", + fileName: "config.yaml", + expectedOut: "config.yaml", + }, + { + name: "yml", + fileName: "config.yml", + expectedOut: "config.yml", + }, + { + name: "toml", + fileName: "config.toml", + expectedOut: "config.toml", + }, + { + name: "no_extension_defaults_to_json", + fileName: "config", + expectedOut: "config.json", + }, + } + + for _, tc := range tests { + tc := tc + t.Run(tc.name, func(t *testing.T) { + tmpDir := t.TempDir() + targetPath := filepath.Join(tmpDir, tc.fileName) + outPath := filepath.Join(tmpDir, tc.expectedOut) + + cfg := DefaultConfig() + cfg.Agents.Defaults.Model = "unit-test-model" + cfg.Agents.Defaults.MaxTokens = 1234 + cfg.Gateway.Host = "127.0.0.1" + cfg.Gateway.Port = 19090 + cfg.Providers.Zhipu.APIKey = "test-zhipu-key" + + if err := SaveConfig(targetPath, cfg); err != nil { + t.Fatalf("SaveConfig(%q) failed: %v", targetPath, err) + } + + if _, err := os.Stat(outPath); err != nil { + t.Fatalf("expected output file %q to exist: %v", outPath, err) + } + + loaded, err := LoadConfig(outPath) + if err != nil { + t.Fatalf("LoadConfig(%q) failed: %v", outPath, err) + } + + if loaded.Agents.Defaults.Model != "unit-test-model" { + t.Errorf("Model = %q, want %q", loaded.Agents.Defaults.Model, "unit-test-model") + } + if loaded.Agents.Defaults.MaxTokens != 1234 { + t.Errorf("MaxTokens = %d, want %d", loaded.Agents.Defaults.MaxTokens, 1234) + } + if loaded.Gateway.Host != "127.0.0.1" { + t.Errorf("Gateway.Host = %q, want %q", loaded.Gateway.Host, "127.0.0.1") + } + if loaded.Gateway.Port != 19090 { + t.Errorf("Gateway.Port = %d, want %d", loaded.Gateway.Port, 19090) + } + if loaded.Providers.Zhipu.APIKey != "test-zhipu-key" { + t.Errorf("Providers.Zhipu.APIKey = %q, want %q", loaded.Providers.Zhipu.APIKey, "test-zhipu-key") + } + }) + } +} + // TestConfig_Complete verifies all config fields are set func TestConfig_Complete(t *testing.T) { cfg := DefaultConfig()