1462 Commits

Author SHA1 Message Date
Xubin Ren
4a7d7b8823 feat(cron): inherit agent timezone for default schedules
Make cron use the configured agent timezone when a cron expression omits tz or a one-shot ISO time has no offset. This keeps runtime context, heartbeat, and scheduling aligned around the same notion of time.

Made-with: Cursor
2026-03-25 22:07:14 +08:00
Xubin Ren
13d6c0ae52 feat(config): add configurable timezone for runtime context
Add agent-level timezone configuration with a UTC default, propagate it into runtime context and heartbeat prompts, and document valid IANA timezone usage in the README.
2026-03-25 22:07:14 +08:00
flobo3
ef10df9acb fix(providers): add max_completion_tokens for openai o1 compatibility 2026-03-25 16:57:02 +08:00
Xubin Ren
b5302b6f3d refactor(provider): preserve extra_content verbatim for Gemini thought_signature round-trip
Replace the flatten/unflatten approach (merging extra_content.google.*
into provider_specific_fields then reconstructing) with direct pass-through:
parse extra_content as-is, store on ToolCallRequest.extra_content, serialize
back untouched.  This is lossless, requires no hardcoded field names, and
covers all three parsing branches (str, dict, SDK object) plus streaming.
2026-03-25 10:00:29 +08:00
Yohei Nishikubo
af84b1b8c0 fix(Gemini): update ToolCallRequest and OpenAICompatProvider to handle thought signatures in extra_content 2026-03-25 10:00:29 +08:00
Yohei Nishikubo
7b720ce9f7 feat(OpenAICompatProvider): enhance tool call handling with provider-specific fields 2026-03-25 10:00:29 +08:00
Xubin Ren
263069583d fix(provider): accept plain text OpenAI-compatible responses
Handle string and dict-shaped responses from OpenAI-compatible backends so non-standard providers no longer crash on missing choices fields. Add regression tests to keep SDK, dict, and plain-text parsing paths aligned.
2026-03-25 01:22:21 +00:00
Seeratul
321214e2e0 Update group policy explanation in README
Clarified instructions for group policy behavior in README.
2026-03-25 09:08:10 +08:00
Seeratul
b7df3a0aea Update README with group policy clarification
Clarify group policy behavior for bot responses in group channels.
2026-03-25 09:08:10 +08:00
xcosmosbox
0ccfcf6588 fix(WeiXin): version migration 2026-03-25 02:58:19 +08:00
xcosmosbox
0dad6124a2 chore(WeiXin): version migration and compatibility update 2026-03-25 02:58:19 +08:00
xcosmosbox
48902ae95a fix(WeiXin): auto-refresh expired QR code during login to improve success rate 2026-03-25 02:58:19 +08:00
xcosmosbox
1f5492ea9e fix(WeiXin): persist _context_tokens with account.json to restore conversations after restart 2026-03-25 02:58:19 +08:00
xcosmosbox
9c872c3458 fix(WeiXin): resolve polling issues in WeiXin plugin
- Prevent repeated retries on expired sessions in the polling thread
- Stop sending messages to invalid agent sessions to eliminate noise logs and unnecessary requests
2026-03-25 02:58:19 +08:00
xcosmosbox
3a9d6ea536 feat(WeXin): add route_tag property to adapt to WeChat official ilinkai 1.0.3 requirements 2026-03-25 02:58:19 +08:00
Xubin Ren
7b31af2204 docs: update news section 2026-03-24 18:11:50 +00:00
Xubin Ren
c3031c9cb8 docs: update news section about litellm 2026-03-24 18:11:03 +00:00
Xubin Ren
3dfdab704e refactor: replace litellm with native openai + anthropic SDKs
- Remove litellm dependency entirely (supply chain risk mitigation)
- Add AnthropicProvider (native SDK) and OpenAICompatProvider (unified)
- Merge CustomProvider into OpenAICompatProvider, delete custom_provider.py
- Add ProviderSpec.backend field for declarative provider routing
- Remove _resolve_model, find_gateway, find_by_model (dead heuristics)
- Pass resolved spec directly into provider — zero internal lookups
- Stub out litellm-dependent model database (cli/models.py)
- Add anthropic>=0.45.0 to dependencies, remove litellm
- 593 tests passed, net -1034 lines
2026-03-25 01:58:48 +08:00
Xubin Ren
38ce054b31 fix(security): pin litellm and add supply chain advisory note 2026-03-24 15:55:43 +00:00
chengyongru
72acba5d27 refactor(tests): optimize unit test structure 2026-03-24 15:12:22 +08:00
Xubin Ren
d25985be0b fix(filesystem): clarify optional tool argument handling
Keep the mypy-friendly optional execute signatures while returning clearer errors for missing arguments and locking that behavior with regression tests.

Made-with: Cursor
2026-03-24 11:49:10 +08:00
19emtuck
d4a7194c88 remove some none used f string 2026-03-24 11:49:10 +08:00
19emtuck
69f1dcdba7 proposal to adopt mypy some e.g. interfaces problems 2026-03-24 11:49:10 +08:00
Xubin Ren
c00e64a817
Merge PR #2386: feat(channel): enhance Telegram, QQ, Feishu, and WhatsApp
feat: telegram/qq/whatsapp/feishu enhancement
2026-03-24 11:40:15 +08:00
Xubin Ren
a96dd8babb Merge branch 'main' into feat/channel_enhancement
Keep the channel enhancements aligned with the current codebase while preserving a simpler product surface. This keeps QQ, Feishu, Telegram, and WhatsApp improvements together, removes the extra Telegram-only tool hint toggle, and makes WhatsApp mention-only groups actually work.
2026-03-24 03:33:44 +00:00
Xubin Ren
14763a6ad1 fix(provider): accept canonical and alias provider names consistently 2026-03-24 03:03:59 +00:00
Xubin Ren
d454386f32 docs(weixin): clarify source-only installation in README 2026-03-24 02:51:50 +00:00
Xubin Ren
b5c95b1a34
Merge PR #2204: fix(cron): scope cron state to each workspace with safe default-only migration
fix(cron): scope cron state to each workspace with safe default-only migration
2026-03-24 10:46:49 +08:00
Xubin Ren
186357e80c Merge branch 'main' into fix/workspace-scoped-cron-store
Keep cron state workspace-scoped while only migrating legacy jobs into the default workspace. This preserves seamless upgrades for existing installs without polluting intentionally new workspaces.
2026-03-24 02:41:58 +00:00
Xubin Ren
1d58c9b9e1 docs: update channel table and add plugin dev note 2026-03-23 17:17:10 +00:00
Xubin Ren
25288f9951 feat(whatsapp): add outbound media support via bridge 2026-03-24 01:11:33 +08:00
Xubin Ren
bef88a5ea1 docs: require explicit channel login command 2026-03-24 01:11:33 +08:00
Xubin Ren
d164548d9a docs(weixin): add setup guide and focused channel tests 2026-03-24 01:11:33 +08:00
Xubin Ren
0ca639bf22 fix(cli): use discovered class for channel login 2026-03-24 01:11:33 +08:00
chengyongru
556b21d011 refactor(channels): abstract login() into BaseChannel, unify CLI commands
Move channel-specific login logic from CLI into each channel class via a
new `login(force=False)` method on BaseChannel. The `channels login <name>`
command now dynamically loads the channel and calls its login() method.

- WeixinChannel.login(): calls existing _qr_login(), with force to clear saved token
- WhatsAppChannel.login(): sets up bridge and spawns npm process for QR login
- CLI no longer contains duplicate login logic per channel
- Update CHANNEL_PLUGIN_GUIDE to document the login() hook

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 01:11:33 +08:00
ZhangYuanhan-AI
11e1bbbab7 feat(weixin): add outbound media file sending via CDN upload
Previously the WeChat channel's send() method only handled text messages,
completely ignoring msg.media. When the agent called message(media=[...]),
the file was never delivered to the user.

Implement the full WeChat CDN upload protocol following the reference
@tencent-weixin/openclaw-weixin v1.0.2:
  1. Generate a client-side AES-128 key (16 random bytes)
  2. Call getuploadurl with file metadata + hex-encoded AES key
  3. AES-128-ECB encrypt the file and POST to CDN with filekey param
  4. Read x-encrypted-param from CDN response header as download param
  5. Send message with the media item (image/video/file) referencing
     the CDN upload

Also adds:
- _encrypt_aes_ecb() for AES-128-ECB encryption (reverse of existing
  _decrypt_aes_ecb)
- Media type detection from file extension (image/video/file)
- Graceful error handling: failed media sends notify the user via text
  without blocking subsequent text delivery

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 01:11:33 +08:00
ZhangYuanhan-AI
8abbe8a6df fix(agent): instruct LLM to use message tool for file delivery
During testing, we discovered that when a user requests the agent to
send a file (e.g., "send me IMG_1115.png"), the agent would call
read_file to view the content and then reply with text claiming
"file sent" — but never actually deliver the file to the user.

Root cause: The system prompt stated "Reply directly with text for
conversations. Only use the 'message' tool to send to a specific
chat channel", which led the LLM to believe text replies were
sufficient for all responses, including file delivery.

Fix: Add an explicit IMPORTANT instruction in the system prompt
telling the LLM it MUST use the 'message' tool with the 'media'
parameter to send files, and that read_file only reads content
for its own analysis.

Co-Authored-By: qulllee <qullkui@tencent.com>
2026-03-24 01:11:33 +08:00
qulllee
bc9f861bb1 feat: add media message support in agent context and message tool
Cherry-picked from PR #2355 (ad128a7) — only agent/context.py and agent/tools/message.py.

Co-Authored-By: qulllee <qullkui@tencent.com>
2026-03-24 01:11:33 +08:00
ZhangYuanhan-AI
ebc4c2ec35 feat(weixin): add personal WeChat channel via ilinkai HTTP long-poll API
Add a new WeChat (微信) channel that connects to personal WeChat using
the ilinkai.weixin.qq.com HTTP long-poll API. Protocol reverse-engineered
from @tencent-weixin/openclaw-weixin v1.0.2.

Features:
- QR code login flow (nanobot weixin login)
- HTTP long-poll message receiving (getupdates)
- Text message sending with proper WeixinMessage format
- Media download with AES-128-ECB decryption (image/voice/file/video)
- Voice-to-text from WeChat + Groq Whisper fallback
- Quoted message (ref_msg) support
- Session expiry detection and auto-pause
- Server-suggested poll timeout adaptation
- Context token caching for replies
- Auto-discovery via channel registry

No WebSocket, no Node.js bridge, no local WeChat client needed — pure
HTTP with a bot token obtained via QR code scan.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 01:11:33 +08:00
Xubin Ren
2056061765 refine heartbeat session retention boundaries 2026-03-24 00:33:43 +08:00
flobo3
ba0a3d14d9 fix: clear heartbeat session to prevent token overflow
(cherry picked from commit 5c871d75d5b1aac09a8df31e6d1e04ee3d9b0d2c)
2026-03-24 00:33:43 +08:00
Eric Yang
84a7f8af73 refactor(shell): fix syntax error 2026-03-24 00:02:49 +08:00
Eric Yang
e2e1c9c276 refactor(shell): use finally block to reap zombie processes on timeoutx 2026-03-24 00:02:49 +08:00
Eric Yang
dbcc7cb539 refactor(shell): use finally block to reap zombie processes on timeout 2026-03-24 00:02:49 +08:00
Eric Yang
e423ceef9c fix(shell): reap zombie processes when command timeout kills subprocess 2026-03-24 00:02:49 +08:00
gem12
97fe9ab7d4 feat(agent): replace global lock with per-session locks for concurrent dispatch
Replace the single _processing_lock (asyncio.Lock) with per-session locks
so that different sessions can process LLM requests concurrently, while
messages within the same session remain serialised.

An optional global concurrency cap is available via the
NANOBOT_MAX_CONCURRENT_REQUESTS env var (default 3, <=0 for unlimited).

Also re-binds tool context before each tool execution round to prevent
concurrent sessions from clobbering each other's routing info.

Tested in production and manually reviewed.

(cherry picked from commit c397bb4229e8c3b7f99acea7ffe4bea15e73e957)
2026-03-23 18:57:03 +08:00
Xubin Ren
20494a2c52 refactor command routing for future plugins and clearer CLI structure 2026-03-23 16:48:42 +08:00
kohath
4145f3eacc feat(feishu): add thread reply support for topic group messages 2026-03-23 15:52:14 +08:00
flobo3
b14d5a0a1d feat(whatsapp): add group_policy to control bot response behavior in groups 2026-03-23 15:48:51 +08:00
chengyongru
e4137736f6 fix(qq): handle file:// URI on Windows in _read_media_bytes
urlparse on Windows puts the path in netloc, not path. Use
(parsed.path or parsed.netloc) to get the correct raw path.
2026-03-23 15:48:31 +08:00