feat(FN-4004): add bounded room thread and mailbox reply context to agents

Adds bounded room thread context and mailbox reply context to the chat system, implemented in `agent-tools.ts` with corresponding dashboard room handling in `chat.ts`; includes expanded test coverage for both modules and updated documentation in `agents.md`.

Fusion-Task-Id: FN-4004
This commit is contained in:
Fusion
2026-05-11 07:34:34 -07:00
committed by gsxdsm
parent 1257155a6f
commit 118e466104
7 changed files with 260 additions and 9 deletions

View File

@@ -748,8 +748,9 @@ When messaging tools are enabled for an agent, heartbeat runs check for unread m
Mailbox replies use `message.metadata.replyTo.messageId` as the stable reply link.
- `read_messages` includes each message ID in its human-readable output so agents can target a specific message.
- `send_message` supports `reply_to_message_id`; when provided, the sent message is stored with `metadata.replyTo.messageId`.
- `fn_read_messages` includes each message ID in its human-readable output so agents can target a specific message.
- When a message has `metadata.replyTo.messageId`, `fn_read_messages` now includes one-level reply-parent context inline (and in structured tool details) so heartbeat/mailbox runs can understand what the message is replying to without expanding full threads.
- `fn_send_message` supports `reply_to_message_id`; when provided, the sent message is stored with `metadata.replyTo.messageId`.
- Heartbeat prompts explicitly instruct agents to include `reply_to_message_id` when replying.
The dashboard mailbox UI also uses the same metadata contract when users click **Reply**, so user and agent replies share one threading model.

View File

@@ -114,6 +114,7 @@ Chat Rooms are project-scoped group conversations for multiple agents. They are
- After a successful room send, the room composer is cleared (matching direct-chat composer behavior) so stale text is not left in the input.
- On mobile, room threads use the same keyboard-aware thread anchoring as direct chat, keeping the composer pinned above the soft keyboard while typing.
- The dashboard backend now orchestrates room responders on that POST: mentioned members are routed as direct responders, additional ambient members may reply (up to the room ambient responder cap), and each assistant reply is persisted with `senderAgentId` via `chatStore.addRoomMessage(...)`.
- Room responder prompt construction now includes a bounded recent room transcript (role, sender label, timestamp, content) plus an explicit latest-user-message marker, so replies stay thread-aware without unbounded prompt growth.
- The UI still avoids optimistic room echo; after `POST /api/chat/rooms/:id/messages`, it immediately re-fetches authoritative room messages to surface persisted user/assistant replies even if SSE delivery is delayed, and it continues to apply `chat:room:message:*` SSE updates for live fan-out.
- Relationship summary: direct Chat runs one target (agent or model) per session; rooms are shared threads with multiple agent members and now use the same message contract as direct Chat; Quick Chat stays a floating single-target panel and does not host rooms.
- For backend details, see the [Chat Room REST API reference](./architecture.md#real-time-channels) and the [chat room storage schema (`chat_rooms`, `chat_room_members`, `chat_room_messages`)](./storage.md#chat-rooms-migration-70).