picoclaw/pkg/config/defaults.go

577 lines
14 KiB
Go
Raw Normal View History

// PicoClaw - Ultra-lightweight personal AI agent
// License: MIT
//
// Copyright (c) 2026 PicoClaw contributors
package config
import (
"encoding/json"
"path/filepath"
"github.com/sipeed/picoclaw/pkg"
)
// DefaultConfig returns the default configuration for PicoClaw.
func DefaultConfig() *Config {
workspacePath := filepath.Join(GetHome(), pkg.WorkspaceName)
return &Config{
Version: CurrentVersion,
// Isolation is opt-in so existing installations keep their current behavior
// until the user explicitly enables subprocess sandboxing.
Isolation: IsolationConfig{
Enabled: false,
},
Agents: AgentsConfig{
Defaults: AgentDefaults{
Workspace: workspacePath,
RestrictToWorkspace: true,
Provider: "",
MaxTokens: 32768,
Temperature: nil, // nil means use provider default
MaxToolIterations: 50,
SummarizeMessageThreshold: 20,
SummarizeTokenPercent: 75,
SteeringMode: "one-at-a-time",
ToolFeedback: ToolFeedbackConfig{
Enabled: false,
MaxArgsLength: 300,
SeparateMessages: false,
PrettyPrint: true,
DisableEscapeHTML: true,
},
SplitOnMarker: false,
},
},
Session: SessionConfig{
Dimensions: []string{"chat"},
},
Channels: defaultChannels(),
Hooks: HooksConfig{
Enabled: true,
Defaults: HookDefaultsConfig{
ObserverTimeoutMS: 500,
InterceptorTimeoutMS: 5000,
ApprovalTimeoutMS: 60000,
},
},
ModelList: []*ModelConfig{
// ============================================
// Add your API key to the model you want to use
// ============================================
// Zhipu AI (智谱) - https://open.bigmodel.cn/usercenter/apikeys
{
ModelName: "glm-4.7",
Provider: "zhipu",
Model: "glm-4.7",
APIBase: "https://open.bigmodel.cn/api/paas/v4",
},
// OpenAI - https://platform.openai.com/api-keys
{
ModelName: "gpt-5.4",
Provider: "openai",
Model: "gpt-5.4",
APIBase: "https://api.openai.com/v1",
},
// Anthropic Claude - https://console.anthropic.com/settings/keys
{
ModelName: "claude-sonnet-4.6",
Provider: "anthropic",
Model: "claude-sonnet-4.6",
APIBase: "https://api.anthropic.com/v1",
},
// DeepSeek - https://platform.deepseek.com/
{
ModelName: "deepseek-chat",
Provider: "deepseek",
Model: "deepseek-chat",
APIBase: "https://api.deepseek.com/v1",
},
// Venice AI - https://venice.ai
{
ModelName: "venice-uncensored",
Provider: "venice",
Model: "venice-uncensored",
APIBase: "https://api.venice.ai/api/v1",
},
// Google Gemini - https://ai.google.dev/
{
ModelName: "gemini-2.0-flash",
Provider: "gemini",
Model: "gemini-2.0-flash-exp",
APIBase: "https://generativelanguage.googleapis.com/v1beta",
},
// Qwen (通义千问) - https://dashscope.console.aliyun.com/apiKey
{
ModelName: "qwen-plus",
Provider: "qwen",
Model: "qwen-plus",
APIBase: "https://dashscope.aliyuncs.com/compatible-mode/v1",
},
// Moonshot (月之暗面) - https://platform.moonshot.cn/console/api-keys
{
ModelName: "moonshot-v1-8k",
Provider: "moonshot",
Model: "moonshot-v1-8k",
APIBase: "https://api.moonshot.cn/v1",
},
// Groq - https://console.groq.com/keys
{
ModelName: "llama-3.3-70b",
Provider: "groq",
Model: "llama-3.3-70b-versatile",
APIBase: "https://api.groq.com/openai/v1",
},
// OpenRouter (100+ models) - https://openrouter.ai/keys
{
ModelName: "openrouter-auto",
Provider: "openrouter",
Model: "auto",
APIBase: "https://openrouter.ai/api/v1",
},
{
ModelName: "openrouter-gpt-5.4",
Provider: "openrouter",
Model: "openai/gpt-5.4",
APIBase: "https://openrouter.ai/api/v1",
},
// NVIDIA - https://build.nvidia.com/
{
ModelName: "nemotron-4-340b",
Provider: "nvidia",
Model: "nemotron-4-340b-instruct",
APIBase: "https://integrate.api.nvidia.com/v1",
},
// Cerebras - https://inference.cerebras.ai/
{
ModelName: "cerebras-llama-3.3-70b",
Provider: "cerebras",
Model: "llama-3.3-70b",
APIBase: "https://api.cerebras.ai/v1",
},
2026-03-04 17:19:03 +00:00
// Vivgrid - https://vivgrid.com
{
ModelName: "vivgrid-auto",
Provider: "vivgrid",
Model: "auto",
2026-03-04 17:19:03 +00:00
APIBase: "https://api.vivgrid.com/v1",
},
// Volcengine (火山引擎) - https://console.volcengine.com/ark
{
ModelName: "ark-code-latest",
Provider: "volcengine",
Model: "ark-code-latest",
APIBase: "https://ark.cn-beijing.volces.com/api/v3",
},
{
ModelName: "doubao-pro",
Provider: "volcengine",
Model: "doubao-pro-32k",
APIBase: "https://ark.cn-beijing.volces.com/api/v3",
},
// ShengsuanYun (神算云)
{
ModelName: "deepseek-v3",
Provider: "shengsuanyun",
Model: "deepseek-v3",
APIBase: "https://api.shengsuanyun.com/v1",
},
// Antigravity (Google Cloud Code Assist) - OAuth only
{
ModelName: "gemini-flash",
Provider: "antigravity",
Model: "gemini-3-flash",
AuthMethod: "oauth",
},
// GitHub Copilot - https://github.com/settings/tokens
{
ModelName: "copilot-gpt-5.4",
Provider: "github-copilot",
Model: "gpt-5.4",
APIBase: "http://localhost:4321",
AuthMethod: "oauth",
},
// Ollama (local) - https://ollama.com
{
ModelName: "llama3",
Provider: "ollama",
Model: "llama3",
APIBase: "http://localhost:11434/v1",
},
// Mistral AI - https://console.mistral.ai/api-keys
{
ModelName: "mistral-small",
Provider: "mistral",
Model: "mistral-small-latest",
APIBase: "https://api.mistral.ai/v1",
},
// Avian - https://avian.io
{
ModelName: "deepseek-v3.2",
Provider: "avian",
Model: "deepseek/deepseek-v3.2",
APIBase: "https://api.avian.io/v1",
},
{
ModelName: "kimi-k2.5",
Provider: "avian",
Model: "moonshotai/kimi-k2.5",
APIBase: "https://api.avian.io/v1",
},
2026-03-09 10:43:58 +00:00
// Minimax - https://api.minimaxi.com/
{
ModelName: "MiniMax-M2.5",
Provider: "minimax",
Model: "MiniMax-M2.5",
2026-03-09 10:43:58 +00:00
APIBase: "https://api.minimaxi.com/v1",
ExtraBody: map[string]any{"reasoning_split": true},
2026-03-09 10:43:58 +00:00
},
// LongCat - https://longcat.chat/platform
{
ModelName: "LongCat-Flash-Thinking",
Provider: "longcat",
Model: "LongCat-Flash-Thinking",
APIBase: "https://api.longcat.chat/openai",
},
// ModelScope (魔搭社区) - https://modelscope.cn/my/tokens
{
ModelName: "modelscope-qwen",
Provider: "modelscope",
Model: "Qwen/Qwen3-235B-A22B-Instruct-2507",
APIBase: "https://api-inference.modelscope.cn/v1",
},
// VLLM (local) - http://localhost:8000
{
ModelName: "local-model",
Provider: "vllm",
Model: "custom-model",
APIBase: "http://localhost:8000/v1",
},
// LM Studio (local) - http://localhost:1234
{
ModelName: "lmstudio-local",
Provider: "lmstudio",
Model: "openai/gpt-oss-20b",
APIBase: "http://localhost:1234/v1",
},
// Azure OpenAI - https://portal.azure.com
// model_name is a user-friendly alias; the model field's path after "azure/" is your deployment name
{
ModelName: "azure-gpt5",
Provider: "azure",
Model: "my-gpt5-deployment",
APIBase: "https://your-resource.openai.azure.com",
},
},
Gateway: GatewayConfig{
Host: "localhost",
Port: 18790,
HotReload: false,
LogLevel: DefaultGatewayLogLevel,
},
Tools: ToolsConfig{
FilterSensitiveData: true,
FilterMinLength: 8,
MediaCleanup: MediaCleanupConfig{
ToolConfig: ToolConfig{
Enabled: true,
},
MaxAge: 30,
Interval: 5,
},
Web: WebToolsConfig{
ToolConfig: ToolConfig{
Enabled: true,
},
Provider: "auto",
PreferNative: true,
2026-02-28 12:34:33 +00:00
Proxy: "",
FetchLimitBytes: 10 * 1024 * 1024, // 10MB by default
Format: "plaintext",
Brave: BraveConfig{
Enabled: false,
MaxResults: 5,
},
Tavily: TavilyConfig{
Enabled: false,
MaxResults: 5,
},
Sogou: SogouConfig{
Enabled: true,
MaxResults: 5,
},
DuckDuckGo: DuckDuckGoConfig{
Enabled: false,
MaxResults: 5,
},
Perplexity: PerplexityConfig{
Enabled: false,
MaxResults: 5,
},
SearXNG: SearXNGConfig{
Enabled: false,
BaseURL: "",
MaxResults: 5,
},
GLMSearch: GLMSearchConfig{
Enabled: false,
BaseURL: "https://open.bigmodel.cn/api/paas/v4/web_search",
SearchEngine: "search_std",
MaxResults: 5,
},
BaiduSearch: BaiduSearchConfig{
Enabled: false,
BaseURL: "https://qianfan.baidubce.com/v2/ai_search/web_search",
MaxResults: 10,
},
},
Cron: CronToolsConfig{
ToolConfig: ToolConfig{
Enabled: true,
},
ExecTimeoutMinutes: 5,
AllowCommand: true,
},
Exec: ExecConfig{
ToolConfig: ToolConfig{
Enabled: true,
},
EnableDenyPatterns: true,
AllowRemote: true,
TimeoutSeconds: 60,
},
Skills: SkillsToolsConfig{
ToolConfig: ToolConfig{
Enabled: true,
},
Registries: SkillsRegistriesConfig{
refactor skills registries and add GitHub-backed skill discovery (#2442) * refactor skills registries and add GitHub-backed skill discovery * fix ci * fix command error * fix default skills install registry behavior * fix github registry URL parsing and versioned skill links * fix skills registry config compatibility and URL installs * * fix lint * fix deprecated github base url compatibility * fix skills registry yaml and github default branch handling * fix github skills registry fallback and install metadata * fix cli skills install origin metadata * fix clawhub registry env compatibility * fix skills registry config merge compatibility * fix skill install metadata consistency and onboard template copy * fix yaml overrides for default skills registries * fix install_skill registry metadata normalization * fix github skill URL parsing for slash branch names * fix skills registry install/search validation and github URLs * fix github skill URL host validation * fix install_skill validation for invalid registry archives * fix redundant skills registry names in saved config * fix github blob skill URL installs and metadata links * fix github registry URL scheme validation * fix v0 skills migration preserving github registry defaults * fix github blob skill install directory resolution * fix install_skill rollback on origin metadata write failure * fix github skill URL validation and registry JSON merging * fix github registry target resolution and metadata links * fix install_skill force reinstall rollback * fix skills config compatibility and legacy security overlays * fix ci
2026-04-14 07:14:16 +00:00
&SkillRegistryConfig{
Name: "clawhub",
Enabled: true,
BaseURL: "https://clawhub.ai",
refactor skills registries and add GitHub-backed skill discovery (#2442) * refactor skills registries and add GitHub-backed skill discovery * fix ci * fix command error * fix default skills install registry behavior * fix github registry URL parsing and versioned skill links * fix skills registry config compatibility and URL installs * * fix lint * fix deprecated github base url compatibility * fix skills registry yaml and github default branch handling * fix github skills registry fallback and install metadata * fix cli skills install origin metadata * fix clawhub registry env compatibility * fix skills registry config merge compatibility * fix skill install metadata consistency and onboard template copy * fix yaml overrides for default skills registries * fix install_skill registry metadata normalization * fix github skill URL parsing for slash branch names * fix skills registry install/search validation and github URLs * fix github skill URL host validation * fix install_skill validation for invalid registry archives * fix redundant skills registry names in saved config * fix github blob skill URL installs and metadata links * fix github registry URL scheme validation * fix v0 skills migration preserving github registry defaults * fix github blob skill install directory resolution * fix install_skill rollback on origin metadata write failure * fix github skill URL validation and registry JSON merging * fix github registry target resolution and metadata links * fix install_skill force reinstall rollback * fix skills config compatibility and legacy security overlays * fix ci
2026-04-14 07:14:16 +00:00
Param: map[string]any{},
},
&SkillRegistryConfig{
Name: "github",
Enabled: true,
BaseURL: "https://github.com",
Param: map[string]any{},
},
},
MaxConcurrentSearches: 2,
SearchCache: SearchCacheConfig{
MaxSize: 50,
TTLSeconds: 300,
},
},
feat(feishu,tools): add outbound media delivery via send_file tool (#1156) * feat(feishu): implement SendMedia and add send_file tool Add outbound media support for the Feishu channel so the agent can send images and files to users via the MediaStore pipeline. Feishu channel: - SendMedia dispatches media parts as image or file uploads - sendImage uploads via Image.Create then sends image message - sendFile uploads via File.Create then sends file message - feishuFileType maps extensions to Feishu file_type values send_file tool: - New tool lets the LLM send a local file to the current chat - Validates path, registers file in MediaStore, returns media ref - Agent loop wires tool registration, MediaStore propagation, and context updates Tested on Radxa Cubie A7A (arm64) with Feishu websocket channel. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(agent): publish outbound media regardless of SendResponse flag The SendResponse flag controls whether the agent loop publishes the final text response (callers that publish it themselves set this to false). However, the media publish path was also gated behind this flag, which meant tool-produced media was silently dropped for normal channel messages. Media should be published immediately when a tool returns media refs, independent of how the text response is delivered. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(tools): use magic-bytes MIME detection and add file size limit to send_file - Replace hardcoded extension-to-MIME map with h2non/filetype (magic bytes) + mime.TypeByExtension fallback, consistent with the vision pipeline in resolveMediaRefs - Add configurable max file size check (defaults to config.DefaultMaxMediaSize, 20 MB) to prevent oversized uploads - Add tests for magic-bytes detection, extension fallback, size limit, and default max size Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor(agent): add ForEachTool to AgentRegistry for cross-agent tool lookup Extract the pattern of iterating agents to find a named tool into AgentRegistry.ForEachTool, simplifying SetMediaStore propagation. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(agent,tools): adapt send_file to ctx-based channel injection after upstream refactor Replace ContextualTool interface (removed upstream) with direct ctx reading in SendFileTool.Execute, using ToolChannel/ToolChatID helpers. Remove updateToolContexts which is no longer needed since ExecuteWithContext already injects channel/chatID into ctx for all tools. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat(tools): support toggling send_file tool via config Add SendFileConfig with Enabled field to ToolsConfig, defaulting to true. Wrap send_file tool registration in loop.go with the config check, consistent with the pattern used by other tools. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 11:42:52 +00:00
SendFile: ToolConfig{
Enabled: true,
},
SendTTS: ToolConfig{
Enabled: false,
},
MCP: MCPConfig{
ToolConfig: ToolConfig{
Enabled: false,
},
Discovery: ToolDiscoveryConfig{
Enabled: false,
TTL: 5,
MaxSearchResults: 5,
UseBM25: true,
UseRegex: false,
},
MaxInlineTextChars: DefaultMCPMaxInlineTextChars,
Servers: map[string]MCPServerConfig{},
},
AppendFile: ToolConfig{
Enabled: true,
},
EditFile: ToolConfig{
Enabled: true,
},
FindSkills: ToolConfig{
Enabled: true,
},
I2C: ToolConfig{
Enabled: false, // Hardware tool - Linux only
},
InstallSkill: ToolConfig{
Enabled: true,
},
ListDir: ToolConfig{
Enabled: true,
},
Message: ToolConfig{
Enabled: true,
},
2026-03-09 08:32:21 +00:00
ReadFile: ReadFileToolConfig{
Enabled: true,
Mode: ReadFileModeBytes,
2026-03-09 08:32:21 +00:00
MaxReadFileSize: 64 * 1024, // 64KB
},
Spawn: ToolConfig{
Enabled: true,
},
feat(tools): add SpawnStatusTool for reporting subagent statuses (#1540) * feat(tools): add SpawnStatusTool for reporting subagent statuses * feat(tools): enhance SpawnStatusTool to restrict task visibility by conversation context * feat(tests): add Unicode result truncation and channel filtering tests for SpawnStatusTool * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * feat(tools): enhance SpawnStatusTool with task ID validation and sorting by creation timestamp * feat(tools): update SpawnStatusTool description and parameter documentation for clarity * refactor(tests): improve comments for clarity in ChannelFiltering test case * fix(tools): update no subagents message for clarity and remove unnecessary locking in runTask * fix(tools): improve description clarity for SpawnStatusTool regarding task context * feat(tools): add spawn_status tool configuration and registration * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * fix(agent): improve subagent management for spawn and spawn_status tools * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * fix(tests): update ResultTruncation_Unicode test to use valid CJK character --------- Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> Co-authored-by: lxowalle <83055338+lxowalle@users.noreply.github.com>
2026-03-17 06:41:43 +00:00
SpawnStatus: ToolConfig{
Enabled: false,
},
SPI: ToolConfig{
Enabled: false, // Hardware tool - Linux only
},
Subagent: ToolConfig{
Enabled: true,
},
WebFetch: ToolConfig{
Enabled: true,
},
WriteFile: ToolConfig{
Enabled: true,
},
},
Heartbeat: HeartbeatConfig{
Enabled: true,
Interval: 30,
},
Devices: DevicesConfig{
Enabled: false,
MonitorUSB: true,
},
Voice: VoiceConfig{
ModelName: "",
TTSModelName: "",
EchoTranscription: false,
ElevenLabsAPIKey: "",
},
BuildInfo: BuildInfo{
Version: Version,
GitCommit: GitCommit,
BuildTime: BuildTime,
GoVersion: GoVersion,
},
}
}
func defaultChannels() ChannelsConfig {
defs := map[string]any{
"whatsapp": map[string]any{
"settings": map[string]any{
"bridge_url": "ws://localhost:3001",
},
},
"telegram": map[string]any{
"typing": map[string]any{"enabled": true},
"placeholder": map[string]any{"enabled": true, "text": []string{"Thinking... 💭"}},
"settings": map[string]any{
"streaming": map[string]any{"enabled": true, "throttle_seconds": 3, "min_growth_chars": 200},
"use_markdown_v2": false,
},
},
"feishu": map[string]any{},
"discord": map[string]any{},
"maixcam": map[string]any{
"settings": map[string]any{"host": "0.0.0.0", "port": 18790},
},
"qq": map[string]any{
"settings": map[string]any{"max_message_length": 2000},
},
"dingtalk": map[string]any{},
"slack": map[string]any{},
"matrix": map[string]any{
"group_trigger": map[string]any{"mention_only": true},
"placeholder": map[string]any{"enabled": true, "text": []string{"Thinking... 💭"}},
"settings": map[string]any{
"homeserver": "https://matrix.org",
"join_on_invite": true,
},
},
"line": map[string]any{
"group_trigger": map[string]any{"mention_only": true},
"settings": map[string]any{
"webhook_host": "0.0.0.0",
"webhook_port": 18791,
"webhook_path": "/webhook/line",
},
},
"onebot": map[string]any{
"settings": map[string]any{
"ws_url": "ws://127.0.0.1:3001",
"reconnect_interval": 5,
},
},
"wecom": map[string]any{
"settings": map[string]any{
"websocket_url": "wss://openws.work.weixin.qq.com",
"send_thinking_message": true,
},
},
"weixin": map[string]any{
"settings": map[string]any{
"base_url": "https://ilinkai.weixin.qq.com/",
"cdn_base_url": "https://novac2c.cdn.weixin.qq.com/c2c",
},
},
"pico": map[string]any{
"settings": map[string]any{
"ping_interval": 30,
"read_timeout": 60,
"write_timeout": 10,
"max_connections": 100,
},
},
"irc": map[string]any{
"settings": map[string]any{
"server": "",
"tls": true,
"nick": "picoclaw",
"channels": []string{},
},
},
}
channels := make(ChannelsConfig, len(defs))
for name, def := range defs {
data, err := json.Marshal(def)
if err != nil {
continue
}
bc := &Channel{}
if err := json.Unmarshal(data, bc); err != nil {
continue
}
bc.SetName(name)
if bc.Type == "" {
bc.Type = name
}
channels[name] = bc
}
return channels
}