The slackify_markdown library misses several patterns that LLMs commonly
produce, causing raw Markdown symbols (**bold**, ##headers) to appear
in Slack messages.
Add _fixup_mrkdwn() post-processor that:
- Converts leftover **bold** patterns (e.g. **Status:**OK where closing
** is adjacent to non-space chars)
- Fixes & over-escaping in bare URLs
- Protects code blocks from false-positive fixups
Co-authored-by: Cursor <cursoragent@cursor.com>
- Defer Brave API key resolution to execute() time instead of __init__,
so env var or config changes take effect without gateway restart
- Improve error message to reference actual config path
(tools.web.search.apiKey) instead of only mentioning env var
Fixes#1069 (issues 1 and 2 of 3)
Previously, `autoReplyEnabled=false` would block ALL email sends,
including proactive emails triggered from other channels (e.g., asking
nanobot on Feishu to send an email).
Now `autoReplyEnabled` only controls automatic replies to incoming
emails, not proactive sends. This allows users to disable auto-replies
while still being able to ask nanobot to send emails on demand.
Changes:
- Check if recipient is in `_last_subject_by_chat` to determine if
it's a reply
- Only skip sending when it's a reply AND auto_reply_enabled is false
- Add test for proactive send with auto_reply_enabled=false
- Update existing test to verify reply behavior
_sanitize_messages strips all non-standard keys from messages, including
reasoning_content. Thinking-enabled models like Moonshot Kimi k2.5
require reasoning_content to be present in assistant tool call messages
when thinking mode is on, causing a BadRequestError (#1014).
Add reasoning_content to _ALLOWED_MSG_KEYS so it passes through
sanitization when present.
Fixes#1014
Previously, WebSearchTool cached the API key in __init__, so keys added
to config.json or env vars after gateway startup were never picked up.
This caused a confusing 'BRAVE_API_KEY not configured' error even after
the key was correctly set (issue #1069).
Changes:
- Store the init-time key separately, resolve via property at each call
- Improve error message to guide users toward the correct fix
Closes#1069
Always provide an explicit httpx client to prevent MCP HTTP transport from inheriting httpx's default 5-second timeout, thereby avoiding conflicts with the upper layer tool's timeout settings.
Fixes#1042. When the LLM returns tool call arguments as a dict or
JSON string instead of parsed values, memory consolidation would fail
with "TypeError: data must be str, not dict".
Changes:
- Add type guard in MemoryStore.consolidate() to parse string arguments
and reject unexpected types gracefully
- Add regression tests covering dict args, string args, and edge cases
Each Slack thread now gets its own conversation session instead of
sharing one session per channel. DM sessions are unchanged.
Added as a generic feature to also support if Feishu threads support
is added in the future.