eve
Version:
Filesystem-first framework for durable backend AI agents that run anywhere.
65 lines (64 loc) • 2.85 kB
TypeScript
/**
* Slack `block_actions` + `view_submission` wire handling.
*
* The route handler reads the form-encoded body, hands it here, and we:
*
* 1. Decode `block_actions` payloads into a typed shape the channel can
* work with — actions, channel/thread metadata, the clicker, and the
* full original block list for answered-card updates.
* 2. Open the freeform-answer modal inline when the click was a "Type
* your answer" button (Slack's `trigger_id` is only valid for ~3s,
* so this can't run under `waitUntil`).
* 3. Resolve `view_submission` payloads (freeform modal submissions)
* back into parked HITL requests via `send`.
*
* Anything we don't consume flows through to the user-supplied
* `onInteraction` callback. Always returns `Response("ok")` — followup
* work runs under `waitUntil` so the webhook ACK is immediate.
*/
import type { SlackChannelConfig, SlackChannelState, SlackInteractionAction } from "#public/channels/slack/slackChannel.js";
import type { SendFn } from "#public/definitions/defineChannel.js";
/**
* Decoded view of a Slack `block_actions` payload. Returned by
* {@link parseBlockActionsPayload} and read by the handler.
*/
interface ParsedBlockActionsPayload {
readonly actions: SlackInteractionAction[];
readonly channelId: string;
readonly threadTs: string;
readonly teamId: string | undefined;
/**
* The full block list off the clicked message. Preserved on the
* answered-card update so the original prompt stays visible after the
* interactive controls are stripped.
*/
readonly messageBlocks: readonly unknown[];
}
/**
* Decodes a Slack `block_actions` payload into a {@link ParsedBlockActionsPayload}.
* Returns `null` for payloads that don't carry the channel/thread
* metadata the handler needs.
*/
export declare function parseBlockActionsPayload(body: Record<string, unknown>): ParsedBlockActionsPayload | null;
/**
* Channel-supplied dependencies for {@link handleInteractionPost}.
*
* Carries the bits the handler needs that come from channel
* construction: credentials for outbound API calls and the user's
* `onInteraction` callback for non-HITL clicks.
*/
export interface InteractionHandlerDeps {
readonly config: SlackChannelConfig;
}
/**
* Entry point for Slack's form-encoded interactivity endpoint. Routes
* `view_submission` payloads to the freeform-answer flow, intercepts
* "Type your answer" button clicks to open a modal, resolves
* framework HITL clicks against the parked session, and forwards
* anything else to `config.onInteraction`.
*/
export declare function handleInteractionPost(rawBody: string, ctx: {
send: SendFn<SlackChannelState>;
waitUntil: (task: Promise<unknown>) => void;
}, deps: InteractionHandlerDeps): Promise<Response>;
export type { ParsedBlockActionsPayload };