@stratusagent/channel-slack 0.11.0 → 0.11.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -4,8 +4,8 @@ Slack adapter for Stratus agents. **One Slack app per agent** — Slack has no w
4
4
 
5
5
  - **Resumable conversations**: session keys are `slack:<agent>:<team>:<channel>:<thread_ts ?? ts>` (DMs: the DM channel id) — a thread is a conversation, it survives daemon restarts, and two agents sharing a thread keep fully separate sessions. A turn parked on a human when the daemon died is re-asked after the restart, and when it finishes its reply is posted into the thread as a fresh message — the placeholder it would have edited belonged to the old process.
6
6
  - **Streaming replies**: post a placeholder, edit as deltas arrive (throttled for `chat.update` limits), show `⚙ tool…` status lines, finalize with the full reply — split across messages when it outgrows one.
7
- - **Markdown is translated to Slack's mrkdwn** on the way out — `**bold**` to `*bold*`, `*italic*` to `_italic_`, `~~struck~~` to `~struck~`, `[text](https://…)` to `<https://…|text>`, and a `#` heading to a bold line, since mrkdwn has no headings. Code spans and fences are left exactly as written, an unclosed fence included, so a `**` inside a snippet stays part of the snippet — a run of N backticks opens code and only a run of exactly N closes it, which is what lets ``a span with a ` in it`` and a ````-fence holding a ```-fence work. One or two unmatched backticks are literal text, as they are in Markdown. Anything whose spelling already matches — lists, block quotes, inline code — is untouched. A marker still being streamed stays literal until its closing half arrives.
8
- - **Mention-only in channels, free-form in DMs.** Inbound mentions of other users are humanized to `@Display Name` for the model; redeliveries are deduped so a slow turn never runs twice.
7
+ - **Markdown is translated to Slack's mrkdwn** on the way out — `**bold**` to `*bold*`, `*italic*` to `_italic_`, `~~struck~~` to `~struck~`, `[text](https://…)` to `<https://…|text>`, and a `#` heading to a bold line, since mrkdwn has no headings — unless the heading already carries an asterisk of its own, which is left as it is: Slack has one bold delimiter and no way to nest it, so a second pair would print rather than render. Code spans and fences are left exactly as written, an unclosed fence included, so a `**` inside a snippet stays part of the snippet — a run of N backticks opens code and only a run of exactly N closes it, which is what lets ``a span with a ` in it`` and a ````-fence holding a ```-fence work. One or two unmatched backticks are literal text, as they are in Markdown. Anything whose spelling already matches — lists, block quotes, inline code — is untouched. A marker still being streamed stays literal until its closing half arrives.
8
+ - **Mention to start, then it stays in the thread.** A mention opens a conversation; every reply in that thread reaches the agent without tagging it again, and free-form DMs are unchanged. Who an untagged reply is for is decided by [Who a message is for](#who-a-message-is-for). Inbound mentions of other users are humanized to `@Display Name` for the model; redeliveries are deduped so a slow turn never runs twice.
9
9
  - **Approval buttons** for the gateway's `remote` permission mode: a gated tool call parks the turn and asks in its thread with **Allow once** / **Always allow** / **Deny**. See [Approving tool calls](#approving-tool-calls) — clicks are authorized by *who clicked*, never by who can see the message, and **Always allow** is offered only where the daemon would actually remember it.
10
10
  - **Tokens are gateway infrastructure secrets**, stored in the `channels` namespace of `~/.stratus/credentials.json` — never in an agent's credential allowlist:
11
11
 
@@ -19,6 +19,67 @@ Slack adapter for Stratus agents. **One Slack app per agent** — Slack has no w
19
19
  }
20
20
  ```
21
21
 
22
+ ## Who a message is for
23
+
24
+ A mention is how a conversation starts. After that, the thread is the
25
+ address — replying in it reaches the agent the way replying to a colleague
26
+ reaches them, with no `@` and no ceremony. Four rules decide the rest, and
27
+ they are the whole model:
28
+
29
+ 1. **A mention is always for whoever is named.** In a thread or out of one,
30
+ naming an agent hands it the question.
31
+ 2. **Inside a thread it is already in, an agent listens without being
32
+ named.** "Already in" means a session exists under that thread's key —
33
+ which happens only because somebody mentioned it there — so an agent
34
+ follows conversations it was brought into and nothing else. That record
35
+ is durable, so a daemon restart mid-thread forgets nothing.
36
+ 3. **The room is not a conversation.** A channel message outside any thread
37
+ is never a follow-up, however much of the channel the app can see. An
38
+ agent that has not been spoken to does not join in.
39
+ 4. **In a thread with several agents, an untagged reply goes to whoever
40
+ spoke last.** The same rule people use: you are answering the voice that
41
+ just answered you. Naming another agent moves the conversation to them —
42
+ so a handover is one `@`, and it takes effect the moment it is sent, not
43
+ whenever the turn it starts gets around to answering: an addendum typed
44
+ straight after it reaches the agent you just named, and the agent that
45
+ *had* the thread stands down at the same instant rather than whenever its
46
+ own app next catches up.
47
+
48
+ Everyone in the thread is talking to the same agent — a reply from a second
49
+ person is a follow-up like any other, and channel messages reach the model
50
+ prefixed with the speaker's display name so it knows who said what. A reply
51
+ carrying a file, or one the author also broadcast to the channel, is a
52
+ follow-up too; what Slack marks as bookkeeping — an edit, a deletion, a
53
+ join — is not, and nothing answers it. **Attachment contents are not
54
+ readable** — the app does not ask for `files:read` — so a message with files
55
+ reaches the agent naming them and saying they cannot be opened, which is
56
+ what lets it answer honestly instead of as though it had read the log. A
57
+ file dropped in with nothing said is not a question, and gets no reply. What is
58
+ *not* shared is history: sessions are per agent, so an agent tagged into a
59
+ thread halfway through starts from what it is told then, not from what the
60
+ other agent was told. Bring it up to speed in the message that tags it.
61
+
62
+ Three edges worth knowing. An agent whose app was installed before the
63
+ history scopes below is told about mentions only, and behaves exactly as it
64
+ always did — the workspace's grant is the switch, per app. Where a thread's
65
+ several agents cannot be ordered — a host whose session routing carries no
66
+ timestamps — an untagged reply is left alone rather than answered twice;
67
+ mention the one you want.
68
+
69
+ A named agent whose app is down answers nothing, and nothing answers in its
70
+ place: being tagged is a decision about who is being asked, and an agent
71
+ that has been handed the question elsewhere does not take it back because
72
+ the other one is offline. That silence is the same signal a mention has
73
+ always given when an app is down.
74
+
75
+ And the rules above are mechanical, which shows in a thread where people are
76
+ mostly talking to *each other*: an agent invited into one answers every
77
+ untagged reply in it, including the ones meant for somebody else. Give the
78
+ side conversation its own thread. Teaching an agent to read the room
79
+ instead — to follow a thread whether or not it is being spoken to, and
80
+ answer only when it has something to add — is
81
+ [roadmap step 31](../../docs/roadmap/31-reading-the-room.md).
82
+
22
83
  ## Installing
23
84
 
24
85
  This package is an **optional peer** of the CLI — `stratus` ships without any
@@ -43,6 +104,7 @@ editing `credentials.json` by hand.
43
104
  The manual equivalent, if you prefer:
44
105
 
45
106
  1. https://api.slack.com/apps → **Create New App → From a manifest** → paste `manifest/stratus-agent.manifest.json` with `NAME` replaced by the agent's name.
107
+ The manifest asks for the `channels:history` / `groups:history` / `mpim:history` scopes and the matching `message.*` events, which is what lets an agent [stay in a thread](#who-a-message-is-for) instead of needing a mention every time. An app created before those shipped needs them added under **OAuth & Permissions** and **Event Subscriptions** and reinstalled once; leave them off and it answers mentions and DMs, exactly as it did before.
46
108
  2. **Basic Information → App-Level Tokens** → generate a token with `connections:write` (that's the `appToken`, `xapp-…`).
47
109
  3. **Install App** to the workspace → copy the **Bot User OAuth Token** (that's the `botToken`, `xoxb-…`).
48
110
  4. Upload the agent's avatar under **Display Information**.
@@ -132,6 +194,49 @@ needs `settings.interactivity.is_enabled` set to `true` once, under **App
132
194
  Manifest**. No request URL is needed — the clicks arrive over the same Socket
133
195
  Mode connection.
134
196
 
197
+ ## Who counts as the operator
198
+
199
+ Everything above decides *which agent* a message is for. None of it decides
200
+ *who is speaking*: the adapter admits a message that has a user, is not a
201
+ bot, carries no bookkeeping subtype, and is a DM or a mention — and any
202
+ member of the workspace can open a DM or type an `@mention`. A DM proves
203
+ nothing about who is typing.
204
+
205
+ So a message is the operator's only when the operator has said so:
206
+
207
+ ```jsonc
208
+ {
209
+ "principals": {
210
+ "slackUsers": ["U01DYLAN"],
211
+ "agents": {
212
+ "ava": { "slackUsers": ["U01DYLAN", "U01OPS"] },
213
+ "bea": { "slackUsers": [] }
214
+ }
215
+ }
216
+ }
217
+ ```
218
+
219
+ A turn from a listed id reaches the agent as its operator's (`user`). A turn
220
+ from anyone else — in a DM as much as in a channel — reaches it as
221
+ `unknown`, and the session it lands in stays `unknown` from then on: that
222
+ text is in the transcript. Every fact the agent remembers afterwards
223
+ carries the label, and the prompt renders it under a heading that says so.
224
+ With no list at all, every Slack sender is `unknown`, and `stratus serve`
225
+ says so at startup. An agent's own entry replaces the shared list;
226
+ `"slackUsers": []` excludes an agent from it.
227
+
228
+ The sender is judged on **every message**, not once per thread. A thread
229
+ keys one session for everyone in it, so an authorized member can open one
230
+ and a stranger can mention the agent inside it afterwards — the stranger's
231
+ turn lowers the session, and the authorized member's next turn does not
232
+ raise it back.
233
+
234
+ Like `approvals`, this block is read only from a config you chose —
235
+ `--config`, `STRATUS_CONFIG`, or the global `~/.stratus/config.json`. A
236
+ project-local `stratus.config.json` cannot appoint itself the principal.
237
+ The labels themselves are documented in
238
+ [Memory](../../docs/concepts/memory.md#where-a-fact-came-from).
239
+
135
240
  ## Speaking first: the outbound seam
136
241
 
137
242
  The adapter also implements the channel contract's `resolveOutbound` — how a
package/dist/index.d.ts CHANGED
@@ -20,6 +20,17 @@ export interface SlackAgentConfig {
20
20
  * the answer already is.
21
21
  */
22
22
  approvalChannel?: string;
23
+ /**
24
+ * Slack user ids whose messages are the operator's: a turn from one of
25
+ * them arrives as `user`, a turn from anyone else as `unknown`. The
26
+ * adapter's own admission checks — has a user, is not a bot, is a DM or
27
+ * a mention — establish nothing about who is typing, since any member of
28
+ * the workspace can open a DM or type an `@mention`; this list is what
29
+ * makes `user` mean something. Evaluated on every message, because a
30
+ * thread keys one session for everyone in it. Empty or absent means
31
+ * nobody is, and every sender is `unknown`.
32
+ */
33
+ principals?: string[];
23
34
  }
24
35
  export interface SlackSocketEventArgs {
25
36
  ack: (response?: unknown) => Promise<void>;
@@ -67,6 +78,16 @@ export interface SlackInboundEvent {
67
78
  channel_type?: string;
68
79
  bot_id?: string;
69
80
  subtype?: string;
81
+ /**
82
+ * Attachments on a `file_share` message. Slack puts the file metadata in
83
+ * the event and the bytes behind an authenticated URL that needs
84
+ * `files:read`, which this app does not ask for — so a turn learns that a
85
+ * file arrived and what it is called, never what is in it.
86
+ */
87
+ files?: Array<{
88
+ name?: string;
89
+ title?: string;
90
+ }>;
70
91
  }
71
92
  export interface SlackSocketLike {
72
93
  on(eventName: string, listener: (args: SlackSocketEventArgs) => void): void;
@@ -168,6 +189,14 @@ export interface SlackAdapterOptions {
168
189
  * (DMs: the DM channel id alone), so threads are resumable conversations
169
190
  * and two agents sharing a thread keep fully separate sessions. Replies
170
191
  * stream via placeholder-then-edit, throttled for chat.update limits.
192
+ *
193
+ * A mention starts a thread conversation; inside one, the agent keeps
194
+ * listening without being tagged again — see `couldBeFollowUp` and
195
+ * `answersFollowUp` for exactly whose reply an untagged message is. That
196
+ * needs the app to be subscribed to `message.channels` / `message.groups`
197
+ * / `message.mpim` (the shipped manifest is); an app installed before
198
+ * those were in it receives only `app_mention` and behaves as it always
199
+ * did, which makes the workspace's own grant the switch.
171
200
  */
172
201
  export declare const createSlackChannelAdapter: (options: SlackAdapterOptions) => ChannelAdapter;
173
202
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}