Merge pull request #6 from Athemis/feat/matrix-improvements

feat(matrix): E2E, typing, markdown/HTML, group policy, inbound+outbound media, thread replies
This commit is contained in:
TANISH RAJPUT
2026-02-20 23:01:56 +05:30
committed by GitHub
6 changed files with 2494 additions and 29 deletions

View File

@@ -301,6 +301,73 @@ nanobot gateway
</details>
<details>
<summary><b>Matrix (Element)</b></summary>
Uses Matrix sync via `matrix-nio` (inbound media + outbound file attachments).
**1. Create/choose a Matrix account**
- Create or reuse a Matrix account on your homeserver (for example `matrix.org`).
- Confirm you can log in with Element.
**2. Get credentials**
- You need:
- `userId` (example: `@nanobot:matrix.org`)
- `accessToken`
- `deviceId` (recommended so sync tokens can be restored across restarts)
- You can obtain these from your homeserver login API (`/_matrix/client/v3/login`) or from your client's advanced session settings.
**3. Configure**
```json
{
"channels": {
"matrix": {
"enabled": true,
"homeserver": "https://matrix.org",
"userId": "@nanobot:matrix.org",
"accessToken": "syt_xxx",
"deviceId": "NANOBOT01",
"e2eeEnabled": true,
"allowFrom": [],
"groupPolicy": "open",
"groupAllowFrom": [],
"allowRoomMentions": false,
"maxMediaBytes": 20971520
}
}
}
```
> `allowFrom`: Empty allows all senders; set user IDs to restrict access.
> `groupPolicy`: `open`, `mention`, or `allowlist`.
> `groupAllowFrom`: Room allowlist used when `groupPolicy` is `allowlist`.
> `allowRoomMentions`: If `true`, accepts `@room` (`m.mentions.room`) in mention mode.
> `e2eeEnabled`: Enables Matrix E2EE support (default `true`); set `false` only for plaintext-only setups.
> `maxMediaBytes`: Max attachment size in bytes (default `20MB`) for inbound and outbound media handling; set to `0` to block all inbound and outbound attachment uploads.
> [!NOTE]
> Matrix E2EE implications:
>
> - Keep a persistent `matrix-store` and stable `deviceId`; otherwise encrypted session state can be lost after restart.
> - In newly joined encrypted rooms, initial messages may fail until Olm/Megolm sessions are established.
> - With `e2eeEnabled=false`, encrypted room messages may be undecryptable and E2EE send safeguards are not applied.
> - With `e2eeEnabled=true`, the bot sends with `ignore_unverified_devices=true` (more compatible, less strict than verified-only sending).
> - Changing `accessToken`/`deviceId` effectively creates a new device and may require session re-establishment.
> - Outbound attachments are sent from `OutboundMessage.media`.
> - Effective media limit (inbound + outbound) uses the stricter value of local `maxMediaBytes` and homeserver `m.upload.size` (if advertised).
> - If `tools.restrictToWorkspace=true`, Matrix outbound attachments are limited to files inside the workspace.
**4. Run**
```bash
nanobot gateway
```
</details>
<details>
<summary><b>WhatsApp</b></summary>

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,8 @@
"""Configuration schema using Pydantic."""
from pathlib import Path
from typing import Literal
from pydantic import BaseModel, Field, ConfigDict
from pydantic.alias_generators import to_camel
from pydantic_settings import BaseSettings
@@ -60,6 +62,26 @@ class DiscordConfig(Base):
intents: int = 37377 # GUILDS + GUILD_MESSAGES + DIRECT_MESSAGES + MESSAGE_CONTENT
class MatrixConfig(Base):
"""Matrix (Element) channel configuration."""
enabled: bool = False
homeserver: str = "https://matrix.org"
access_token: str = ""
user_id: str = "" # @bot:matrix.org
device_id: str = ""
# Enable Matrix E2EE support (encryption + encrypted room handling).
e2ee_enabled: bool = True
# Max seconds to wait for sync_forever to stop gracefully before cancellation fallback.
sync_stop_grace_seconds: int = 2
# Max attachment size accepted for Matrix media handling (inbound + outbound).
max_media_bytes: int = 20 * 1024 * 1024
allow_from: list[str] = Field(default_factory=list)
group_policy: Literal["open", "mention", "allowlist"] = "open"
group_allow_from: list[str] = Field(default_factory=list)
allow_room_mentions: bool = False
class EmailConfig(Base):
"""Email channel configuration (IMAP inbound + SMTP outbound)."""
@@ -176,6 +198,7 @@ class ChannelsConfig(Base):
email: EmailConfig = Field(default_factory=EmailConfig)
slack: SlackConfig = Field(default_factory=SlackConfig)
qq: QQConfig = Field(default_factory=QQConfig)
matrix: MatrixConfig = Field(default_factory=MatrixConfig)
class AgentDefaults(Base):

View File

@@ -42,6 +42,9 @@ dependencies = [
"prompt-toolkit>=3.0.50,<4.0.0",
"mcp>=1.26.0,<2.0.0",
"json-repair>=0.57.0,<1.0.0",
"matrix-nio[e2e]>=0.25.2",
"mistune>=3.0.0,<4.0.0",
"nh3>=0.2.17,<1.0.0",
]
[project.optional-dependencies]

1279
tests/test_matrix_channel.py Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,10 @@
import pytest
from nanobot.agent.tools.message import MessageTool
@pytest.mark.asyncio
async def test_message_tool_returns_error_when_no_target_context() -> None:
tool = MessageTool()
result = await tool.execute(content="test")
assert result == "Error: No target channel/chat specified"