Add tiers, continuation, fetch cooldown, persistent action log, voice read, batch MCP

This commit is contained in:
Fisto
2026-09-11 15:53:06 +02:00
parent 82f78bb2b4
commit 8e8c15e8bc
17 changed files with 669 additions and 139 deletions
+68 -20
View File
@@ -1,27 +1,31 @@
# Communication
This document describes the trigger rules, the trust model, the commands, the trigger log, the
context cache, and the response policy.
This document describes the trigger rules, trust tiers, commands, the trigger log, context, the
continuation window, and the response policy.
## Trigger rules
A message is a trigger when both conditions are true:
- The author is trusted. The owner counts as trusted.
- The author is trusted. Each tier counts as trusted.
- One of these conditions is true:
- The message is a one-to-one DM to the puppet.
- The message mentions the puppet in a guild channel or a group DM.
All other messages are ignored. Untrusted messages do not enter the log at this time. The daemon
ignores bots and its own messages.
All other messages are ignored. Untrusted messages do not enter the log at this time. Bots and the
puppet's own messages are ignored.
## Trust model
The daemon processes events one at a time. This order matters for continuation windows.
The puppet has one owner and a trust list.
## Trust tiers
- The owner is always trusted. The default owner is `177117296140091393` (zzib).
- The trust list holds more user IDs.
- The owner controls the trust list. Commands from other users do not change the list.
| Tier | Meaning |
| --- | --- |
| `user` | Can trigger the puppet. This is the default tier. |
| `trusted` | Can trigger the puppet. Future chat commands need this tier. |
| `admin` | Can manage the trust list and the config. The owner is always an admin. |
The owner controls the trust list. Commands from other users do not change the list.
## Commands
@@ -30,14 +34,15 @@ mention the puppet first.
| Command | Effect |
| --- | --- |
| `whitelist list` | Show the owner and the trusted users. |
| `whitelist add @user` | Add one or more users to the trust list. |
| `whitelist list` | Show the owner and the trusted users with their tiers. |
| `whitelist add @user [user\|trusted\|admin]` | Add one or more users. The default tier is `user`. |
| `whitelist remove @user` | Remove one or more users from the trust list. |
Notes:
- The owner cannot be removed.
- The command accepts mentions and raw user IDs.
- `whitelist` commands need the admin tier.
- The reply follows the response policy.
## Response policy
@@ -62,7 +67,7 @@ The log has two ring buffers.
| Buffer | Limit | Content |
| --- | --- | --- |
| Trusted | 100 entries | Triggers from the owner and trusted users |
| Trusted | 100 entries | Triggers from trusted users |
| Untrusted | 30 entries | Reserved. No triggers enter this buffer at this time. |
One entry holds these fields:
@@ -78,7 +83,7 @@ One entry holds these fields:
| `timestamp` | The message timestamp |
| `trusted` | True for a trusted author |
| `command` | The parsed command text, when the message looks like a command |
| `context` | Prior messages. Present on mention triggers. |
| `context` | Prior messages. Present on mention triggers. Follow-ups join this list. |
## Context
@@ -87,7 +92,8 @@ The daemon collects prior messages for a mention trigger. Direct messages do not
- Message limit: `contextMessages`, default 15.
- Character limit: `contextChars`, default 4000.
- The lower limit stops the collection.
- The content is the message text and the attachment file names. Media bodies stay on Discord.
- Each line holds a time stamp, the author, the message text, and attachment file names.
- Media bodies stay on Discord.
- The trigger message is not part of its own context.
The cache makes the fetch small.
@@ -97,6 +103,9 @@ The cache makes the fetch small.
3. It merges the new messages into the cache.
4. It assembles the context from the merged list.
The fetch cooldown stops a burst of queries. The setting `fetchCooldownSeconds` (default 5) is the
minimum gap between two fetches for one channel.
Cache settings:
| Setting | Default |
@@ -107,15 +116,53 @@ Cache settings:
Eviction removes the least recently written channel files until the folder fits the size limit.
## Continuation window
A user can send a second message right after a request. The second message often adds a missing
detail. The daemon appends such messages to the request context.
- Window: `continuationSeconds`, default 10.
- The window starts at the trigger and resets on each follow-up.
- Only messages from the same author in the same channel count.
- A follow-up does not need a mention.
- A follow-up needs a trusted author.
## Action log
The daemon writes a persistent log beside the state file: `actions.jsonl`. One JSON line holds one
event. The log rotates at the size limit.
| Event | Content |
| --- | --- |
| `trigger` | Message ID, channel, guild, author, tier, command, context count |
| `continuation` | Follow-up message ID and the parent entry ID |
| `command` | Command text, requester, result |
| `reply` | Command, mode, target, result, error |
| `error` | Scope and message |
Secret-looking strings are redacted before the write. Discord token shapes and `mfa.` strings
become `[redacted]`.
Settings:
| Setting | Default |
| --- | --- |
| `VESKSLOP_ACTION_LOG` | `<state dir>/actions.jsonl` |
| `VESKSLOP_ACTION_LOG_MAX_BYTES` | 5 MiB |
Read the log with the `get_action_log` MCP tool.
## Event flow
1. The client receives a `MESSAGE_CREATE` gateway event.
2. The core normalizes the event.
3. The core bridge pushes the event to the daemon.
4. The daemon applies the trigger rules.
5. The daemon collects context for a mention trigger.
6. The daemon adds the entry to the log.
7. The daemon runs a trusted command and replies through the response policy.
4. The daemon queues the event. Events run one at a time.
5. The daemon drops a replayed event.
6. The daemon applies the trigger rules.
7. The daemon collects context for a mention trigger.
8. The daemon adds the entry to the log and writes the action log.
9. The daemon runs a trusted command and replies through the response policy.
## State file
@@ -123,7 +170,8 @@ The daemon stores the owner ID, the trust list, and the config in JSON.
- Default path: `poc/.veskslop-state.json`.
- Override: `VESKSLOP_STATE_FILE`.
- The trigger log is in memory only. The log resets at restart.
- The trust list is an object: user ID to tier.
- The trigger log is in memory only. The action log is persistent.
## How to add a trigger rule or a command
+2
View File
@@ -57,6 +57,7 @@ Event line:
| `ping` | none | `"pong"` |
| `events.subscribe` | none | `{ "subscribed": true }`. The socket becomes an event subscriber. |
| `state.get` | none | The current user, the guilds, and the channels. Cache-only. |
| `voice.get` | optional `userId`, optional `guildId` | The voice channel and its members, or `channelId: null` |
| `message.send` | `channelId`, `content` | `{ channelId, sent: true }` |
| `message.read` | `channelId`, `limit` | `{ cached, messages }`. Cache-only. |
| `message.fetch` | `channelId`, `limit`, optional `before` or `after` | `{ fetched, messages }`. Fetches from Discord. |
@@ -76,6 +77,7 @@ The core validates all input. The daemon cannot bypass these rules.
- `limit` must be an integer from 1 to 100.
- `before` and `after` must be snowflakes. They are mutually exclusive. `message.fetch` uses them
to walk history.
- `voice.get` accepts snowflakes only. It reads the client cache. It never joins a call.
- A request line must not be larger than 64 KiB.
## Core rate limit
+6
View File
@@ -10,6 +10,7 @@ The daemon runs outside Vesktop. It holds all logic. It talks to the core bridge
| `poc/src/puppet.ts` | Trust list, command handling, trigger log, response policy | Implemented |
| `poc/src/communication.ts` | Pure log, parser, and context logic | Implemented |
| `poc/src/message-cache.ts` | Channel message cache in a tmp folder | Implemented |
| `poc/src/action-log.ts` | Persistent JSONL action log with rotation | Implemented |
| `poc/src/pacing.ts` | Paced queue and query coalescing | Implemented |
| `poc/src/core-client.ts` | Client actions over the core bridge | Implemented (primary transport) |
| `poc/src/cdp-client.ts` | Chrome DevTools Protocol client | Development fallback |
@@ -48,7 +49,10 @@ The daemon exposes MCP over Streamable HTTP. The default address is `http://127.
| `send_message` | Send a message to a channel. |
| `read_messages` | Read cached messages from a channel. |
| `send_dm` | Send a DM to a user. |
| `get_voice_state` | Which voice channel a user is in and who else is there. |
| `get_message_log` | Read the trigger log. |
| `get_action_log` | Read the persistent action log. |
| `run_commands` | Run several read-only tools in one call, in order. |
| `get_context` | Assemble conversation context for a channel. Fetches new messages by default. |
| `get_puppet_config` | Read the response policy and context settings. |
| `set_puppet_config` | Change the response policy and context settings. |
@@ -94,6 +98,8 @@ CDP_EXPRESSION='...' pnpm cdp:dispatch
| --- | --- | --- |
| `VESKSLOP_SOCKET` | `$XDG_RUNTIME_DIR/vesktop-puppet.sock` | Core bridge socket |
| `VESKSLOP_STATE_FILE` | `poc/.veskslop-state.json` | Owner, trust list, and config |
| `VESKSLOP_ACTION_LOG` | `<state dir>/actions.jsonl` | Persistent action log |
| `VESKSLOP_ACTION_LOG_MAX_BYTES` | 5 MiB | Action log rotation limit |
| `VESKSLOP_CACHE_DIR` | `<tmp>/veskslop-cache` | Context cache folder |
| `VESKSLOP_CACHE_MAX_BYTES` | 50 MiB | Context cache size limit |
| `MCP_HOST` / `MCP_PORT` | `127.0.0.1` / `8788` | MCP listen address |