Selaa lähdekoodia

docs(chatto): name every writing tool where the room gates are stated

Both documents described the read-only rule as a property of
chatto_send_room alone, which stopped being true when pinning landed and
stops being true again with chatto_send_ephemeral. README gains the new
tool row and count; AGENTS.md states the rule over all three writing tools
and records that ephemeral posting must go through _post_chunks, since a
direct post_message call would be the copy that section exists to prevent.
Paul Klumpp 1 viikko sitten
vanhempi
commit
35850ed2e3
2 muutettua tiedostoa jossa 14 lisäystä ja 8 poistoa
  1. 9 4
      AGENTS.md
  2. 5 4
      README.md

+ 9 - 4
AGENTS.md

@@ -223,9 +223,11 @@ changes must keep them, or consciously renegotiate the docs.**
   unexpanded, so neither path needs a roster to recognise them. DMs answer
   regardless so `/join` stays reachable;
   `hermes_validate_config` rejects listing a room on both lists. The sending
-  tools obey the same lists: `chatto_send_room` refuses a channel on neither
-  (a DM room is never gated), because a tool that posted there would break the
-  read-only promise the same paragraph makes. The read tools are deliberately
+  tools obey the same lists: `chatto_send_room` and `chatto_send_ephemeral`
+  refuse a channel on neither (a DM room is never gated), because a tool that
+  posted there would break the read-only promise the same paragraph makes, and
+  `chatto_pin_message` refuses it too — a pin changes what the room shows
+  everyone even though it posts nothing. The read tools are deliberately
   exempt — `chatto_get_message` and `chatto_get_history` post nothing and
   answer nothing, so reading a room grants no privilege the bot's token did not
   already have and the server's own visibility rules are the only gate.
@@ -542,7 +544,10 @@ Three rules already exist once each, and each answers for both callers:
   into a `SendResult` and `_post_chunks` into a refusal, because those result
   contracts genuinely differ; the *sending* is the same job and must not be.
   `on_posted` is how the adapter marks its own output seen — without it the
-  realtime echo of its own message would come back as input.
+  realtime echo of its own message would come back as input. `chatto_send_ephemeral`
+  is a third caller and posts through `_post_chunks`, so it inherits the split
+  and the partial-failure refusal; a posting tool that called `post_message`
+  directly would be the copy this section exists to prevent.
 - **`_resolve_thread_root`** — "this event ID is a root of a thread in *this*
   room", which both tools taking a `thread_root_event_id` need
   (`_send_room` posting into one, `_get_history` reading one). Two copies

+ 5 - 4
README.md

@@ -43,7 +43,7 @@ Capabilities natively implemented by the Chatto plugin adapter:
 | file attachments | yes (chunked upload) |
 | image / video / audio / documents | yes (native attachments) |
 | DM participation | only once the person has DMed the bot — a bot cannot start a DM on Chatto, see [DM Initiation](#dm-initiation) |
-| plugin tools | yes (thirteen tools covering sending, reading, pinning, attachments, custom status, link previews and room groups — see [Plugin tools](#plugin-tools)) |
+| plugin tools | yes (fourteen tools covering sending, self-deleting notices, reading, pinning, attachments, custom status, link previews and room groups — see [Plugin tools](#plugin-tools)) |
 | room creation | yes |
 | room join/leave over DM | yes (`/join`, `/leave`) |
 | member directory | yes (cached) |
@@ -391,10 +391,11 @@ Two refusals by design: direct messages cannot be left, and leaving the configur
 
 ## Plugin tools
 
-Beyond answering inbound messages, the agent can act on Chatto on its own initiative. The plugin registers thirteen tools, available to the agent in the gateway and, with `hermes tools`, in the CLI:
+Beyond answering inbound messages, the agent can act on Chatto on its own initiative. The plugin registers fourteen tools, available to the agent in the gateway and, with `hermes tools`, in the CLI:
 
 | Tool | What it does |
 |------|--------------|
+| `chatto_send_ephemeral` | Posts a notice into a channel that deletes itself after `ttl_seconds` (default 60, range 5-3600), for progress or status updates that should not stay in the timeline. Same room rules as `chatto_send_room`. Deletion is best-effort: a gateway restart before the TTL expires leaves the notice behind. |
 | `chatto_list_rooms` | Lists the rooms visible to the bot with their IDs, kinds and membership. Optional `name` filters case-insensitively by substring. Useful for turning a channel name into the `platform:chat_id` address a cron `deliver` target needs. |
 | `chatto_send_room` | Posts a message into a channel or DM room, by `room_id` or `room_name`. Can post inside an existing thread (`thread_root_event_id`) or open a new one (`create_thread`). Either way the bot follows the thread afterwards, so later replies in it reach the agent. |
 | `chatto_send_dm` | Posts a message into the DM room you already have with a person, addressed by `user_id` or `user_login`. |
@@ -411,11 +412,11 @@ Beyond answering inbound messages, the agent can act on Chatto on its own initia
 
 Five boundaries are deliberate, and each tool reports them as an error instead of half-doing the job:
 
-- **A channel must be opted in.** `chatto_send_room` only posts into a room listed in `CHATTO_REQUIRE_MENTION_ROOMS` or `CHATTO_OPTIONAL_MENTION_ROOMS` (DM rooms are never gated). A room on neither list stays read-only — a human message there would never have produced output either. The refusal names both settings so you can paste the room ID into `~/.hermes/.env`. The read tools are exempt: `chatto_get_message`, `chatto_get_history`, `chatto_list_room_attachments`, `chatto_list_pinned_messages` and `chatto_list_room_groups` read any room the server lets the bot see, because reading answers nothing and posts nothing — the server's own visibility rules are the only gate.
+- **A channel must be opted in.** `chatto_send_room` and `chatto_send_ephemeral` only post into a room listed in `CHATTO_REQUIRE_MENTION_ROOMS` or `CHATTO_OPTIONAL_MENTION_ROOMS` (DM rooms are never gated). A room on neither list stays read-only — a human message there would never have produced output either. The refusal names both settings so you can paste the room ID into `~/.hermes/.env`. The read tools are exempt: `chatto_get_message`, `chatto_get_history`, `chatto_list_room_attachments`, `chatto_list_pinned_messages` and `chatto_list_room_groups` read any room the server lets the bot see, because reading answers nothing and posts nothing — the server's own visibility rules are the only gate.
 - **Pinning is a write.** `chatto_pin_message` changes what the room shows everyone, so it obeys the same opt-in rule as `chatto_send_room`: an unlisted channel refuses the pin and names both settings. A DM is never gated.
 - **The bot cannot open a DM.** Only a person can start a direct message on Chatto, so `chatto_send_dm` needs a recipient who has written to the bot at least once. To reach someone else, mention them in a channel message.
 - **A name is not an identity.** If several rooms share the name you passed, `chatto_send_room` returns their IDs and asks for `room_id` instead of picking one. Same rule as `/join #name`. The read tools resolve names by the same rule.
-- **Visible is not joined.** `chatto_list_rooms` lists rooms the bot can see, which includes channels it has not joined; check `is_member` before posting into one. `chatto_send_room` and `chatto_pin_message` refuse an unjoined room and say how to get in, because the server would reject the write with an error naming neither the room nor the fix. Reading needs no membership beyond what the server allows — a room the bot merely sees stays readable if the server permits the timeline.
+- **Visible is not joined.** `chatto_list_rooms` lists rooms the bot can see, which includes channels it has not joined; check `is_member` before posting into one. `chatto_send_room`, `chatto_send_ephemeral` and `chatto_pin_message` refuse an unjoined room and say how to get in, because the server would reject the write with an error naming neither the room nor the fix. Reading needs no membership beyond what the server allows — a room the bot merely sees stays readable if the server permits the timeline.
 
 Credentials never come from the model: no tool takes a server URL or a token as an argument, so the configured bot token cannot be pointed at another host. Inside a channel, mention people in the message text (`@login, …`) — there is no separate mention parameter.