feat(queue): add queue modes and discord gating

This commit is contained in:
Peter Steinberger
2025-12-26 13:35:44 +01:00
parent e9f1851c5d
commit 8dda07a1e9
16 changed files with 378 additions and 12 deletions

View File

@@ -85,6 +85,26 @@ Group messages default to **require mention** (either metadata mention or regex
}
```
### `routing.queue`
Controls how inbound messages behave when an agent run is already active.
```json5
{
routing: {
queue: {
mode: "interrupt", // global default: queue | interrupt | drop
bySurface: {
whatsapp: "interrupt",
telegram: "interrupt",
discord: "queue",
webchat: "queue"
}
}
}
}
```
### `discord` (bot transport)
Configure the Discord bot by setting the bot token and optional gating:
@@ -94,6 +114,10 @@ Configure the Discord bot by setting the bot token and optional gating:
discord: {
token: "your-bot-token",
allowFrom: ["discord:1234567890", "*"], // optional DM allowlist (user ids)
guildAllowFrom: {
guilds: ["123456789012345678"], // optional guild allowlist (ids)
users: ["987654321098765432"] // optional user allowlist (ids)
},
requireMention: true, // require @bot mentions in guilds
mediaMaxMb: 8 // clamp inbound media size
}

View File

@@ -22,6 +22,7 @@ Status: ready for DM and guild text channels via the official Discord bot gatewa
5. Direct chats: use `user:<id>` (or a `<@id>` mention) when delivering; all turns land in the shared `main` session.
6. Guild channels: use `channel:<channelId>` for delivery. Mentions are required by default; disable with `discord.requireMention = false`.
7. Optional DM allowlist: reuse `discord.allowFrom` with user ids (`1234567890` or `discord:1234567890`). Use `"*"` to allow all DMs.
8. Optional guild allowlist: set `discord.guildAllowFrom` with `guilds` and/or `users` to gate who can invoke the bot in servers.
Note: Discord does not provide a simple username → id lookup without extra guild context, so prefer ids or `<@id>` mentions for DM delivery targets.
@@ -38,6 +39,10 @@ Note: Discord does not provide a simple username → id lookup without extra gui
discord: {
token: "abc.123",
allowFrom: ["123456789012345678"],
guildAllowFrom: {
guilds: ["123456789012345678"],
users: ["987654321098765432"]
},
requireMention: true,
mediaMaxMb: 8
}
@@ -45,6 +50,7 @@ Note: Discord does not provide a simple username → id lookup without extra gui
```
- `allowFrom`: DM allowlist (user ids). Omit or set to `["*"]` to allow any DM sender.
- `guildAllowFrom`: Optional allowlist for guild messages. Set `guilds` and/or `users` (ids). When both are set, both must match.
- `requireMention`: when `true`, messages in guild channels must mention the bot.
- `mediaMaxMb`: clamp inbound media saved to disk.

View File

@@ -18,6 +18,33 @@ We now serialize command-based auto-replies (WhatsApp Web listener) through a ti
- When verbose logging is enabled, queued commands emit a short notice if they waited more than ~2s before starting.
- Typing indicators (`onReplyStart`) still fire immediately on enqueue so user experience is unchanged while we wait our turn.
## Queue modes (per surface)
Inbound messages can either queue or interrupt when a run is already active:
- `queue`: serialize per session; if the agent is streaming, the new message is appended to the current run.
- `interrupt`: abort the active run for that session, then run the newest message.
- `drop`: ignore the message if the session lane is busy.
Defaults (when unset in config):
- WhatsApp + Telegram → `interrupt`
- Discord + WebChat → `queue`
Configure globally or per surface via `routing.queue`:
```json5
{
routing: {
queue: {
mode: "interrupt",
bySurface: { discord: "queue", telegram: "interrupt" }
}
}
}
```
## Per-session overrides
- `/queue <mode>` as a standalone command stores the mode for the current session.
- `/queue <mode>` embedded in a message applies **once** (no persistence).
## Scope and guarantees
- Applies only to config-driven command replies; plain text replies are unaffected.
- Default lane (`main`) is process-wide for inbound + main heartbeats; set `agent.maxConcurrent` to allow multiple sessions in parallel.