/** * Slack ingress channel — drive Franklin from a Slack workspace. * * Why this exists: same motivation as the Telegram channel, but for teams. * A persistent agent with a wallet is most useful when a whole channel can * reach it. This module wraps Franklin's `interactiveSession` with a Slack * Socket Mode connection: inbound @mentions (and DMs) → agent turn → streamed * text deltas posted back into the originating thread. * * Multi-user: unlike Telegram's single-owner lock, Slack uses an allowlist of * user ids (`SLACK_ALLOWED_USERS`). Anyone on the list can @mention the bot in * a channel or DM it; everyone else is ignored. The wallet is real money, so * an empty allowlist denies everyone by default. * * Session model (MVP v1): ONE shared session for the running bot, exactly like * the Telegram channel. All authorized users share a single Franklin * conversation. Replies always land in a thread so the channel stays tidy. * NOTE: Hermes-style per-thread isolation (a separate concurrent session per * Slack thread) is the planned v2 — it needs a session-manager that runs * multiple `interactiveSession` instances at once, which this single-queue * design intentionally does not do yet. * * Transport: Socket Mode (WebSocket via @slack/bolt), not Events API webhooks. * Works behind NAT / through laptop sleep-wake without a public HTTPS endpoint. */ import type { AgentConfig } from '../agent/types.js'; export interface SlackOptions { /** Bot User OAuth token (xoxb-…), from the Slack app's OAuth page. */ botToken: string; /** App-level token (xapp-…) with connections:write, for Socket Mode. */ appToken: string; /** Slack user ids allowed to drive the bot. Empty set denies everyone. */ allowedUsers: Set; /** Verbose: log every inbound event and turn on bolt's DEBUG logging. */ debug?: boolean; /** Called with each user-facing log line so the CLI can print them. */ log?: (line: string) => void; } /** * Split a long agent response into Slack-sized chunks. Prefers newline * boundaries, falls back to a hard character split for pathological inputs. * Short responses return a single chunk. Mirrors `splitForTelegram`. */ export declare function splitForSlack(text: string, max?: number): string[]; /** * Progressive flush: given a growing buffer, return `{flush, keep}` where * `flush` ends at a paragraph boundary and `keep` is the trailing partial to * hold until more arrives. Identical strategy to the Telegram channel. */ export declare function takeProgressiveChunk(buffer: string, threshold?: number, hardCap?: number): { flush: string; keep: string; }; /** * Start the bot. Resolves only on fatal error; the outer CLI handles SIGINT. */ export declare function runSlackBot(agentConfig: AgentConfig, opts: SlackOptions): Promise;