2026-02-04 11:06:13 +00:00
|
|
|
{
|
2026-05-04 08:25:16 +00:00
|
|
|
"version": 3,
|
2026-02-04 11:06:13 +00:00
|
|
|
"agents": {
|
|
|
|
|
"defaults": {
|
|
|
|
|
"workspace": "~/.picoclaw/workspace",
|
2026-02-11 14:18:13 +00:00
|
|
|
"restrict_to_workspace": true,
|
2026-03-12 08:10:29 +00:00
|
|
|
"model_name": "gpt-5.4",
|
2026-02-04 11:06:13 +00:00
|
|
|
"max_tokens": 8192,
|
2026-03-22 11:21:58 +00:00
|
|
|
"context_window": 131072,
|
2026-02-04 11:06:13 +00:00
|
|
|
"temperature": 0.7,
|
2026-03-04 13:55:02 +00:00
|
|
|
"max_tool_iterations": 20,
|
|
|
|
|
"summarize_message_threshold": 20,
|
2026-03-19 10:08:50 +00:00
|
|
|
"summarize_token_percent": 75,
|
2026-03-25 17:33:49 +00:00
|
|
|
"split_on_marker": false,
|
2026-04-25 16:09:44 +00:00
|
|
|
"max_llm_retries": 2,
|
|
|
|
|
"llm_retry_backoff_secs": 2,
|
2026-03-19 10:08:50 +00:00
|
|
|
"tool_feedback": {
|
|
|
|
|
"enabled": false,
|
2026-04-24 03:49:41 +00:00
|
|
|
"max_args_length": 300,
|
|
|
|
|
"separate_messages": false
|
2026-03-19 10:08:50 +00:00
|
|
|
}
|
2026-02-04 11:06:13 +00:00
|
|
|
}
|
|
|
|
|
},
|
2026-05-12 03:23:06 +00:00
|
|
|
"evolution": {
|
|
|
|
|
"enabled": false,
|
|
|
|
|
"mode": "observe",
|
|
|
|
|
"state_dir": "",
|
|
|
|
|
"min_task_count": 2,
|
|
|
|
|
"min_success_ratio": 0.7,
|
|
|
|
|
"cold_path_trigger": "after_turn",
|
|
|
|
|
"cold_path_times": []
|
|
|
|
|
},
|
feat: add model_list configuration for zero-code provider addition
- Add ModelConfig struct with protocol prefix support (openai/, anthropic/, etc.)
- Implement GetModelConfig with round-robin load balancing
- Add CreateProviderFromConfig factory for protocol-based routing
- Add ModelRegistry for thread-safe endpoint selection
- Maintain full backward compatibility with legacy providers config
- Update README.md and README.zh.md with model_list documentation
- Add migration guide at docs/migration/model-list-migration.md
Supported protocols: openai, anthropic, antigravity, claude-cli, codex-cli,
github-copilot, openrouter, groq, deepseek, cerebras, qwen, zhipu, gemini
Closes #283
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 15:26:00 +00:00
|
|
|
"model_list": [
|
|
|
|
|
{
|
2026-03-12 08:10:29 +00:00
|
|
|
"model_name": "gpt-5.4",
|
|
|
|
|
"model": "openai/gpt-5.4",
|
2026-05-04 08:25:16 +00:00
|
|
|
"api_keys": ["sk-your-openai-key"],
|
feat: add model_list configuration for zero-code provider addition
- Add ModelConfig struct with protocol prefix support (openai/, anthropic/, etc.)
- Implement GetModelConfig with round-robin load balancing
- Add CreateProviderFromConfig factory for protocol-based routing
- Add ModelRegistry for thread-safe endpoint selection
- Maintain full backward compatibility with legacy providers config
- Update README.md and README.zh.md with model_list documentation
- Add migration guide at docs/migration/model-list-migration.md
Supported protocols: openai, anthropic, antigravity, claude-cli, codex-cli,
github-copilot, openrouter, groq, deepseek, cerebras, qwen, zhipu, gemini
Closes #283
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 15:26:00 +00:00
|
|
|
"api_base": "https://api.openai.com/v1"
|
|
|
|
|
},
|
|
|
|
|
{
|
2026-02-20 04:15:04 +00:00
|
|
|
"model_name": "claude-sonnet-4.6",
|
|
|
|
|
"model": "anthropic/claude-sonnet-4.6",
|
2026-05-04 08:25:16 +00:00
|
|
|
"api_keys": ["sk-ant-your-key"],
|
2026-03-05 01:51:18 +00:00
|
|
|
"api_base": "https://api.anthropic.com/v1",
|
|
|
|
|
"thinking_level": "high"
|
feat: add model_list configuration for zero-code provider addition
- Add ModelConfig struct with protocol prefix support (openai/, anthropic/, etc.)
- Implement GetModelConfig with round-robin load balancing
- Add CreateProviderFromConfig factory for protocol-based routing
- Add ModelRegistry for thread-safe endpoint selection
- Maintain full backward compatibility with legacy providers config
- Update README.md and README.zh.md with model_list documentation
- Add migration guide at docs/migration/model-list-migration.md
Supported protocols: openai, anthropic, antigravity, claude-cli, codex-cli,
github-copilot, openrouter, groq, deepseek, cerebras, qwen, zhipu, gemini
Closes #283
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 15:26:00 +00:00
|
|
|
},
|
feat: add anthropic-messages protocol for native Anthropic Messages API support Fixes #269 (#1284)
* feat: add anthropic-messages protocol support
Add native Anthropic Messages API format support to enable
compatibility with custom endpoints that only support Anthropic's
native message format (not OpenAI-compatible format).
Changes:
- Add new pkg/providers/anthropic_messages package with HTTP-based provider
- Implement Anthropic Messages API request/response format conversion
- Add anthropic-messages protocol support in factory_provider.go
- Include comprehensive unit tests (64.2% coverage)
Features:
- Support for system, user, assistant, and tool messages
- Support for tool calls (tool_use blocks)
- Proper header handling (x-api-key, anthropic-version)
- Configurable max_tokens and temperature
- Automatic base URL normalization
Configuration example:
model: "anthropic-messages/claude-opus-4-6"
api_base: "https://api.anthropic.com"
api_key: "sk-..."
Tested with actual API endpoint, verified compatibility
with Anthropic Messages API specification.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* docs: add anthropic-messages protocol examples to README and config
Add configuration examples and documentation for the new
anthropic-messages protocol:
- config.example.json: Add claude-opus-4.6 example with anthropic-messages
- README.md: Add "Anthropic Messages API (native format)" section
- README.zh.md: Add Chinese version of the documentation
This helps users understand when to use anthropic-messages vs
anthropic protocol and fixes issue #269.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* fix: format code with gofmt -s
- Align constant definitions in provider.go
- Align struct fields in test cases
- Fix gofmt formatting issues reported in review
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* fix: address linter errors
- Fix HTTP header canonical form: "x-api-key" → "X-API-Key"
- Fix HTTP header canonical form: "anthropic-version" → "Anthropic-Version"
- Format imports with gci (standard, default, localmodule order)
- Format code with golines (max line length 120)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* fix: resolve golangci-lint errors in anthropic-messages provider
- add nolint comment for canonicalheader rule on X-API-Key header (Anthropic API requires exact casing)
- fix golines formatting issues in provider_test.go (split long lines under 120 chars)
- fix long comment line in factory_provider.go (split into two lines)
Resolves CI linter failures for the anthropic-messages protocol implementation.
* fix(providers): address review comments in anthropic-messages provider
- fix normalizeBaseURL edge case that incorrectly appends /v1 to URLs already containing /v1 path (e.g., https://api.example.com/v1/proxy)
- remove dead code for apiBase empty check as normalizeBaseURL() always provides a default value
- update test to use proper constructor instead of direct struct initialization
- add detailed comments explaining the URL normalization logic
Resolves review comments on PR #1284
* fix(providers): remove hardcoded max_tokens in anthropic-messages provider
- remove hardcoded max_tokens value (4096) from buildRequestBody
- read max_tokens directly from options parameter
- add error handling when max_tokens is missing from options
- update test cases to include max_tokens in options
This fix ensures the provider respects the config default value (32768)
or system fallback (8192) instead of always using the hardcoded 4096.
* fix(providers): improve error handling and add edge case tests
- fix ToolCalls nil vs empty slice issue to ensure consistent JSON serialization
- add detailed HTTP error handling for common status codes (401, 429, 400, 404, 500, 503)
- add edge case tests for buildRequestBody and parseResponseBody
- clarify anthropic vs anthropic-messages protocol differences in docs
---------
Co-authored-by: Claude <noreply@anthropic.com>
2026-03-13 06:09:40 +00:00
|
|
|
{
|
|
|
|
|
"_comment": "Anthropic Messages API - use native format for direct Anthropic API access",
|
|
|
|
|
"model_name": "claude-opus-4-6",
|
|
|
|
|
"model": "anthropic-messages/claude-opus-4-6",
|
2026-05-04 08:25:16 +00:00
|
|
|
"api_keys": ["sk-ant-your-key"],
|
feat: add anthropic-messages protocol for native Anthropic Messages API support Fixes #269 (#1284)
* feat: add anthropic-messages protocol support
Add native Anthropic Messages API format support to enable
compatibility with custom endpoints that only support Anthropic's
native message format (not OpenAI-compatible format).
Changes:
- Add new pkg/providers/anthropic_messages package with HTTP-based provider
- Implement Anthropic Messages API request/response format conversion
- Add anthropic-messages protocol support in factory_provider.go
- Include comprehensive unit tests (64.2% coverage)
Features:
- Support for system, user, assistant, and tool messages
- Support for tool calls (tool_use blocks)
- Proper header handling (x-api-key, anthropic-version)
- Configurable max_tokens and temperature
- Automatic base URL normalization
Configuration example:
model: "anthropic-messages/claude-opus-4-6"
api_base: "https://api.anthropic.com"
api_key: "sk-..."
Tested with actual API endpoint, verified compatibility
with Anthropic Messages API specification.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* docs: add anthropic-messages protocol examples to README and config
Add configuration examples and documentation for the new
anthropic-messages protocol:
- config.example.json: Add claude-opus-4.6 example with anthropic-messages
- README.md: Add "Anthropic Messages API (native format)" section
- README.zh.md: Add Chinese version of the documentation
This helps users understand when to use anthropic-messages vs
anthropic protocol and fixes issue #269.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* fix: format code with gofmt -s
- Align constant definitions in provider.go
- Align struct fields in test cases
- Fix gofmt formatting issues reported in review
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* fix: address linter errors
- Fix HTTP header canonical form: "x-api-key" → "X-API-Key"
- Fix HTTP header canonical form: "anthropic-version" → "Anthropic-Version"
- Format imports with gci (standard, default, localmodule order)
- Format code with golines (max line length 120)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* fix: resolve golangci-lint errors in anthropic-messages provider
- add nolint comment for canonicalheader rule on X-API-Key header (Anthropic API requires exact casing)
- fix golines formatting issues in provider_test.go (split long lines under 120 chars)
- fix long comment line in factory_provider.go (split into two lines)
Resolves CI linter failures for the anthropic-messages protocol implementation.
* fix(providers): address review comments in anthropic-messages provider
- fix normalizeBaseURL edge case that incorrectly appends /v1 to URLs already containing /v1 path (e.g., https://api.example.com/v1/proxy)
- remove dead code for apiBase empty check as normalizeBaseURL() always provides a default value
- update test to use proper constructor instead of direct struct initialization
- add detailed comments explaining the URL normalization logic
Resolves review comments on PR #1284
* fix(providers): remove hardcoded max_tokens in anthropic-messages provider
- remove hardcoded max_tokens value (4096) from buildRequestBody
- read max_tokens directly from options parameter
- add error handling when max_tokens is missing from options
- update test cases to include max_tokens in options
This fix ensures the provider respects the config default value (32768)
or system fallback (8192) instead of always using the hardcoded 4096.
* fix(providers): improve error handling and add edge case tests
- fix ToolCalls nil vs empty slice issue to ensure consistent JSON serialization
- add detailed HTTP error handling for common status codes (401, 429, 400, 404, 500, 503)
- add edge case tests for buildRequestBody and parseResponseBody
- clarify anthropic vs anthropic-messages protocol differences in docs
---------
Co-authored-by: Claude <noreply@anthropic.com>
2026-03-13 06:09:40 +00:00
|
|
|
"api_base": "https://api.anthropic.com"
|
|
|
|
|
},
|
feat: add model_list configuration for zero-code provider addition
- Add ModelConfig struct with protocol prefix support (openai/, anthropic/, etc.)
- Implement GetModelConfig with round-robin load balancing
- Add CreateProviderFromConfig factory for protocol-based routing
- Add ModelRegistry for thread-safe endpoint selection
- Maintain full backward compatibility with legacy providers config
- Update README.md and README.zh.md with model_list documentation
- Add migration guide at docs/migration/model-list-migration.md
Supported protocols: openai, anthropic, antigravity, claude-cli, codex-cli,
github-copilot, openrouter, groq, deepseek, cerebras, qwen, zhipu, gemini
Closes #283
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 15:26:00 +00:00
|
|
|
{
|
|
|
|
|
"model_name": "gemini",
|
2026-04-27 19:10:30 +00:00
|
|
|
"_comment": "Optional: set \"tool_schema_transform\": \"simple\" for providers that reject complex tool JSON Schema.",
|
feat: add model_list configuration for zero-code provider addition
- Add ModelConfig struct with protocol prefix support (openai/, anthropic/, etc.)
- Implement GetModelConfig with round-robin load balancing
- Add CreateProviderFromConfig factory for protocol-based routing
- Add ModelRegistry for thread-safe endpoint selection
- Maintain full backward compatibility with legacy providers config
- Update README.md and README.zh.md with model_list documentation
- Add migration guide at docs/migration/model-list-migration.md
Supported protocols: openai, anthropic, antigravity, claude-cli, codex-cli,
github-copilot, openrouter, groq, deepseek, cerebras, qwen, zhipu, gemini
Closes #283
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 15:26:00 +00:00
|
|
|
"model": "antigravity/gemini-2.0-flash",
|
|
|
|
|
"auth_method": "oauth"
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"model_name": "deepseek",
|
|
|
|
|
"model": "deepseek/deepseek-chat",
|
2026-05-04 08:25:16 +00:00
|
|
|
"api_keys": ["sk-your-deepseek-key"]
|
feat: add model_list configuration for zero-code provider addition
- Add ModelConfig struct with protocol prefix support (openai/, anthropic/, etc.)
- Implement GetModelConfig with round-robin load balancing
- Add CreateProviderFromConfig factory for protocol-based routing
- Add ModelRegistry for thread-safe endpoint selection
- Maintain full backward compatibility with legacy providers config
- Update README.md and README.zh.md with model_list documentation
- Add migration guide at docs/migration/model-list-migration.md
Supported protocols: openai, anthropic, antigravity, claude-cli, codex-cli,
github-copilot, openrouter, groq, deepseek, cerebras, qwen, zhipu, gemini
Closes #283
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 15:26:00 +00:00
|
|
|
},
|
2026-04-01 15:50:29 +00:00
|
|
|
{
|
|
|
|
|
"model_name": "venice-uncensored",
|
|
|
|
|
"model": "venice/venice-uncensored",
|
2026-05-04 08:25:16 +00:00
|
|
|
"api_keys": ["your-venice-api-key"]
|
2026-04-01 15:50:29 +00:00
|
|
|
},
|
2026-03-31 06:48:18 +00:00
|
|
|
{
|
|
|
|
|
"model_name": "lmstudio-local",
|
|
|
|
|
"model": "lmstudio/openai/gpt-oss-20b"
|
|
|
|
|
},
|
2026-03-11 18:34:42 +00:00
|
|
|
{
|
|
|
|
|
"model_name": "longcat",
|
|
|
|
|
"model": "longcat/LongCat-Flash-Thinking",
|
2026-05-04 08:25:16 +00:00
|
|
|
"api_keys": ["your-longcat-api-key"]
|
2026-03-11 18:34:42 +00:00
|
|
|
},
|
2026-03-13 06:02:23 +00:00
|
|
|
{
|
|
|
|
|
"model_name": "modelscope-qwen",
|
|
|
|
|
"model": "modelscope/Qwen/Qwen3-235B-A22B-Instruct-2507",
|
2026-05-04 08:25:16 +00:00
|
|
|
"api_keys": ["your-modelscope-access-token"],
|
2026-03-13 06:02:23 +00:00
|
|
|
"api_base": "https://api-inference.modelscope.cn/v1"
|
|
|
|
|
},
|
2026-03-14 14:52:34 +00:00
|
|
|
{
|
|
|
|
|
"model_name": "azure-gpt5",
|
|
|
|
|
"model": "azure/my-gpt5-deployment",
|
2026-05-04 08:25:16 +00:00
|
|
|
"api_keys": ["your-azure-api-key"],
|
2026-03-14 14:52:34 +00:00
|
|
|
"api_base": "https://your-resource.openai.azure.com"
|
|
|
|
|
},
|
feat: add model_list configuration for zero-code provider addition
- Add ModelConfig struct with protocol prefix support (openai/, anthropic/, etc.)
- Implement GetModelConfig with round-robin load balancing
- Add CreateProviderFromConfig factory for protocol-based routing
- Add ModelRegistry for thread-safe endpoint selection
- Maintain full backward compatibility with legacy providers config
- Update README.md and README.zh.md with model_list documentation
- Add migration guide at docs/migration/model-list-migration.md
Supported protocols: openai, anthropic, antigravity, claude-cli, codex-cli,
github-copilot, openrouter, groq, deepseek, cerebras, qwen, zhipu, gemini
Closes #283
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 15:26:00 +00:00
|
|
|
{
|
2026-03-12 08:10:29 +00:00
|
|
|
"model_name": "loadbalanced-gpt-5.4",
|
|
|
|
|
"model": "openai/gpt-5.4",
|
2026-05-04 08:25:16 +00:00
|
|
|
"api_keys": ["sk-key1"],
|
feat: add model_list configuration for zero-code provider addition
- Add ModelConfig struct with protocol prefix support (openai/, anthropic/, etc.)
- Implement GetModelConfig with round-robin load balancing
- Add CreateProviderFromConfig factory for protocol-based routing
- Add ModelRegistry for thread-safe endpoint selection
- Maintain full backward compatibility with legacy providers config
- Update README.md and README.zh.md with model_list documentation
- Add migration guide at docs/migration/model-list-migration.md
Supported protocols: openai, anthropic, antigravity, claude-cli, codex-cli,
github-copilot, openrouter, groq, deepseek, cerebras, qwen, zhipu, gemini
Closes #283
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 15:26:00 +00:00
|
|
|
"api_base": "https://api1.example.com/v1"
|
|
|
|
|
},
|
|
|
|
|
{
|
2026-03-12 08:10:29 +00:00
|
|
|
"model_name": "loadbalanced-gpt-5.4",
|
|
|
|
|
"model": "openai/gpt-5.4",
|
2026-05-04 08:25:16 +00:00
|
|
|
"api_keys": ["sk-key2"],
|
feat: add model_list configuration for zero-code provider addition
- Add ModelConfig struct with protocol prefix support (openai/, anthropic/, etc.)
- Implement GetModelConfig with round-robin load balancing
- Add CreateProviderFromConfig factory for protocol-based routing
- Add ModelRegistry for thread-safe endpoint selection
- Maintain full backward compatibility with legacy providers config
- Update README.md and README.zh.md with model_list documentation
- Add migration guide at docs/migration/model-list-migration.md
Supported protocols: openai, anthropic, antigravity, claude-cli, codex-cli,
github-copilot, openrouter, groq, deepseek, cerebras, qwen, zhipu, gemini
Closes #283
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 15:26:00 +00:00
|
|
|
"api_base": "https://api2.example.com/v1"
|
|
|
|
|
}
|
|
|
|
|
],
|
2026-05-04 08:25:16 +00:00
|
|
|
"channel_list": {
|
2026-02-04 11:06:13 +00:00
|
|
|
"telegram": {
|
|
|
|
|
"enabled": false,
|
2026-05-04 08:25:16 +00:00
|
|
|
"type": "telegram",
|
2026-03-18 13:29:21 +00:00
|
|
|
"allow_from": ["YOUR_USER_ID"],
|
feat(telegram): stream LLM responses via sendMessageDraft (#1101)
* feat(telegram): stream LLM responses in real-time via sendMessageDraft
Implements real-time token streaming to Telegram using the sendMessageDraft
API (telego v1.6.0). Instead of showing only a "Thinking..." placeholder
until the full response arrives, users now see partial LLM output appear
in the chat as it's generated.
The streaming pipeline threads through all layers:
- StreamingProvider interface (providers/types.go): opt-in ChatStream()
method that receives an onChunk callback with accumulated text
- OpenAI-compatible SSE streaming (openai_compat/provider.go): parses
SSE events with stream:true, handles text deltas and tool call assembly
- Anthropic native streaming (anthropic/provider.go): uses SDK's
NewStreaming() for direct Anthropic API connections
- HTTPProvider delegation (http_provider.go): delegates ChatStream to
the underlying openai_compat provider
- StreamingCapable + Streamer interfaces (channels/interfaces.go):
opt-in channel capability like TypingCapable/PlaceholderCapable
- Telegram streamer (telegram/telegram.go): BeginStream returns a
telegramStreamer that throttles sendMessageDraft calls (3s/200 chars)
with graceful degradation on API errors
- StreamDelegate bridge (bus/bus.go): decouples agent loop from channel
manager without tight imports
- Manager integration (manager.go): implements StreamDelegate, tracks
streamActive state, coordinates with placeholder editing
- Agent loop (loop.go): uses ChatStream when both provider and channel
support streaming, cancels stream on tool calls, skips PublishOutbound
when Finalize already delivered the message
Graceful degradation:
- Bots without forum/topics mode: first sendMessageDraft error sets
failed=true, subsequent Updates become no-ops, Finalize still delivers
via SendMessage. User sees normal non-streaming behavior.
- Non-streaming providers: type assertion fails, falls back to Chat()
- Config opt-out: streaming.enabled (default true) in telegram config
Closes #1098
* fix(telegram): delete placeholder message when streaming delivers response
When streaming was active, the "Thinking..." placeholder message stayed
in the chat because preSend only deleted the tracking entry without
removing the actual Telegram message. Now preSend deletes the placeholder
via the new MessageDeleter interface when streamActive is set.
* refactor(streaming): remove dead code and simplify streaming wiring
- Delete unused Anthropic ChatStream/parseStream (-131 lines) — factory
creates HTTPProvider for all OpenAI-compat providers including OpenRouter
- Simplify runLLMIteration from 4 to 3 return values (remove unused
streamed bool)
- Replace managerStreamer struct with finalizeHookStreamer using embedding
(Update/Cancel promoted, only Finalize overridden)
* fix(streaming): skip streamer acquisition when SendResponse is false
Heartbeat messages set SendResponse=false but the streaming path
was unconditionally acquiring a streamer, causing HEARTBEAT_OK to
leak to Telegram via streamer.Finalize().
* fix(streaming): guard streamer for non-sendable messages, add streaming config
Skip streamer acquisition for heartbeat (NoHistory=true), preventing
HEARTBEAT_OK from leaking to Telegram via streamer.Finalize().
Add streaming.enabled to Telegram defaults and example config.
* feat(telegram): stream LLM responses in real-time via sendMessageDraft
Implements real-time token streaming to Telegram using the sendMessageDraft
API (telego v1.6.0). Instead of showing only a "Thinking..." placeholder
until the full response arrives, users now see partial LLM output appear
in the chat as it's generated.
The streaming pipeline threads through all layers:
- StreamingProvider interface (providers/types.go): opt-in ChatStream()
method that receives an onChunk callback with accumulated text
- OpenAI-compatible SSE streaming (openai_compat/provider.go): parses
SSE events with stream:true, handles text deltas and tool call assembly
- Anthropic native streaming (anthropic/provider.go): uses SDK's
NewStreaming() for direct Anthropic API connections
- HTTPProvider delegation (http_provider.go): delegates ChatStream to
the underlying openai_compat provider
- StreamingCapable + Streamer interfaces (channels/interfaces.go):
opt-in channel capability like TypingCapable/PlaceholderCapable
- Telegram streamer (telegram/telegram.go): BeginStream returns a
telegramStreamer that throttles sendMessageDraft calls (3s/200 chars)
with graceful degradation on API errors
- StreamDelegate bridge (bus/bus.go): decouples agent loop from channel
manager without tight imports
- Manager integration (manager.go): implements StreamDelegate, tracks
streamActive state, coordinates with placeholder editing
- Agent loop (loop.go): uses ChatStream when both provider and channel
support streaming, cancels stream on tool calls, skips PublishOutbound
when Finalize already delivered the message
Graceful degradation:
- Bots without forum/topics mode: first sendMessageDraft error sets
failed=true, subsequent Updates become no-ops, Finalize still delivers
via SendMessage. User sees normal non-streaming behavior.
- Non-streaming providers: type assertion fails, falls back to Chat()
- Config opt-out: streaming.enabled (default true) in telegram config
Closes #1098
* fix(telegram): delete placeholder message when streaming delivers response
When streaming was active, the "Thinking..." placeholder message stayed
in the chat because preSend only deleted the tracking entry without
removing the actual Telegram message. Now preSend deletes the placeholder
via the new MessageDeleter interface when streamActive is set.
* refactor(streaming): remove dead code and simplify streaming wiring
- Delete unused Anthropic ChatStream/parseStream (-131 lines) — factory
creates HTTPProvider for all OpenAI-compat providers including OpenRouter
- Simplify runLLMIteration from 4 to 3 return values (remove unused
streamed bool)
- Replace managerStreamer struct with finalizeHookStreamer using embedding
(Update/Cancel promoted, only Finalize overridden)
* fix(streaming): skip streamer acquisition when SendResponse is false
Heartbeat messages set SendResponse=false but the streaming path
was unconditionally acquiring a streamer, causing HEARTBEAT_OK to
leak to Telegram via streamer.Finalize().
* fix(streaming): guard streamer for non-sendable messages, add streaming config
Skip streamer acquisition for heartbeat (NoHistory=true), preventing
HEARTBEAT_OK from leaking to Telegram via streamer.Finalize().
Add streaming.enabled to Telegram defaults and example config.
* fix(picoclaw): add missing closing brace for StreamingProvider interface
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: resolve golangci-lint formatting issues
Fix gci import ordering in telegram and anthropic provider, and break
long function signature in openai_compat provider to satisfy golines.
* fix: address code review feedback on streaming PR
- Deduplicate Streamer interface: alias channels.Streamer to bus.Streamer
to prevent type drift across packages
- Increase SSE scanner buffer to 10MB max to handle large single-line
responses that exceed bufio.Scanner's 64KB default
- Switch draftID generation from math/rand to crypto/rand for
collision-resistant random IDs
- Add context cancellation check in SSE parsing loop so cancelled
streams stop processing immediately
- Log Finalize failures with chat_id and content length for debugging
silent message delivery failures
* feat: make streaming throttle interval and min growth configurable
Move hardcoded streamThrottleInterval (3s) and streamMinGrowth (200)
into StreamingConfig so they can be tuned per deployment via config
or environment variables.
* fix(telegram): use parseTelegramChatID in DeleteMessage and BeginStream
These two functions called undefined parseChatID. Use
parseTelegramChatID with _ for the unused threadID instead of adding
a wrapper function. Fixes all three CI checks.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(streaming): set streamActive only after successful Finalize
Move onFinalize hook to run after Streamer.Finalize succeeds, so that
if Finalize fails the streamActive flag stays false and the regular
placeholder fallback path remains available.
Addresses review feedback from @alexhoshina.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-20 13:04:14 +00:00
|
|
|
"reasoning_channel_id": "",
|
2026-05-04 08:25:16 +00:00
|
|
|
"settings": {
|
|
|
|
|
"token": "YOUR_TELEGRAM_BOT_TOKEN",
|
|
|
|
|
"base_url": "",
|
|
|
|
|
"proxy": "",
|
|
|
|
|
"use_markdown_v2": false,
|
|
|
|
|
"streaming": {
|
|
|
|
|
"enabled": true
|
|
|
|
|
}
|
feat(telegram): stream LLM responses via sendMessageDraft (#1101)
* feat(telegram): stream LLM responses in real-time via sendMessageDraft
Implements real-time token streaming to Telegram using the sendMessageDraft
API (telego v1.6.0). Instead of showing only a "Thinking..." placeholder
until the full response arrives, users now see partial LLM output appear
in the chat as it's generated.
The streaming pipeline threads through all layers:
- StreamingProvider interface (providers/types.go): opt-in ChatStream()
method that receives an onChunk callback with accumulated text
- OpenAI-compatible SSE streaming (openai_compat/provider.go): parses
SSE events with stream:true, handles text deltas and tool call assembly
- Anthropic native streaming (anthropic/provider.go): uses SDK's
NewStreaming() for direct Anthropic API connections
- HTTPProvider delegation (http_provider.go): delegates ChatStream to
the underlying openai_compat provider
- StreamingCapable + Streamer interfaces (channels/interfaces.go):
opt-in channel capability like TypingCapable/PlaceholderCapable
- Telegram streamer (telegram/telegram.go): BeginStream returns a
telegramStreamer that throttles sendMessageDraft calls (3s/200 chars)
with graceful degradation on API errors
- StreamDelegate bridge (bus/bus.go): decouples agent loop from channel
manager without tight imports
- Manager integration (manager.go): implements StreamDelegate, tracks
streamActive state, coordinates with placeholder editing
- Agent loop (loop.go): uses ChatStream when both provider and channel
support streaming, cancels stream on tool calls, skips PublishOutbound
when Finalize already delivered the message
Graceful degradation:
- Bots without forum/topics mode: first sendMessageDraft error sets
failed=true, subsequent Updates become no-ops, Finalize still delivers
via SendMessage. User sees normal non-streaming behavior.
- Non-streaming providers: type assertion fails, falls back to Chat()
- Config opt-out: streaming.enabled (default true) in telegram config
Closes #1098
* fix(telegram): delete placeholder message when streaming delivers response
When streaming was active, the "Thinking..." placeholder message stayed
in the chat because preSend only deleted the tracking entry without
removing the actual Telegram message. Now preSend deletes the placeholder
via the new MessageDeleter interface when streamActive is set.
* refactor(streaming): remove dead code and simplify streaming wiring
- Delete unused Anthropic ChatStream/parseStream (-131 lines) — factory
creates HTTPProvider for all OpenAI-compat providers including OpenRouter
- Simplify runLLMIteration from 4 to 3 return values (remove unused
streamed bool)
- Replace managerStreamer struct with finalizeHookStreamer using embedding
(Update/Cancel promoted, only Finalize overridden)
* fix(streaming): skip streamer acquisition when SendResponse is false
Heartbeat messages set SendResponse=false but the streaming path
was unconditionally acquiring a streamer, causing HEARTBEAT_OK to
leak to Telegram via streamer.Finalize().
* fix(streaming): guard streamer for non-sendable messages, add streaming config
Skip streamer acquisition for heartbeat (NoHistory=true), preventing
HEARTBEAT_OK from leaking to Telegram via streamer.Finalize().
Add streaming.enabled to Telegram defaults and example config.
* feat(telegram): stream LLM responses in real-time via sendMessageDraft
Implements real-time token streaming to Telegram using the sendMessageDraft
API (telego v1.6.0). Instead of showing only a "Thinking..." placeholder
until the full response arrives, users now see partial LLM output appear
in the chat as it's generated.
The streaming pipeline threads through all layers:
- StreamingProvider interface (providers/types.go): opt-in ChatStream()
method that receives an onChunk callback with accumulated text
- OpenAI-compatible SSE streaming (openai_compat/provider.go): parses
SSE events with stream:true, handles text deltas and tool call assembly
- Anthropic native streaming (anthropic/provider.go): uses SDK's
NewStreaming() for direct Anthropic API connections
- HTTPProvider delegation (http_provider.go): delegates ChatStream to
the underlying openai_compat provider
- StreamingCapable + Streamer interfaces (channels/interfaces.go):
opt-in channel capability like TypingCapable/PlaceholderCapable
- Telegram streamer (telegram/telegram.go): BeginStream returns a
telegramStreamer that throttles sendMessageDraft calls (3s/200 chars)
with graceful degradation on API errors
- StreamDelegate bridge (bus/bus.go): decouples agent loop from channel
manager without tight imports
- Manager integration (manager.go): implements StreamDelegate, tracks
streamActive state, coordinates with placeholder editing
- Agent loop (loop.go): uses ChatStream when both provider and channel
support streaming, cancels stream on tool calls, skips PublishOutbound
when Finalize already delivered the message
Graceful degradation:
- Bots without forum/topics mode: first sendMessageDraft error sets
failed=true, subsequent Updates become no-ops, Finalize still delivers
via SendMessage. User sees normal non-streaming behavior.
- Non-streaming providers: type assertion fails, falls back to Chat()
- Config opt-out: streaming.enabled (default true) in telegram config
Closes #1098
* fix(telegram): delete placeholder message when streaming delivers response
When streaming was active, the "Thinking..." placeholder message stayed
in the chat because preSend only deleted the tracking entry without
removing the actual Telegram message. Now preSend deletes the placeholder
via the new MessageDeleter interface when streamActive is set.
* refactor(streaming): remove dead code and simplify streaming wiring
- Delete unused Anthropic ChatStream/parseStream (-131 lines) — factory
creates HTTPProvider for all OpenAI-compat providers including OpenRouter
- Simplify runLLMIteration from 4 to 3 return values (remove unused
streamed bool)
- Replace managerStreamer struct with finalizeHookStreamer using embedding
(Update/Cancel promoted, only Finalize overridden)
* fix(streaming): skip streamer acquisition when SendResponse is false
Heartbeat messages set SendResponse=false but the streaming path
was unconditionally acquiring a streamer, causing HEARTBEAT_OK to
leak to Telegram via streamer.Finalize().
* fix(streaming): guard streamer for non-sendable messages, add streaming config
Skip streamer acquisition for heartbeat (NoHistory=true), preventing
HEARTBEAT_OK from leaking to Telegram via streamer.Finalize().
Add streaming.enabled to Telegram defaults and example config.
* fix(picoclaw): add missing closing brace for StreamingProvider interface
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: resolve golangci-lint formatting issues
Fix gci import ordering in telegram and anthropic provider, and break
long function signature in openai_compat provider to satisfy golines.
* fix: address code review feedback on streaming PR
- Deduplicate Streamer interface: alias channels.Streamer to bus.Streamer
to prevent type drift across packages
- Increase SSE scanner buffer to 10MB max to handle large single-line
responses that exceed bufio.Scanner's 64KB default
- Switch draftID generation from math/rand to crypto/rand for
collision-resistant random IDs
- Add context cancellation check in SSE parsing loop so cancelled
streams stop processing immediately
- Log Finalize failures with chat_id and content length for debugging
silent message delivery failures
* feat: make streaming throttle interval and min growth configurable
Move hardcoded streamThrottleInterval (3s) and streamMinGrowth (200)
into StreamingConfig so they can be tuned per deployment via config
or environment variables.
* fix(telegram): use parseTelegramChatID in DeleteMessage and BeginStream
These two functions called undefined parseChatID. Use
parseTelegramChatID with _ for the unused threadID instead of adding
a wrapper function. Fixes all three CI checks.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(streaming): set streamActive only after successful Finalize
Move onFinalize hook to run after Streamer.Finalize succeeds, so that
if Finalize fails the streamActive flag stays false and the regular
placeholder fallback path remains available.
Addresses review feedback from @alexhoshina.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-20 13:04:14 +00:00
|
|
|
}
|
2026-02-04 11:06:13 +00:00
|
|
|
},
|
|
|
|
|
"discord": {
|
|
|
|
|
"enabled": false,
|
2026-05-04 08:25:16 +00:00
|
|
|
"type": "discord",
|
2026-02-20 11:18:37 +00:00
|
|
|
"allow_from": [],
|
2026-02-28 14:25:31 +00:00
|
|
|
"group_trigger": {
|
|
|
|
|
"mention_only": false
|
|
|
|
|
},
|
2026-05-04 08:25:16 +00:00
|
|
|
"reasoning_channel_id": "",
|
|
|
|
|
"settings": {
|
|
|
|
|
"token": "YOUR_DISCORD_BOT_TOKEN",
|
|
|
|
|
"proxy": ""
|
|
|
|
|
}
|
2026-02-04 11:06:13 +00:00
|
|
|
},
|
2026-02-20 07:11:40 +00:00
|
|
|
"qq": {
|
|
|
|
|
"enabled": false,
|
2026-05-04 08:25:16 +00:00
|
|
|
"type": "qq",
|
2026-02-26 06:03:01 +00:00
|
|
|
"allow_from": [],
|
2026-05-04 08:25:16 +00:00
|
|
|
"reasoning_channel_id": "",
|
|
|
|
|
"settings": {
|
|
|
|
|
"app_id": "YOUR_QQ_APP_ID",
|
|
|
|
|
"app_secret": "YOUR_QQ_APP_SECRET"
|
|
|
|
|
}
|
2026-02-20 07:11:40 +00:00
|
|
|
},
|
2026-02-04 11:06:13 +00:00
|
|
|
"maixcam": {
|
|
|
|
|
"enabled": false,
|
2026-05-04 08:25:16 +00:00
|
|
|
"type": "maixcam",
|
2026-02-26 06:03:01 +00:00
|
|
|
"allow_from": [],
|
2026-05-04 08:25:16 +00:00
|
|
|
"reasoning_channel_id": "",
|
|
|
|
|
"settings": {
|
|
|
|
|
"host": "0.0.0.0",
|
|
|
|
|
"port": 18790
|
|
|
|
|
}
|
2026-02-04 11:06:13 +00:00
|
|
|
},
|
|
|
|
|
"whatsapp": {
|
|
|
|
|
"enabled": false,
|
2026-05-04 08:25:16 +00:00
|
|
|
"type": "whatsapp",
|
2026-02-26 06:03:01 +00:00
|
|
|
"allow_from": [],
|
2026-05-04 08:25:16 +00:00
|
|
|
"reasoning_channel_id": "",
|
|
|
|
|
"settings": {
|
|
|
|
|
"bridge_url": "ws://localhost:3001",
|
|
|
|
|
"use_native": false,
|
|
|
|
|
"session_store_path": ""
|
|
|
|
|
}
|
2026-02-04 11:06:13 +00:00
|
|
|
},
|
|
|
|
|
"feishu": {
|
|
|
|
|
"enabled": false,
|
2026-05-04 08:25:16 +00:00
|
|
|
"type": "feishu",
|
2026-02-26 06:03:01 +00:00
|
|
|
"allow_from": [],
|
2026-05-04 08:25:16 +00:00
|
|
|
"reasoning_channel_id": "",
|
2026-03-25 09:41:50 +00:00
|
|
|
"placeholder": {
|
|
|
|
|
"enabled": true,
|
|
|
|
|
"text": ["Thinking...", "Processing...", "Typing..."]
|
|
|
|
|
},
|
2026-05-04 08:25:16 +00:00
|
|
|
"settings": {
|
|
|
|
|
"app_id": "",
|
|
|
|
|
"app_secret": "",
|
|
|
|
|
"encrypt_key": "",
|
|
|
|
|
"verification_token": "",
|
|
|
|
|
"random_reaction_emoji": [],
|
|
|
|
|
"is_lark": false
|
|
|
|
|
}
|
2026-02-11 11:47:11 +00:00
|
|
|
},
|
|
|
|
|
"dingtalk": {
|
|
|
|
|
"enabled": false,
|
2026-05-04 08:25:16 +00:00
|
|
|
"type": "dingtalk",
|
2026-02-26 06:03:01 +00:00
|
|
|
"allow_from": [],
|
2026-05-04 08:25:16 +00:00
|
|
|
"reasoning_channel_id": "",
|
|
|
|
|
"settings": {
|
|
|
|
|
"client_id": "YOUR_CLIENT_ID",
|
|
|
|
|
"client_secret": "YOUR_CLIENT_SECRET"
|
|
|
|
|
}
|
2026-02-11 18:48:32 +00:00
|
|
|
},
|
|
|
|
|
"slack": {
|
|
|
|
|
"enabled": false,
|
2026-05-04 08:25:16 +00:00
|
|
|
"type": "slack",
|
2026-02-26 06:03:01 +00:00
|
|
|
"allow_from": [],
|
2026-05-04 08:25:16 +00:00
|
|
|
"reasoning_channel_id": "",
|
|
|
|
|
"settings": {
|
|
|
|
|
"bot_token": "xoxb-YOUR-BOT-TOKEN",
|
|
|
|
|
"app_token": "xapp-YOUR-APP-TOKEN"
|
|
|
|
|
}
|
2026-02-14 01:01:20 +00:00
|
|
|
},
|
2026-03-07 17:44:24 +00:00
|
|
|
"matrix": {
|
|
|
|
|
"enabled": false,
|
2026-05-04 08:25:16 +00:00
|
|
|
"type": "matrix",
|
2026-03-07 17:44:24 +00:00
|
|
|
"allow_from": [],
|
|
|
|
|
"group_trigger": {
|
|
|
|
|
"mention_only": true
|
|
|
|
|
},
|
|
|
|
|
"placeholder": {
|
|
|
|
|
"enabled": true,
|
2026-03-25 09:41:50 +00:00
|
|
|
"text": ["Thinking...", "Processing...", "Typing..."]
|
2026-03-07 17:44:24 +00:00
|
|
|
},
|
2026-03-20 16:00:37 +00:00
|
|
|
"reasoning_channel_id": "",
|
2026-05-04 08:25:16 +00:00
|
|
|
"settings": {
|
|
|
|
|
"homeserver": "https://matrix.org",
|
|
|
|
|
"user_id": "@your-bot:matrix.org",
|
|
|
|
|
"access_token": "YOUR_MATRIX_ACCESS_TOKEN",
|
|
|
|
|
"device_id": "",
|
|
|
|
|
"join_on_invite": true,
|
|
|
|
|
"crypto_database_path": "",
|
|
|
|
|
"crypto_passphrase": "YOUR_MATRIX_CRYPTO_PICKLE_KEY"
|
|
|
|
|
}
|
2026-03-07 17:44:24 +00:00
|
|
|
},
|
2026-02-14 01:01:20 +00:00
|
|
|
"line": {
|
|
|
|
|
"enabled": false,
|
2026-05-04 08:25:16 +00:00
|
|
|
"type": "line",
|
2026-02-26 06:03:01 +00:00
|
|
|
"allow_from": [],
|
2026-05-04 08:25:16 +00:00
|
|
|
"reasoning_channel_id": "",
|
|
|
|
|
"settings": {
|
|
|
|
|
"channel_secret": "YOUR_LINE_CHANNEL_SECRET",
|
|
|
|
|
"channel_access_token": "YOUR_LINE_CHANNEL_ACCESS_TOKEN",
|
|
|
|
|
"webhook_path": "/webhook/line"
|
|
|
|
|
}
|
2026-02-14 08:50:21 +00:00
|
|
|
},
|
|
|
|
|
"onebot": {
|
|
|
|
|
"enabled": false,
|
2026-05-04 08:25:16 +00:00
|
|
|
"type": "onebot",
|
2026-02-26 06:03:01 +00:00
|
|
|
"allow_from": [],
|
2026-05-04 08:25:16 +00:00
|
|
|
"reasoning_channel_id": "",
|
|
|
|
|
"group_trigger": {
|
|
|
|
|
"prefixes": []
|
|
|
|
|
},
|
|
|
|
|
"settings": {
|
|
|
|
|
"ws_url": "ws://127.0.0.1:3001",
|
|
|
|
|
"access_token": "",
|
|
|
|
|
"reconnect_interval": 5
|
|
|
|
|
}
|
2026-02-20 07:33:24 +00:00
|
|
|
},
|
|
|
|
|
"wecom": {
|
2026-03-24 07:04:14 +00:00
|
|
|
"_comment": "WeCom AI Bot over WebSocket.",
|
2026-02-28 05:25:37 +00:00
|
|
|
"enabled": false,
|
2026-05-04 08:25:16 +00:00
|
|
|
"type": "wecom",
|
2026-03-24 07:04:14 +00:00
|
|
|
"allow_from": [],
|
2026-05-04 08:25:16 +00:00
|
|
|
"reasoning_channel_id": "",
|
|
|
|
|
"settings": {
|
|
|
|
|
"bot_id": "YOUR_BOT_ID",
|
|
|
|
|
"secret": "YOUR_SECRET",
|
|
|
|
|
"websocket_url": "wss://openws.work.weixin.qq.com",
|
|
|
|
|
"send_thinking_message": true
|
|
|
|
|
}
|
2026-03-05 10:46:01 +00:00
|
|
|
},
|
2026-03-20 12:43:40 +00:00
|
|
|
"pico": {
|
|
|
|
|
"enabled": false,
|
2026-05-04 08:25:16 +00:00
|
|
|
"type": "pico",
|
|
|
|
|
"allow_from": [],
|
|
|
|
|
"settings": {
|
|
|
|
|
"token": "YOUR_PICO_TOKEN",
|
|
|
|
|
"allow_token_query": false,
|
|
|
|
|
"allow_origins": [],
|
|
|
|
|
"ping_interval": 30,
|
|
|
|
|
"read_timeout": 60,
|
|
|
|
|
"max_connections": 100
|
|
|
|
|
}
|
2026-03-20 12:43:40 +00:00
|
|
|
},
|
|
|
|
|
"pico_client": {
|
|
|
|
|
"enabled": false,
|
2026-05-04 08:25:16 +00:00
|
|
|
"type": "pico_client",
|
|
|
|
|
"allow_from": [],
|
|
|
|
|
"settings": {
|
|
|
|
|
"url": "wss://remote-pico-server/pico/ws",
|
|
|
|
|
"token": "YOUR_PICO_TOKEN",
|
|
|
|
|
"session_id": "",
|
|
|
|
|
"ping_interval": 30,
|
|
|
|
|
"read_timeout": 60
|
|
|
|
|
}
|
2026-03-20 12:43:40 +00:00
|
|
|
},
|
2026-03-05 10:46:01 +00:00
|
|
|
"irc": {
|
|
|
|
|
"enabled": false,
|
2026-05-04 08:25:16 +00:00
|
|
|
"type": "irc",
|
2026-03-05 10:46:01 +00:00
|
|
|
"allow_from": [],
|
|
|
|
|
"group_trigger": {
|
|
|
|
|
"mention_only": true
|
|
|
|
|
},
|
|
|
|
|
"typing": {
|
|
|
|
|
"enabled": false
|
|
|
|
|
},
|
2026-05-04 08:25:16 +00:00
|
|
|
"reasoning_channel_id": "",
|
|
|
|
|
"settings": {
|
|
|
|
|
"server": "irc.libera.chat:6697",
|
|
|
|
|
"tls": true,
|
|
|
|
|
"nick": "mybot",
|
|
|
|
|
"user": "",
|
|
|
|
|
"real_name": "",
|
|
|
|
|
"password": "",
|
|
|
|
|
"nickserv_password": "",
|
|
|
|
|
"sasl_user": "",
|
|
|
|
|
"sasl_password": "",
|
|
|
|
|
"channels": ["#mychannel"],
|
|
|
|
|
"request_caps": ["server-time", "message-tags"]
|
|
|
|
|
}
|
2026-02-04 11:06:13 +00:00
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
"tools": {
|
2026-03-05 06:53:26 +00:00
|
|
|
"allow_read_paths": null,
|
|
|
|
|
"allow_write_paths": null,
|
2026-02-04 11:06:13 +00:00
|
|
|
"web": {
|
2026-03-05 06:53:26 +00:00
|
|
|
"enabled": true,
|
2026-03-18 03:55:30 +00:00
|
|
|
"prefer_native": true,
|
2026-03-15 21:12:03 +00:00
|
|
|
"format": "plaintext",
|
2026-02-17 13:02:56 +00:00
|
|
|
"brave": {
|
|
|
|
|
"enabled": false,
|
2026-02-04 11:06:13 +00:00
|
|
|
"api_key": "YOUR_BRAVE_API_KEY",
|
2026-03-25 17:33:49 +00:00
|
|
|
"api_keys": ["YOUR_BRAVE_API_KEY"],
|
2026-02-04 11:06:13 +00:00
|
|
|
"max_results": 5
|
2026-02-17 13:02:56 +00:00
|
|
|
},
|
2026-03-05 06:53:26 +00:00
|
|
|
"tavily": {
|
|
|
|
|
"enabled": false,
|
|
|
|
|
"api_key": "",
|
|
|
|
|
"base_url": "",
|
|
|
|
|
"max_results": 0
|
|
|
|
|
},
|
2026-06-07 12:42:04 +00:00
|
|
|
"kagi": {
|
|
|
|
|
"enabled": false,
|
|
|
|
|
"api_key": "",
|
|
|
|
|
"api_keys": ["YOUR_KAGI_API_KEY"],
|
|
|
|
|
"base_url": "https://kagi.com/api/v1/search",
|
|
|
|
|
"max_results": 5
|
|
|
|
|
},
|
2026-04-15 10:45:28 +00:00
|
|
|
"provider": "auto",
|
2026-04-14 14:58:07 +00:00
|
|
|
"sogou": {
|
2026-02-20 07:11:40 +00:00
|
|
|
"enabled": true,
|
|
|
|
|
"max_results": 5
|
|
|
|
|
},
|
2026-04-14 14:58:07 +00:00
|
|
|
"duckduckgo": {
|
|
|
|
|
"enabled": false,
|
|
|
|
|
"max_results": 5
|
|
|
|
|
},
|
2026-05-14 01:50:47 +00:00
|
|
|
"gemini": {
|
|
|
|
|
"enabled": false,
|
|
|
|
|
"api_key": "",
|
|
|
|
|
"model": "gemini-2.5-flash",
|
|
|
|
|
"max_results": 5
|
|
|
|
|
},
|
2026-02-17 13:02:56 +00:00
|
|
|
"perplexity": {
|
|
|
|
|
"enabled": false,
|
2026-03-10 08:34:11 +00:00
|
|
|
"api_key": "pplx-xxx",
|
2026-03-25 17:33:49 +00:00
|
|
|
"api_keys": ["pplx-xxx"],
|
2026-02-17 13:02:56 +00:00
|
|
|
"max_results": 5
|
2026-02-20 11:39:25 +00:00
|
|
|
},
|
|
|
|
|
"searxng": {
|
|
|
|
|
"enabled": false,
|
|
|
|
|
"base_url": "http://localhost:8888",
|
|
|
|
|
"max_results": 5
|
2026-02-26 07:21:09 +00:00
|
|
|
},
|
2026-03-05 06:53:26 +00:00
|
|
|
"glm_search": {
|
|
|
|
|
"enabled": false,
|
|
|
|
|
"api_key": "",
|
|
|
|
|
"base_url": "https://open.bigmodel.cn/api/paas/v4/web_search",
|
|
|
|
|
"search_engine": "search_std",
|
2026-02-17 13:02:56 +00:00
|
|
|
"max_results": 5
|
2026-02-24 09:16:16 +00:00
|
|
|
},
|
2026-03-25 07:11:02 +00:00
|
|
|
"baidu_search": {
|
|
|
|
|
"enabled": false,
|
|
|
|
|
"api_key": "",
|
|
|
|
|
"base_url": "https://qianfan.baidubce.com/v2/ai_search/web_search",
|
|
|
|
|
"max_results": 10
|
|
|
|
|
},
|
2026-03-17 15:22:05 +00:00
|
|
|
"fetch_limit_bytes": 10485760,
|
|
|
|
|
"private_host_whitelist": []
|
2026-02-15 10:41:39 +00:00
|
|
|
},
|
|
|
|
|
"cron": {
|
2026-03-05 06:53:26 +00:00
|
|
|
"enabled": true,
|
2026-02-15 10:41:39 +00:00
|
|
|
"exec_timeout_minutes": 5
|
2026-02-20 07:11:40 +00:00
|
|
|
},
|
2026-02-15 09:26:36 +00:00
|
|
|
"mcp": {
|
|
|
|
|
"enabled": false,
|
2026-03-09 17:21:49 +00:00
|
|
|
"discovery": {
|
|
|
|
|
"enabled": false,
|
|
|
|
|
"ttl": 5,
|
|
|
|
|
"max_search_results": 5,
|
|
|
|
|
"use_bm25": true,
|
|
|
|
|
"use_regex": false
|
|
|
|
|
},
|
2026-02-21 05:42:26 +00:00
|
|
|
"servers": {
|
2026-03-02 18:50:34 +00:00
|
|
|
"context7": {
|
|
|
|
|
"enabled": false,
|
|
|
|
|
"type": "http",
|
|
|
|
|
"url": "https://mcp.context7.com/mcp",
|
|
|
|
|
"headers": {
|
|
|
|
|
"CONTEXT7_API_KEY": "ctx7sk-xx"
|
|
|
|
|
}
|
|
|
|
|
},
|
2026-02-21 05:42:26 +00:00
|
|
|
"filesystem": {
|
|
|
|
|
"enabled": false,
|
|
|
|
|
"command": "npx",
|
2026-03-25 17:33:49 +00:00
|
|
|
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"]
|
2026-02-21 05:42:26 +00:00
|
|
|
},
|
|
|
|
|
"github": {
|
|
|
|
|
"enabled": false,
|
|
|
|
|
"command": "npx",
|
2026-03-25 17:33:49 +00:00
|
|
|
"args": ["-y", "@modelcontextprotocol/server-github"],
|
2026-02-21 05:42:26 +00:00
|
|
|
"env": {
|
|
|
|
|
"GITHUB_PERSONAL_ACCESS_TOKEN": "YOUR_GITHUB_TOKEN"
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
"brave-search": {
|
|
|
|
|
"enabled": false,
|
|
|
|
|
"command": "npx",
|
2026-03-25 17:33:49 +00:00
|
|
|
"args": ["-y", "@modelcontextprotocol/server-brave-search"],
|
2026-02-21 05:42:26 +00:00
|
|
|
"env": {
|
|
|
|
|
"BRAVE_API_KEY": "YOUR_BRAVE_API_KEY"
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
"postgres": {
|
|
|
|
|
"enabled": false,
|
|
|
|
|
"command": "npx",
|
|
|
|
|
"args": [
|
|
|
|
|
"-y",
|
|
|
|
|
"@modelcontextprotocol/server-postgres",
|
|
|
|
|
"postgresql://user:password@localhost/dbname"
|
|
|
|
|
]
|
2026-03-01 02:56:02 +00:00
|
|
|
},
|
|
|
|
|
"slack": {
|
|
|
|
|
"enabled": false,
|
|
|
|
|
"command": "npx",
|
2026-03-25 17:33:49 +00:00
|
|
|
"args": ["-y", "@modelcontextprotocol/server-slack"],
|
2026-03-01 02:56:02 +00:00
|
|
|
"env": {
|
|
|
|
|
"SLACK_BOT_TOKEN": "YOUR_SLACK_BOT_TOKEN",
|
|
|
|
|
"SLACK_TEAM_ID": "YOUR_SLACK_TEAM_ID"
|
|
|
|
|
}
|
2026-02-21 05:42:26 +00:00
|
|
|
}
|
|
|
|
|
}
|
2026-02-21 05:28:15 +00:00
|
|
|
},
|
2026-02-20 07:11:40 +00:00
|
|
|
"exec": {
|
2026-03-05 06:53:26 +00:00
|
|
|
"enabled": true,
|
|
|
|
|
"enable_deny_patterns": true,
|
|
|
|
|
"custom_deny_patterns": null,
|
|
|
|
|
"custom_allow_patterns": null
|
2026-02-20 10:55:04 +00:00
|
|
|
},
|
|
|
|
|
"skills": {
|
2026-03-05 06:53:26 +00:00
|
|
|
"enabled": true,
|
2026-02-20 10:55:04 +00:00
|
|
|
"registries": {
|
|
|
|
|
"clawhub": {
|
|
|
|
|
"enabled": true,
|
|
|
|
|
"base_url": "https://clawhub.ai",
|
2026-03-05 06:53:26 +00:00
|
|
|
"auth_token": "",
|
|
|
|
|
"search_path": "",
|
|
|
|
|
"skills_path": "",
|
|
|
|
|
"download_path": "",
|
|
|
|
|
"timeout": 0,
|
|
|
|
|
"max_zip_size": 0,
|
|
|
|
|
"max_response_size": 0
|
2026-04-14 07:14:16 +00:00
|
|
|
},
|
|
|
|
|
"github": {
|
|
|
|
|
"enabled": true,
|
|
|
|
|
"base_url": "https://github.com",
|
|
|
|
|
"auth_token": "",
|
|
|
|
|
"proxy": "http://127.0.0.1:7891"
|
2026-02-20 10:55:04 +00:00
|
|
|
}
|
2026-03-05 06:53:26 +00:00
|
|
|
},
|
2026-03-13 06:04:02 +00:00
|
|
|
"github": {
|
2026-04-14 07:14:16 +00:00
|
|
|
"base_url": "https://github.com",
|
2026-03-13 06:04:02 +00:00
|
|
|
"proxy": "http://127.0.0.1:7891",
|
|
|
|
|
"token": ""
|
|
|
|
|
},
|
2026-03-05 06:53:26 +00:00
|
|
|
"max_concurrent_searches": 2,
|
|
|
|
|
"search_cache": {
|
|
|
|
|
"max_size": 50,
|
|
|
|
|
"ttl_seconds": 300
|
2026-02-20 10:55:04 +00:00
|
|
|
}
|
2026-03-05 06:53:26 +00:00
|
|
|
},
|
|
|
|
|
"media_cleanup": {
|
|
|
|
|
"enabled": true,
|
|
|
|
|
"max_age_minutes": 30,
|
|
|
|
|
"interval_minutes": 5
|
|
|
|
|
},
|
|
|
|
|
"append_file": {
|
|
|
|
|
"enabled": true
|
|
|
|
|
},
|
|
|
|
|
"edit_file": {
|
|
|
|
|
"enabled": true
|
|
|
|
|
},
|
|
|
|
|
"find_skills": {
|
|
|
|
|
"enabled": true
|
|
|
|
|
},
|
|
|
|
|
"i2c": {
|
|
|
|
|
"enabled": false
|
|
|
|
|
},
|
|
|
|
|
"install_skill": {
|
|
|
|
|
"enabled": true
|
|
|
|
|
},
|
|
|
|
|
"list_dir": {
|
|
|
|
|
"enabled": true
|
|
|
|
|
},
|
|
|
|
|
"message": {
|
|
|
|
|
"enabled": true
|
|
|
|
|
},
|
|
|
|
|
"read_file": {
|
2026-04-02 10:49:08 +00:00
|
|
|
"enabled": true,
|
|
|
|
|
"mode": "bytes"
|
2026-03-05 06:53:26 +00:00
|
|
|
},
|
2026-04-26 04:44:05 +00:00
|
|
|
"serial": {
|
|
|
|
|
"enabled": false
|
|
|
|
|
},
|
2026-04-01 04:21:21 +00:00
|
|
|
"send_tts": {
|
|
|
|
|
"enabled": false
|
|
|
|
|
},
|
2026-03-05 06:53:26 +00:00
|
|
|
"spawn": {
|
|
|
|
|
"enabled": true
|
|
|
|
|
},
|
|
|
|
|
"spi": {
|
|
|
|
|
"enabled": false
|
|
|
|
|
},
|
|
|
|
|
"subagent": {
|
|
|
|
|
"enabled": true
|
|
|
|
|
},
|
|
|
|
|
"web_fetch": {
|
|
|
|
|
"enabled": true
|
|
|
|
|
},
|
|
|
|
|
"write_file": {
|
|
|
|
|
"enabled": true
|
2026-02-04 11:06:13 +00:00
|
|
|
}
|
|
|
|
|
},
|
2026-02-13 07:19:37 +00:00
|
|
|
"heartbeat": {
|
|
|
|
|
"enabled": true,
|
|
|
|
|
"interval": 30
|
|
|
|
|
},
|
2026-02-14 05:56:08 +00:00
|
|
|
"devices": {
|
|
|
|
|
"enabled": false,
|
|
|
|
|
"monitor_usb": true
|
|
|
|
|
},
|
2026-03-07 14:49:33 +00:00
|
|
|
"voice": {
|
2026-03-22 13:04:10 +00:00
|
|
|
"model_name": "",
|
2026-03-07 14:49:33 +00:00
|
|
|
"echo_transcription": false
|
|
|
|
|
},
|
2026-03-22 11:21:58 +00:00
|
|
|
"hooks": {
|
|
|
|
|
"enabled": true,
|
|
|
|
|
"defaults": {
|
|
|
|
|
"observer_timeout_ms": 500,
|
|
|
|
|
"interceptor_timeout_ms": 5000,
|
|
|
|
|
"approval_timeout_ms": 60000
|
|
|
|
|
}
|
|
|
|
|
},
|
2026-04-26 09:41:00 +00:00
|
|
|
"events": {
|
|
|
|
|
"logging": {
|
|
|
|
|
"enabled": true,
|
|
|
|
|
"include": ["agent.*"],
|
|
|
|
|
"exclude": [],
|
|
|
|
|
"min_severity": "info",
|
|
|
|
|
"include_payload": false
|
|
|
|
|
}
|
|
|
|
|
},
|
2026-02-04 11:06:13 +00:00
|
|
|
"gateway": {
|
2026-03-23 05:14:53 +00:00
|
|
|
"_comment": "Default log level is set to 'fatal'. Other available options are 'debug', 'info', 'warn' and 'error'.",
|
2026-04-14 04:43:49 +00:00
|
|
|
"host": "localhost",
|
2026-03-17 10:46:00 +00:00
|
|
|
"port": 18790,
|
2026-03-23 05:14:53 +00:00
|
|
|
"hot_reload": false,
|
|
|
|
|
"log_level": "fatal"
|
2026-02-04 11:06:13 +00:00
|
|
|
}
|
2026-02-18 08:30:30 +00:00
|
|
|
}
|