@open-everywhere/provider-slack 0.1.0

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.
Files changed (151) hide show
  1. package/LICENSE +201 -0
  2. package/NOTICE +21 -0
  3. package/README.md +47 -0
  4. package/agent/access/slack-attachment-fetch.ts +168 -0
  5. package/agent/app-manifest.ts +149 -0
  6. package/agent/channels/slack-approval-card.ts +275 -0
  7. package/agent/channels/slack-attachments.ts +195 -0
  8. package/agent/channels/slack-commands.ts +227 -0
  9. package/agent/channels/slack-context.ts +185 -0
  10. package/agent/channels/slack-events.ts +5406 -0
  11. package/agent/channels/slack-front.ts +2349 -0
  12. package/agent/channels/slack-identity.ts +520 -0
  13. package/agent/channels/slack-input-response.ts +162 -0
  14. package/agent/channels/slack-mrkdwn.ts +61 -0
  15. package/agent/channels/slack-origin-codec.ts +62 -0
  16. package/agent/channels/slack-post-arm.ts +314 -0
  17. package/agent/channels/slack-read.ts +248 -0
  18. package/agent/channels/slack-route-hold.ts +107 -0
  19. package/agent/channels/slack-shortcut.ts +336 -0
  20. package/agent/channels/slack-signature.ts +53 -0
  21. package/agent/channels/slack-spend-gate.ts +62 -0
  22. package/agent/channels/slack-tenant-fence.ts +99 -0
  23. package/agent/channels/slack-wake-backscroll.ts +604 -0
  24. package/agent/channels/slack-web-api.ts +178 -0
  25. package/agent/channels/slack-webhook-verifier.ts +116 -0
  26. package/agent/channels/slack.ts +1266 -0
  27. package/agent/contributions.ts +32 -0
  28. package/agent/docs-generated.ts +15 -0
  29. package/agent/ops.ts +50 -0
  30. package/agent/provider-events.ts +91 -0
  31. package/agent/register.ts +144 -0
  32. package/agent/surface-parity.ts +99 -0
  33. package/dist/agent/access/slack-attachment-fetch.d.ts +15 -0
  34. package/dist/agent/access/slack-attachment-fetch.d.ts.map +1 -0
  35. package/dist/agent/access/slack-attachment-fetch.js +151 -0
  36. package/dist/agent/access/slack-attachment-fetch.js.map +1 -0
  37. package/dist/agent/app-manifest.d.ts +15 -0
  38. package/dist/agent/app-manifest.d.ts.map +1 -0
  39. package/dist/agent/app-manifest.js +141 -0
  40. package/dist/agent/app-manifest.js.map +1 -0
  41. package/dist/agent/channels/slack-approval-card.d.ts +71 -0
  42. package/dist/agent/channels/slack-approval-card.d.ts.map +1 -0
  43. package/dist/agent/channels/slack-approval-card.js +232 -0
  44. package/dist/agent/channels/slack-approval-card.js.map +1 -0
  45. package/dist/agent/channels/slack-attachments.d.ts +66 -0
  46. package/dist/agent/channels/slack-attachments.d.ts.map +1 -0
  47. package/dist/agent/channels/slack-attachments.js +174 -0
  48. package/dist/agent/channels/slack-attachments.js.map +1 -0
  49. package/dist/agent/channels/slack-commands.d.ts +27 -0
  50. package/dist/agent/channels/slack-commands.d.ts.map +1 -0
  51. package/dist/agent/channels/slack-commands.js +208 -0
  52. package/dist/agent/channels/slack-commands.js.map +1 -0
  53. package/dist/agent/channels/slack-context.d.ts +26 -0
  54. package/dist/agent/channels/slack-context.d.ts.map +1 -0
  55. package/dist/agent/channels/slack-context.js +178 -0
  56. package/dist/agent/channels/slack-context.js.map +1 -0
  57. package/dist/agent/channels/slack-events.d.ts +1654 -0
  58. package/dist/agent/channels/slack-events.d.ts.map +1 -0
  59. package/dist/agent/channels/slack-events.js +4240 -0
  60. package/dist/agent/channels/slack-events.js.map +1 -0
  61. package/dist/agent/channels/slack-front.d.ts +387 -0
  62. package/dist/agent/channels/slack-front.d.ts.map +1 -0
  63. package/dist/agent/channels/slack-front.js +1958 -0
  64. package/dist/agent/channels/slack-front.js.map +1 -0
  65. package/dist/agent/channels/slack-identity.d.ts +245 -0
  66. package/dist/agent/channels/slack-identity.d.ts.map +1 -0
  67. package/dist/agent/channels/slack-identity.js +405 -0
  68. package/dist/agent/channels/slack-identity.js.map +1 -0
  69. package/dist/agent/channels/slack-input-response.d.ts +26 -0
  70. package/dist/agent/channels/slack-input-response.d.ts.map +1 -0
  71. package/dist/agent/channels/slack-input-response.js +127 -0
  72. package/dist/agent/channels/slack-input-response.js.map +1 -0
  73. package/dist/agent/channels/slack-mrkdwn.d.ts +3 -0
  74. package/dist/agent/channels/slack-mrkdwn.d.ts.map +1 -0
  75. package/dist/agent/channels/slack-mrkdwn.js +53 -0
  76. package/dist/agent/channels/slack-mrkdwn.js.map +1 -0
  77. package/dist/agent/channels/slack-origin-codec.d.ts +7 -0
  78. package/dist/agent/channels/slack-origin-codec.d.ts.map +1 -0
  79. package/dist/agent/channels/slack-origin-codec.js +55 -0
  80. package/dist/agent/channels/slack-origin-codec.js.map +1 -0
  81. package/dist/agent/channels/slack-post-arm.d.ts +54 -0
  82. package/dist/agent/channels/slack-post-arm.d.ts.map +1 -0
  83. package/dist/agent/channels/slack-post-arm.js +268 -0
  84. package/dist/agent/channels/slack-post-arm.js.map +1 -0
  85. package/dist/agent/channels/slack-read.d.ts +84 -0
  86. package/dist/agent/channels/slack-read.d.ts.map +1 -0
  87. package/dist/agent/channels/slack-read.js +205 -0
  88. package/dist/agent/channels/slack-read.js.map +1 -0
  89. package/dist/agent/channels/slack-route-hold.d.ts +34 -0
  90. package/dist/agent/channels/slack-route-hold.d.ts.map +1 -0
  91. package/dist/agent/channels/slack-route-hold.js +97 -0
  92. package/dist/agent/channels/slack-route-hold.js.map +1 -0
  93. package/dist/agent/channels/slack-shortcut.d.ts +162 -0
  94. package/dist/agent/channels/slack-shortcut.d.ts.map +1 -0
  95. package/dist/agent/channels/slack-shortcut.js +262 -0
  96. package/dist/agent/channels/slack-shortcut.js.map +1 -0
  97. package/dist/agent/channels/slack-signature.d.ts +19 -0
  98. package/dist/agent/channels/slack-signature.d.ts.map +1 -0
  99. package/dist/agent/channels/slack-signature.js +50 -0
  100. package/dist/agent/channels/slack-signature.js.map +1 -0
  101. package/dist/agent/channels/slack-spend-gate.d.ts +22 -0
  102. package/dist/agent/channels/slack-spend-gate.d.ts.map +1 -0
  103. package/dist/agent/channels/slack-spend-gate.js +48 -0
  104. package/dist/agent/channels/slack-spend-gate.js.map +1 -0
  105. package/dist/agent/channels/slack-tenant-fence.d.ts +61 -0
  106. package/dist/agent/channels/slack-tenant-fence.d.ts.map +1 -0
  107. package/dist/agent/channels/slack-tenant-fence.js +88 -0
  108. package/dist/agent/channels/slack-tenant-fence.js.map +1 -0
  109. package/dist/agent/channels/slack-wake-backscroll.d.ts +188 -0
  110. package/dist/agent/channels/slack-wake-backscroll.d.ts.map +1 -0
  111. package/dist/agent/channels/slack-wake-backscroll.js +473 -0
  112. package/dist/agent/channels/slack-wake-backscroll.js.map +1 -0
  113. package/dist/agent/channels/slack-web-api.d.ts +46 -0
  114. package/dist/agent/channels/slack-web-api.d.ts.map +1 -0
  115. package/dist/agent/channels/slack-web-api.js +147 -0
  116. package/dist/agent/channels/slack-web-api.js.map +1 -0
  117. package/dist/agent/channels/slack-webhook-verifier.d.ts +5 -0
  118. package/dist/agent/channels/slack-webhook-verifier.d.ts.map +1 -0
  119. package/dist/agent/channels/slack-webhook-verifier.js +112 -0
  120. package/dist/agent/channels/slack-webhook-verifier.js.map +1 -0
  121. package/dist/agent/channels/slack.d.ts +37 -0
  122. package/dist/agent/channels/slack.d.ts.map +1 -0
  123. package/dist/agent/channels/slack.js +1169 -0
  124. package/dist/agent/channels/slack.js.map +1 -0
  125. package/dist/agent/contributions.d.ts +17 -0
  126. package/dist/agent/contributions.d.ts.map +1 -0
  127. package/dist/agent/contributions.js +32 -0
  128. package/dist/agent/contributions.js.map +1 -0
  129. package/dist/agent/docs-generated.d.ts +3 -0
  130. package/dist/agent/docs-generated.d.ts.map +1 -0
  131. package/dist/agent/docs-generated.js +13 -0
  132. package/dist/agent/docs-generated.js.map +1 -0
  133. package/dist/agent/ops.d.ts +3 -0
  134. package/dist/agent/ops.d.ts.map +1 -0
  135. package/dist/agent/ops.js +38 -0
  136. package/dist/agent/ops.js.map +1 -0
  137. package/dist/agent/provider-events.d.ts +3 -0
  138. package/dist/agent/provider-events.d.ts.map +1 -0
  139. package/dist/agent/provider-events.js +84 -0
  140. package/dist/agent/provider-events.js.map +1 -0
  141. package/dist/agent/register.d.ts +5 -0
  142. package/dist/agent/register.d.ts.map +1 -0
  143. package/dist/agent/register.js +118 -0
  144. package/dist/agent/register.js.map +1 -0
  145. package/dist/agent/surface-parity.d.ts +3 -0
  146. package/dist/agent/surface-parity.d.ts.map +1 -0
  147. package/dist/agent/surface-parity.js +95 -0
  148. package/dist/agent/surface-parity.js.map +1 -0
  149. package/package.json +209 -0
  150. package/tsconfig.build.json +22 -0
  151. package/tsconfig.json +15 -0
@@ -0,0 +1,473 @@
1
+ // Wake-time conversation backscroll.
2
+ //
3
+ // The MENTION path enriches a turn with surrounding conversation (slack-context.ts, via Eve's
4
+ // `SlackContext` handle). The WAKE path — a name-drop that pulls the bot into a conversation it
5
+ // was never mentioned in (slack-events.ts routeNameDropEvent) — used to hand the model ONLY the
6
+ // triggering message, so:
7
+ // (a) a cold name-drop mid-thread arrived with no idea what's being discussed, and
8
+ // (b) a re-wake after auto-disengage resumed the SAME thread session, which has a GAP for
9
+ // everything said while the bot was disengaged.
10
+ // This module closes both by fetching recent history at wake time and attaching it as the same
11
+ // `context` strings the mention path uses.
12
+ //
13
+ // WHY A STANDALONE CALLER (not Eve's `ctx`): a wake fires from a raw HTTP route, not a live
14
+ // session, so there's no `SlackContext`/`ctx.slack` to borrow. We call the Web API through OE's
15
+ // `callSlackWebApi` seam (channels/slack-web-api.ts) with the bot token — the same seam every other
16
+ // Slack Web API call uses, so this path inherits the 429 backoff. The message→line mapping,
17
+ // the render, and the UNTRUSTED wrapping are REUSED from slack-context.ts (linesFromMessages /
18
+ // renderContext / ContextLine), so wake context is attributed + fenced byte-identically to the
19
+ // mention path — the untrusted framing is a security invariant (channel content is DATA, never
20
+ // instructions), not decoration, so it must never diverge between the two paths.
21
+ //
22
+ // BOOTSTRAP BACKSCROLL is fail-soft: any error yields no context and never blocks the first wake.
23
+ // SEAT CATCH-UP propagates the same read failure to core's shared fail-soft boundary, so the wake
24
+ // still continues but its `seat.catch_up` row says `failed` rather than `empty` (OPE-1842).
25
+ import { callSlackWebApi } from "./slack-web-api.js";
26
+ import { RateLimitExhaustedError } from "@open-everywhere/core/agent/adapter-api.js";
27
+ import { linesFromMessages, readMoreHint } from "./slack-context.js";
28
+ import { renderContext, sinceLastAgentReply, WAKE_BACKSCROLL_MAX, fetchedBackscroll, catchUpSender, } from "@open-everywhere/core/agent/adapter-api.js";
29
+ // Re-export the shared cap so this module's public surface (and its test, which imports it from
30
+ // here) is unchanged after the extraction into context-render.ts (now reached via the barrel).
31
+ export { WAKE_BACKSCROLL_MAX };
32
+ /**
33
+ * The widest THREAD slice this module hands a caller that ADMITS BEFORE IT CAPS (OPE-1744,
34
+ * {@link WakeBackscrollInput.threadAdmissionSlice}). Five times {@link WAKE_BACKSCROLL_MAX}, so the
35
+ * policy can look past a long run of refused replies and still fill the ten-line slot; half the page
36
+ * the thread fetch buys, so the slice stays bounded.
37
+ * 🔴 IT IS A COST BOUND, AND THE COST IS THE CALLER'S PER-AUTHOR PROBE. Slack's hydration regrades
38
+ * every returned line before it admits, and that regrade runs one TTL-cached `users.info` per
39
+ * DISTINCT vouchable author. Handing back the whole 100-reply page would put that fan-out on a busy
40
+ * thread; the probe fails OPEN, so an exhausted burst demotes nobody and a guest keeps the tier a
41
+ * confirmed-internal channel gives. The slice is bounded here to keep that burst small.
42
+ */
43
+ export const THREAD_ADMISSION_MAX = WAKE_BACKSCROLL_MAX * 5;
44
+ // --- live (bot-token) implementations ---------------------------------------
45
+ // Bot-token POST to the Slack Web API via OE's `callSlackWebApi` (channels/slack-web-api.ts), which
46
+ // a wake path can't reach through `ctx` because it fires from a raw HTTP route with no live session.
47
+ // Form-encodes `params` and resolves the token from `SLACK_BOT_TOKEN`. Fail-soft: a missing token
48
+ // makes the seam throw, and any throw → undefined (backscroll never blocks a wake).
49
+ const liveRequest = async (method, params) => {
50
+ try {
51
+ return (await callSlackWebApi({ botToken: undefined, operation: method, body: params }));
52
+ }
53
+ catch (err) {
54
+ // 🔴 LOG A RATE-LIMIT EXHAUSTION BEFORE SWALLOWING IT (OPE-1211). Fail-soft is right here — a
55
+ // backscroll must never block a wake — but an exhausted 429 retry with no trace is the silent
56
+ // drop the ticket exists to prevent. Every field is token-free.
57
+ if (err instanceof RateLimitExhaustedError) {
58
+ console.warn(`[open-everywhere:slack] rate limited: backscroll ${method} gave up after ${err.attempts} attempts (waited ${err.waitedMs} ms)`);
59
+ }
60
+ return undefined;
61
+ }
62
+ };
63
+ // The bot's (user_id, bot_id) via auth.test, resolved once (cached). Same shape as
64
+ // slack-front.ts's resolveBotIdentity; a local copy avoids the import cycle noted above. Used
65
+ // only to attribute the agent's own posts in the backscroll — best-effort, never a hard gate.
66
+ let wakeBotIdentityPromise;
67
+ function liveWakeBotIdentity() {
68
+ if (!wakeBotIdentityPromise) {
69
+ wakeBotIdentityPromise = (async () => {
70
+ const res = await liveRequest("auth.test", {});
71
+ if (res?.ok === true) {
72
+ return {
73
+ userId: typeof res.user_id === "string" ? res.user_id : undefined,
74
+ botId: typeof res.bot_id === "string" ? res.bot_id : undefined,
75
+ };
76
+ }
77
+ return {};
78
+ })();
79
+ }
80
+ return wakeBotIdentityPromise;
81
+ }
82
+ /** Reset the cached wake bot identity (tests only). */
83
+ export function _resetWakeBotIdentity() {
84
+ wakeBotIdentityPromise = undefined;
85
+ }
86
+ const liveDeps = { request: liveRequest, identity: liveWakeBotIdentity };
87
+ /**
88
+ * Fetch recent conversation history for a name-drop wake as RAW ContextLines + source + hint (W3) —
89
+ * the renderer wraps them (renderContext, inside renderWake). `null` = nothing to add OR any
90
+ * failure (always non-fatal).
91
+ *
92
+ * - IN-THREAD wake (`threadTs`): `conversations.replies`, sliced to "since the agent's last reply"
93
+ * (see {@link sinceLastAgentReply}); the triggering message itself is excluded (the wake message
94
+ * already carries its text). Capped at {@link WAKE_BACKSCROLL_MAX}, or at the wider
95
+ * {@link THREAD_ADMISSION_MAX} when the caller asks for the admission slice
96
+ * ({@link WakeBackscrollInput.threadAdmissionSlice}).
97
+ * - TOP-LEVEL wake (no `threadTs`): `conversations.history` with `latest = ts`, `inclusive: false`
98
+ * → strictly-older messages only, most recent N.
99
+ */
100
+ export async function fetchWakeBackscrollLines(input, deps = liveDeps) {
101
+ try {
102
+ const ids = await deps.identity().catch(() => ({}));
103
+ if (input.threadTs) {
104
+ const res = await deps.request("conversations.replies", {
105
+ channel: input.channelId,
106
+ ts: input.threadTs,
107
+ // A single (oldest-anchored) page — no cursor paging. Comfortably covers any realistic
108
+ // thread; a pathologically long one degrades to "older context only", still fail-soft.
109
+ limit: "100",
110
+ });
111
+ const raw = extractMessages(res);
112
+ if (!raw)
113
+ return null;
114
+ // Drop the trigger itself (its text rides on the wake message, not the backscroll).
115
+ const priorRaw = raw.filter((m) => (typeof m.ts === "string" ? m.ts : "") !== input.ts);
116
+ // conversations.replies is oldest-first already — no reverse.
117
+ const lines = sinceLastAgentReply(linesFromMessages(priorRaw, ids));
118
+ const source = `slack thread ${input.channelId}/${input.threadTs}`;
119
+ // The wider ADMISSION slice when the caller admits before it caps (OPE-1744), the render-cap
120
+ // slice otherwise — see {@link WakeBackscrollInput.threadAdmissionSlice}.
121
+ return input.threadAdmissionSlice ? backscrollEntry(lines.slice(-THREAD_ADMISSION_MAX), source) : cappedEntry(lines, source);
122
+ }
123
+ // Top-level: strictly-older backscroll of the channel (mirrors slack-context's channel path).
124
+ const res = await deps.request("conversations.history", {
125
+ channel: input.channelId,
126
+ latest: input.ts,
127
+ inclusive: "false",
128
+ limit: String(WAKE_BACKSCROLL_MAX),
129
+ });
130
+ const raw = extractMessages(res);
131
+ if (!raw)
132
+ return null;
133
+ const lines = linesFromMessages(raw, ids);
134
+ lines.reverse(); // conversations.history is newest-first → oldest-first for rendering
135
+ return cappedEntry(lines, `slack channel ${input.channelId}`);
136
+ }
137
+ catch {
138
+ return null; // fail-soft: a wake never depends on its backscroll
139
+ }
140
+ }
141
+ /**
142
+ * Fetch recent conversation history for a name-drop wake, rendered as `context` strings
143
+ * (untrusted-wrapped, oldest-first, capped at {@link WAKE_BACKSCROLL_MAX}). Empty array = nothing to
144
+ * add OR any failure. Thin wrapper over {@link fetchWakeBackscrollLines} + the shared renderContext,
145
+ * so its output stays byte-identical to before the W3 refactor (retained for its existing callers
146
+ * and byte-identity tests; the live name-drop path now uses the lines variant directly).
147
+ */
148
+ export async function fetchWakeBackscroll(input, deps = liveDeps) {
149
+ const res = await fetchWakeBackscrollLines(input, deps);
150
+ if (!res)
151
+ return [];
152
+ const entry = renderContext(res.lines, res.source, { readMoreHint: res.readMoreHint });
153
+ return entry ? [entry] : [];
154
+ }
155
+ // Pull the `messages` array out of an ok response, or undefined (fail-soft on junk / not-ok).
156
+ function extractMessages(res) {
157
+ if (!res || res.ok !== true || !Array.isArray(res.messages))
158
+ return undefined;
159
+ return res.messages;
160
+ }
161
+ // Return the RAW lines + source + hint — the renderer (renderContext, inside renderWake) does the
162
+ // untrusted-wrap, so wrapping happens in exactly ONE place (W3). `lines` must be oldest-first.
163
+ // Returns null when there's nothing to keep, so the caller renders no context block.
164
+ // The hint is handed over unconditionally: `renderContext` appends it only when the RENDERED slice
165
+ // fills MAX_MESSAGES, so it always describes what the model was shown, never what was fetched.
166
+ function backscrollEntry(lines, source) {
167
+ if (lines.length === 0)
168
+ return null;
169
+ return { lines, source, readMoreHint: readMoreHint() };
170
+ }
171
+ // {@link backscrollEntry} with the WAKE_BACKSCROLL_MAX cap applied first (keep the most recent).
172
+ function cappedEntry(lines, source) {
173
+ return backscrollEntry(lines.slice(-WAKE_BACKSCROLL_MAX), source);
174
+ }
175
+ // --- envelope-shaped first-wake backscroll (supervisor context hydration) — SLACK ADAPTER ----
176
+ //
177
+ // The channel-supervisor's FIRST wake on a generation (a brand-new session OR the fresh generation
178
+ // minted by a rotation, slack-events.ts shouldRotate/routeSupervisorEvent) carries channel
179
+ // backscroll rendered as the wake ENVELOPE's own non-trigger `<message>` siblings, grouped into
180
+ // `<session>` blocks (wake-envelope.ts renderWakeEnvelope) — Claude Tag's observed first-wake shape
181
+ // is individual attributed messages, oldest-first, ending at the trigger (claude-tag-behaviour.md
182
+ // §4.1), and OE's is richer: idle-gap-clustered pseudo-sessions with count/time/token bounds
183
+ //.
184
+ //
185
+ // THIS FILE IS THE SLACK FETCH ADAPTER behind the platform-NEUTRAL clustering/bounds core
186
+ // (backscroll-window.ts). Its job: turn conversations.history (+ conversations.replies for thread
187
+ // enrichment) into a visibility-GATED {@link NormalizedMessage}[] window, then hand it to
188
+ // {@link fetchedBackscroll}. Discord/Teams later add their OWN fetch adapter with zero change to the
189
+ // core. FAIL-SOFT ABSOLUTELY throughout, exactly like {@link fetchWakeBackscroll}.
190
+ // --- fetch bounds (Slack-specific; the clustering/token bounds live in backscroll-window.ts) ---
191
+ /** Reachback (hours) for the raw Slack window: how far back from the trigger conversations.history
192
+ * is paginated. Generous enough that the SPINE (the most-recent cluster, exempt from the 36h
193
+ * enrichment cap) can still reach across a weekend/overnight gap (~66h Fri-4pm→Mon-10am), yet a
194
+ * hard floor that bounds the fetch. 7d default; overridable for ops/testing. */
195
+ export const RAW_FETCH_REACHBACK_HOURS = Number(process.env.OE_SUPERVISOR_BACKSCROLL_REACHBACK_HOURS) || 168;
196
+ /** conversations.history page size (Slack max is 1000; 200 keeps each page cheap). */
197
+ const RAW_FETCH_PAGE_LIMIT = 200;
198
+ /** Max history pages to paginate — bounds a busy channel's fetch at ≤600 messages so a burst can't
199
+ * fan out into an unbounded loop. Combined with the reachback floor (whichever binds first). */
200
+ const RAW_FETCH_MAX_PAGES = 3;
201
+ /** Max in-window thread ROOTS to enrich via conversations.replies — bounds the reply fan-out so a
202
+ * channel full of threads can't explode into unbounded API calls. */
203
+ const MAX_THREADS_ENRICHED = 8;
204
+ /** Single-page reply fetch per thread (mirrors the name-drop thread leg's own 100). */
205
+ const THREAD_REPLIES_LIMIT = 100;
206
+ /**
207
+ * The VISIBILITY / TRUST GATE (spec §Bounds — the load-bearing SECURITY filter): backscroll must
208
+ * never surface a message it can't ATTRIBUTE. The channel-internal confirmation
209
+ * (confirmChannelInternalWithMeta) fail-closes the restricted-area / at-rest-isolation dimension
210
+ * BEFORE this fetcher is ever called. So the per-message gate here KEEPS:
211
+ * - the bot's OWN prior posts (`agent` → `self`);
212
+ * - identifiable humans (`user` → `human`);
213
+ * - ATTRIBUTABLE foreign bots (`bot` WITH a bot id → `bot`) — INCLUDED as MARKED AWARENESS
214
+ * (clearly bot-flagged, CONTEXT-ONLY, never a wake trigger). Design intent: the supervisor
215
+ * SHOULD see foreign-bot posts, and dropping them breaks CONVERSATIONAL COHERENCE — a human
216
+ * replying to a bot's message would otherwise arrive with the bot message missing, so the agent
217
+ * couldn't tell what the human is responding to.
218
+ * and DROPS ONLY:
219
+ * - unattributable senders (`unknown`, or a `bot` with no id) — no auth'd author ⇒ fail closed.
220
+ * (System-subtype noise is already dropped upstream by linesFromMessages.) Foreign-bot messages are
221
+ * CONTEXT-ONLY on this path: the neutral core never sets `trigger` on backscroll, and the LIVE
222
+ * trigger gate (slack-events.ts shouldSupervisorWake) still drops bot-authored messages as triggers,
223
+ * so a bot post is awareness, never a response obligation. Wired explicitly + unit-tested
224
+ * (slack-wake-backscroll-test.ts) so it can't be forgotten.
225
+ */
226
+ export function isBackscrollVisible(line) {
227
+ return (line.senderType === "agent" ||
228
+ line.senderType === "user" ||
229
+ (line.senderType === "bot" && line.senderId !== undefined) // attributable foreign bot: marked awareness
230
+ );
231
+ }
232
+ // Pull the pagination cursor from a conversations.history response, or undefined when there's no
233
+ // next page (fail-soft on junk).
234
+ function extractCursor(res) {
235
+ const meta = res?.response_metadata;
236
+ const cursor = meta?.next_cursor;
237
+ return typeof cursor === "string" && cursor.length > 0 ? cursor : undefined;
238
+ }
239
+ // Paginate conversations.history backward from `latest` (exclusive) down to `oldest`, bounded by
240
+ // RAW_FETCH_MAX_PAGES. Returns the raw messages (newest-first across pages — the neutral core sorts
241
+ // by ts anyway). Fail-soft: a not-ok/absent page ends pagination with whatever's in hand.
242
+ async function fetchChannelWindow(request, channelId, latest, oldest) {
243
+ const all = [];
244
+ let cursor;
245
+ for (let page = 0; page < RAW_FETCH_MAX_PAGES; page++) {
246
+ const res = await request("conversations.history", {
247
+ channel: channelId,
248
+ latest,
249
+ inclusive: "false",
250
+ oldest,
251
+ limit: String(RAW_FETCH_PAGE_LIMIT),
252
+ ...(cursor ? { cursor } : {}),
253
+ });
254
+ const msgs = extractMessages(res);
255
+ if (!msgs)
256
+ break;
257
+ all.push(...msgs);
258
+ cursor = extractCursor(res);
259
+ if (!cursor)
260
+ break; // no more pages
261
+ }
262
+ return all;
263
+ }
264
+ // Enrich with thread replies for in-window thread ROOTS (conversations.history returns roots +
265
+ // top-level messages, not the replies inside a thread). BOUNDED: only roots that actually have
266
+ // replies, capped at MAX_THREADS_ENRICHED, one page each. Returns [{ root, msgs }]; fail-soft per
267
+ // thread (a failed reply fetch just omits that thread's replies).
268
+ async function fetchThreadReplies(request, channelId, channelMsgs) {
269
+ const roots = [];
270
+ for (const m of channelMsgs) {
271
+ if (roots.length >= MAX_THREADS_ENRICHED)
272
+ break;
273
+ const ts = typeof m.ts === "string" ? m.ts : undefined;
274
+ const threadTs = typeof m.thread_ts === "string" ? m.thread_ts : undefined;
275
+ const replyCount = typeof m.reply_count === "number" ? m.reply_count : 0;
276
+ // A thread root: it IS its own thread anchor (no thread_ts, or thread_ts === ts) and has replies.
277
+ if (ts && replyCount > 0 && (!threadTs || threadTs === ts))
278
+ roots.push(ts);
279
+ }
280
+ const out = [];
281
+ for (const root of roots) {
282
+ const res = await request("conversations.replies", { channel: channelId, ts: root, limit: String(THREAD_REPLIES_LIMIT) });
283
+ const msgs = extractMessages(res);
284
+ if (msgs)
285
+ out.push({ root, msgs });
286
+ }
287
+ return out;
288
+ }
289
+ // Read one KNOWN thread without first discovering its root through channel history. A standing
290
+ // seat's catch-up window commonly starts after the thread root, so root discovery would answer an
291
+ // empty channel page even when the thread has new replies inside the window (OPE-1920).
292
+ async function fetchKnownThreadReplies(request, channelId, threadRoot, oldest, latest) {
293
+ const res = await request("conversations.replies", {
294
+ channel: channelId,
295
+ ts: threadRoot,
296
+ oldest,
297
+ latest,
298
+ // Keep both endpoints at the transport seam. Core removes the trigger by exact id and enforces
299
+ // the same bounds again after normalization.
300
+ inclusive: "true",
301
+ limit: String(THREAD_REPLIES_LIMIT),
302
+ });
303
+ const msgs = extractMessages(res);
304
+ return msgs ? [{ root: threadRoot, msgs }] : [];
305
+ }
306
+ // Normalize ONE raw Slack message → {@link NormalizedMessage}, reusing linesFromMessages for the
307
+ // exact sender classification + system/empty drop, then applying the VISIBILITY GATE. Returns
308
+ // undefined for a dropped (invisible / subtype / empty / unparseable-ts) message.
309
+ function normalizeOne(m, ids, type, threadId) {
310
+ const [line] = linesFromMessages([m], ids);
311
+ if (!line)
312
+ return undefined; // system subtype / empty text (dropped upstream)
313
+ if (!isBackscrollVisible(line))
314
+ return undefined; // VISIBILITY GATE (unattributable sender only)
315
+ const seconds = Number.parseFloat(line.ts);
316
+ if (!Number.isFinite(seconds))
317
+ return undefined;
318
+ return {
319
+ id: line.ts,
320
+ ms: seconds * 1000,
321
+ // undefined for the bot's OWN posts (agent); the foreign bot's id for a `bot`; the user id for
322
+ // a human — kept raw for @-tagging / attribution.
323
+ authorId: line.senderId,
324
+ // THE SHARED SENDER RULE (OPE-1857): agent → self (our own post); bot → bot (attributable
325
+ // foreign bot, marked awareness); every other visible line is a `user` → human. `unknown` was
326
+ // already dropped by the gate above.
327
+ sender: catchUpSender({ self: line.senderType === "agent", bot: line.senderType === "bot" }),
328
+ type,
329
+ threadId,
330
+ text: line.text,
331
+ };
332
+ }
333
+ /**
334
+ * SLACK FETCH SEAM: fetch a bounded, visibility-GATED, NORMALIZED backscroll window (channel history
335
+ * + in-window thread replies) for a supervisor first wake. This is the platform boundary — the
336
+ * neutral core ({@link fetchedBackscroll}) consumes its output. FAIL-SOFT: any error/failure yields
337
+ * `[]`. Deduped by message id (a thread root appears in both history and its replies[0]).
338
+ */
339
+ export async function fetchSlackBackscrollWindow(input, deps = liveDeps, failureMode = "soft") {
340
+ try {
341
+ const ids = await deps.identity().catch(() => ({}));
342
+ const latestSeconds = Number.parseFloat(input.ts);
343
+ if (!Number.isFinite(latestSeconds))
344
+ return [];
345
+ const reachbackHours = input.reachbackHours ?? RAW_FETCH_REACHBACK_HOURS;
346
+ // The reachback floor, then the seat's own last wake where it is LATER — never earlier, so the
347
+ // catch-up can only narrow the fetch (see {@link WakeEnvelopeBackscrollInput.sinceMs}).
348
+ const floorSeconds = latestSeconds - reachbackHours * 3600;
349
+ const sinceSeconds = typeof input.sinceMs === "number" && Number.isFinite(input.sinceMs) ? input.sinceMs / 1000 : undefined;
350
+ const oldestSeconds = sinceSeconds !== undefined ? Math.max(floorSeconds, sinceSeconds) : floorSeconds;
351
+ const oldest = String(oldestSeconds);
352
+ // A thread-bound catch-up already knows its root. Read it directly: the root can predate the
353
+ // lower bound, which makes it undiscoverable through the bounded channel-history page even
354
+ // though newer replies belong in this wake. Bootstrap/container reads still take the original
355
+ // channel-history + bounded enrichment path.
356
+ const channelMsgs = input.threadRoot === undefined ? await fetchChannelWindow(deps.request, input.channelId, input.ts, oldest) : [];
357
+ const threadGroups = input.threadRoot === undefined
358
+ ? await fetchThreadReplies(deps.request, input.channelId, channelMsgs)
359
+ : await fetchKnownThreadReplies(deps.request, input.channelId, input.threadRoot, oldest, input.ts);
360
+ if (channelMsgs.length === 0 && threadGroups.length === 0)
361
+ return [];
362
+ const seen = new Set();
363
+ const out = [];
364
+ const add = (n) => {
365
+ if (n && !seen.has(n.id)) {
366
+ seen.add(n.id);
367
+ out.push(n);
368
+ }
369
+ };
370
+ for (const m of channelMsgs)
371
+ add(normalizeOne(m, ids, "channel", undefined));
372
+ for (const g of threadGroups) {
373
+ for (const m of g.msgs) {
374
+ const ts = typeof m.ts === "string" ? m.ts : "";
375
+ // The root is already a channel message — and so is the TRIGGER when it is a reply inside a
376
+ // thread whose root is in the window: `conversations.replies` returns it, and the wake
377
+ // renderer would then show the seat the message that woke it twice, once as context and once
378
+ // as the live trigger. The channel fetch excludes the trigger with `inclusive: "false"`; this
379
+ // is the same exclusion on the enrichment leg (the precedent is `linesFromMessages`' own
380
+ // "drop the trigger itself").
381
+ // A discovered root is already present in `channelMsgs`; a directly-read root is not, so
382
+ // let the ordinary lower/upper bounds decide whether it belongs. The trigger always leaves
383
+ // exactly by id.
384
+ if ((input.threadRoot === undefined && ts === g.root) || ts === input.ts)
385
+ continue;
386
+ const secs = Number.parseFloat(ts);
387
+ if (Number.isFinite(secs) && secs < oldestSeconds)
388
+ continue; // reply older than the window
389
+ if (input.threadRoot !== undefined && Number.isFinite(secs) && secs > latestSeconds)
390
+ continue; // reply after the trigger
391
+ add(normalizeOne(m, ids, "thread", g.root));
392
+ }
393
+ }
394
+ return out;
395
+ }
396
+ catch (err) {
397
+ if (failureMode === "throw")
398
+ throw err;
399
+ return []; // fail-soft: a first wake never depends on its backscroll
400
+ }
401
+ }
402
+ /**
403
+ * SLACK'S REGISTERED CATCH-UP FETCH (OPE-1726) — the one thing this surface contributes to the shared
404
+ * since-last-wake path (core channels/seat-catch-up.ts). It is the SAME window fetch the bootstrap
405
+ * arm takes ({@link fetchSlackBackscrollWindow}), addressed by the neutral request shape: the seat's
406
+ * container, bounded below by its last wake and above by the trigger.
407
+ * 🔴 THE UPPER BOUND IS RE-EXPRESSED AS A SLACK `ts`, because `conversations.history` takes `latest`
408
+ * in Slack's own seconds-with-fraction form and not epoch ms. `excludeId` IS that ts on this surface
409
+ * (a Slack ts is both a time and an id), so it is preferred over the derived string — a derived one
410
+ * can lose the trailing digits Slack's ordering depends on. With neither, the read falls back to
411
+ * `now`, which is the honest upper bound for a catch-up with no stated trigger.
412
+ * A transport/read failure propagates to core's shared boundary, which keeps the wake alive and
413
+ * records `failed` instead of reporting a quiet channel (OPE-1842). Bootstrap callers keep the
414
+ * window fetch's default fail-soft mode.
415
+ */
416
+ export async function fetchSlackSeatCatchUp(req, deps = liveDeps) {
417
+ const latestTs = req.excludeId ?? (req.untilMs !== undefined ? String(req.untilMs / 1000) : String(Date.now() / 1000));
418
+ const strictDeps = {
419
+ ...deps,
420
+ request: async (method, params) => {
421
+ const res = await deps.request(method, params);
422
+ if (!res || res.ok !== true || !Array.isArray(res.messages)) {
423
+ throw new Error(`Slack catch-up ${method} failed`);
424
+ }
425
+ return res;
426
+ },
427
+ };
428
+ return fetchSlackBackscrollWindow({ channelId: req.container, ts: latestTs, sinceMs: req.sinceMs, ...(req.threadRoot ? { threadRoot: req.threadRoot } : {}) }, strictDeps, "throw");
429
+ }
430
+ /**
431
+ * A Slack `ts` is a second with a six-digit fraction, so it carries MILLISECOND grain (OPE-1847,
432
+ * `core/agent/channels/seat-catch-up.ts` {@link SeatCatchUpDeclaration.timestampPrecisionMs}).
433
+ * 🔴 ONE MILLISECOND IS NOT ZERO WIDENING. The road widens the LOWER bound by nothing here and the
434
+ * UPPER bound by exactly one millisecond, so a message stamped at the trigger's own instant is
435
+ * INSIDE the window and `excludeId` is the only thing that removes the trigger. That holds on this
436
+ * surface twice over: `conversations.history` is called with `inclusive: "false"`, so the trigger
437
+ * never reaches the fetch, and a message that did would carry its `ts` as its id — the same value
438
+ * the wake path passes as `excludeId`.
439
+ * 🔴 THE DECLARATION CANNOT EXPRESS THIS SURFACE'S SUB-MILLISECOND `ts`. The unit is a whole number
440
+ * of milliseconds, so the road's floor rounds Slack's fraction away. It costs nothing today: the
441
+ * bound is a bound, not an ordering, and the fetch orders by `ts` itself.
442
+ * 🔴 IT IS STILL DECLARED, and the parity test requires it. The declaration is what makes "this
443
+ * surface needs the finest unit" a CHECKED claim rather than an omission, and an omission is
444
+ * indistinguishable from the GitHub and Notion defect this whole mechanism exists to close.
445
+ */
446
+ export const SLACK_TIMESTAMP_PRECISION_MS = 1;
447
+ /** The registered form — the transport seam is fixed to the live one, so a caller cannot inject past
448
+ * the bot token. Tests drive {@link fetchSlackSeatCatchUp} with a canned requester instead. */
449
+ export const slackSeatCatchUpFetch = (req) => fetchSlackSeatCatchUp(req);
450
+ /**
451
+ * Fetch + cluster a standing seat's channel backscroll into session-tagged
452
+ * {@link WakeMessageInput} entries (oldest-first, no `trigger`; per-message trust via
453
+ * `trustFor` when the caller supplies the resolver, the fail-closed per-sender default otherwise).
454
+ * Thin orchestration over the Slack fetch seam ({@link fetchSlackBackscrollWindow}) + the neutral
455
+ * capped core ({@link fetchedBackscroll}), which applies the domain's `admit` policy. Serves the
456
+ * BOOTSTRAP window ONLY — a fresh generation's first wake, the one read with no cross-surface twin.
457
+ * Since OPE-1726 the since-last-wake CATCH-UP is not this function's job: it runs through
458
+ * {@link fetchSlackSeatCatchUp}, registered into the shared core path (core channels/seat-catch-up.ts
459
+ * `seatCatchUp`), which owns the bounds, the admission policy and the cap for every surface. This
460
+ * function still ACCEPTS `input.sinceMs`, but no caller sets it. FAIL-SOFT ABSOLUTELY.
461
+ */
462
+ export async function fetchWakeEnvelopeBackscroll(input, deps = liveDeps, trustFor, admit) {
463
+ try {
464
+ const window = await fetchSlackBackscrollWindow(input, deps);
465
+ if (window.length === 0)
466
+ return [];
467
+ return fetchedBackscroll(window, undefined, trustFor, admit);
468
+ }
469
+ catch {
470
+ return []; // fail-soft: a wake never depends on its backscroll
471
+ }
472
+ }
473
+ //# sourceMappingURL=slack-wake-backscroll.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"slack-wake-backscroll.js","sourceRoot":"","sources":["../../../agent/channels/slack-wake-backscroll.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,46 @@
1
+ import { type RateLimitRetryOptions } from "@open-everywhere/core/agent/adapter-api.js";
2
+ /** The Slack Web API JSON envelope. `ok` signals Slack's own verdict; callers inspect it. */
3
+ export interface SlackWebApiResponse {
4
+ readonly ok?: boolean;
5
+ readonly error?: string;
6
+ readonly [key: string]: unknown;
7
+ }
8
+ /** The failure a non-2xx Slack response produces. Mirrors eve's `SlackApiError` field-for-field, so
9
+ * a caller that reads `status` or `response` off a caught error keeps reading the same thing. */
10
+ export declare class SlackWebApiError extends Error {
11
+ readonly method: string;
12
+ readonly status: number;
13
+ readonly response: unknown;
14
+ constructor(init: {
15
+ method: string;
16
+ status: number;
17
+ response: unknown;
18
+ });
19
+ }
20
+ /** The subset of the global `fetch` this module uses — injectable so tests drive it without Slack. */
21
+ export type SlackFetchLike = (input: string, init: RequestInit) => Promise<Response>;
22
+ /** Transport and retry seams. A test injects all of them; live code passes none. */
23
+ export interface SlackWebApiDeps {
24
+ readonly fetch?: SlackFetchLike;
25
+ readonly sleep?: RateLimitRetryOptions["sleep"];
26
+ readonly now?: RateLimitRetryOptions["now"];
27
+ readonly maxAttempts?: number;
28
+ readonly capMs?: number;
29
+ readonly totalBudgetMs?: number;
30
+ readonly apiBase?: string;
31
+ }
32
+ /** Form-encode a Slack request body exactly as eve's `encodeSlackApiBody` does. */
33
+ export declare function encodeSlackForm(body: unknown): string;
34
+ /**
35
+ * POST one Slack Web API method, with the 429 backoff applied.
36
+ *
37
+ * Returns Slack's parsed JSON envelope on any 2xx, `ok:false` included. Throws
38
+ * {@link SlackWebApiError} on a non-2xx that is not a 429, and `RateLimitExhaustedError` when a 429
39
+ * outlasts the bounded attempts.
40
+ */
41
+ export declare function callSlackWebApi(input: {
42
+ readonly botToken?: string;
43
+ readonly operation: string;
44
+ readonly body: unknown;
45
+ }, deps?: SlackWebApiDeps): Promise<SlackWebApiResponse>;
46
+ //# sourceMappingURL=slack-web-api.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"slack-web-api.d.ts","sourceRoot":"","sources":["../../../agent/channels/slack-web-api.ts"],"names":[],"mappings":"AAyCA,OAAO,EAAkB,KAAK,qBAAqB,EAAE,MAAM,4CAA4C,CAAC;AAMxG,6FAA6F;AAC7F,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,EAAE,CAAC,EAAE,OAAO,CAAC;IACtB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACjC;AAED;kGACkG;AAClG,qBAAa,gBAAiB,SAAQ,KAAK;IACzC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAE3B,YAAY,IAAI,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,OAAO,CAAA;KAAE,EAMtE;CACF;AAED,sGAAsG;AACtG,MAAM,MAAM,cAAc,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;AAErF,oFAAoF;AACpF,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,KAAK,CAAC,EAAE,cAAc,CAAC;IAChC,QAAQ,CAAC,KAAK,CAAC,EAAE,qBAAqB,CAAC,OAAO,CAAC,CAAC;IAChD,QAAQ,CAAC,GAAG,CAAC,EAAE,qBAAqB,CAAC,KAAK,CAAC,CAAC;IAC5C,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,mFAAmF;AACnF,wBAAgB,eAAe,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,CAUrD;AA2CD;;;;;;GAMG;AACH,wBAAsB,eAAe,CACnC,KAAK,EAAE;IAAE,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAA;CAAE,EACzF,IAAI,GAAE,eAAoB,GACzB,OAAO,CAAC,mBAAmB,CAAC,CA6B9B"}