Different channels could theoretically share the same chat_id.
Check both channel and chat_id to avoid cross-channel reply issues.
Co-authored-by: layla <111667698+04cb@users.noreply.github.com>
When the message tool is used to send a message to a different chat_id
than the current conversation, it was incorrectly including the default
message_id from the original context. This caused channels like Feishu
to send the message as a reply to the original chat instead of creating
a new message in the target chat.
Changes:
- Only use default message_id when chat_id matches the default context
- When targeting a different chat, set message_id to None to avoid
unintended reply behavior
Address PR review feedback by avoiding an async method reference as the OpenAI client api_key.
Initialize the client with a placeholder key, refresh the Copilot token before each chat/chat_stream call, and update the runtime client api_key before dispatch.
Add a regression test that verifies the client api_key is refreshed to a real string before chat requests.
Generated with GitHub Copilot, GPT-5.4.
Implement the real GitHub device flow and Copilot token exchange for the GitHub Copilot provider.
Also route github-copilot models through a dedicated backend and strip the provider prefix before API requests.
Add focused regression coverage for provider wiring and model normalization.
Generated with GitHub Copilot, GPT-5.4.
Remove the fragile barrier-based synchronization that could cause
deadlock when the second request is scheduled first. Instead, rely
on the session lock for serialization and handle either execution
order in assertions.
1. Fix full_url path for non-image media to require AES key and skip download when missing,
instead of persisting encrypted bytes as valid media.
2. Restrict quoted media fallback trigger to only when no top-level media item exists,
not when top-level media download/decryption fails.
* feat(discord): channel-side read receipt and subagent indicator
- Add 👀 reaction on message receipt, removed after bot reply
- Add 🔧 reaction on first progress message, removed on final reply
- Both managed purely in discord.py channel layer, no subagent.py changes
- Config: read_receipt_emoji, subagent_emoji with sensible defaults
Addresses maintainer feedback on HKUDS/nanobot#2330
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(discord): add both reactions on inbound, not on progress
_progress flag is for streaming chunks, not subagent lifecycle.
Add 👀 + 🔧 immediately on message receipt, clear both on final reply.
* fix: remove stale _subagent_active reference in _clear_reactions
* fix(discord): clean up reactions on message handling failure
Previously, if _handle_message raised an exception, pending reactions
(read receipt + subagent indicator) would remain on the user's message
indefinitely since send() — which handles normal cleanup — would never
be called.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* refactor(discord): replace subagent_emoji with delayed working indicator
- Rename subagent_emoji → working_emoji (honest naming: not tied to
subagent lifecycle)
- Add working_emoji_delay (default 2s) — cosmetic delay so 🔧 appears
after 👀, cancelled if bot replies before delay fires
- Clean up: cancel pending task + remove both reactions on reply/error
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Introduce a CompositeHook that fans out lifecycle callbacks to an
ordered list of AgentHook instances with per-hook error isolation.
Extract the nested _LoopHook and _SubagentHook to module scope as
public LoopHook / SubagentHook so downstream users can subclass or
compose them. Add `hooks` parameter to AgentLoop.__init__ for
registering custom hooks at construction time.
Closes#2603
Make the fixed-session API surface explicit, document its usage, exclude api/ from core agent line counts, and remove implicit aiohttp pytest fixture dependencies from API tests.
Require a single user message, reject mismatched models, document the OpenAI-compatible API, and exclude api/ from core agent line counts so the interface matches nanobot's minimal fixed-session runtime.
Reject mismatched models and require a single user message so the OpenAI-compatible endpoint reflects the fixed-session nanobot runtime without extra compatibility noise.
Read serve host, port, and timeout from config by default, keep CLI flags higher priority, and bind the API to localhost by default for safer local usage.
Expose OpenAI-compatible chat completions and models endpoints through a single persistent API session, keeping the integration simple without adding multi-session isolation yet.