UNPKG

chat

Version:

Unified chat abstraction for Slack, Teams, Google Chat, and Discord

167 lines (122 loc) 5.89 kB
--- title: Creating a Chat Instance description: Initialize the Chat class with adapters, state, and configuration options. type: guide prerequisites: - /docs/getting-started related: - /docs/handling-events - /docs/adapters - /docs/state --- The `Chat` class is the main entry point for your bot. It coordinates adapters, routes events to your handlers, and manages thread state. ## Basic setup ```typescript title="lib/bot.ts" lineNumbers import { Chat } from "chat"; import { createSlackAdapter } from "@chat-adapter/slack"; import { createRedisState } from "@chat-adapter/state-redis"; const bot = new Chat({ userName: "mybot", adapters: { slack: createSlackAdapter(), }, state: createRedisState(), }); bot.onNewMention(async (thread) => { await thread.subscribe(); await thread.post("Hello! I'm listening to this thread."); }); ``` <Callout type="info"> This example uses Redis. Chat SDK also supports [PostgreSQL](/adapters/official/postgres) and [ioredis](/adapters/official/ioredis) as production state adapters. See [State Adapters](/docs/state) for all options. </Callout> Each adapter factory auto-detects credentials from environment variables (`SLACK_BOT_TOKEN`, `SLACK_SIGNING_SECRET`, `REDIS_URL`, etc.), so you can get started with zero config. Pass explicit values to override. ## Multiple adapters Register multiple [adapters](/adapters) to deploy your bot across platforms simultaneously: ```typescript title="lib/bot.ts" lineNumbers import { Chat } from "chat"; import { createSlackAdapter } from "@chat-adapter/slack"; import { createTeamsAdapter } from "@chat-adapter/teams"; import { createDiscordAdapter } from "@chat-adapter/discord"; import { createRedisState } from "@chat-adapter/state-redis"; const bot = new Chat({ userName: "mybot", adapters: { slack: createSlackAdapter(), teams: createTeamsAdapter(), discord: createDiscordAdapter(), }, state: createRedisState(), }); ``` Your event handlers work identically across all registered adapters — the SDK normalizes messages, threads, and reactions into a consistent format. ## Configuration options | Option | Type | Default | Description | |--------|------|---------|-------------| | `userName` | `string` | *required* | Default bot username across all adapters | | `adapters` | `Record<string, Adapter>` | *required* | Map of adapter name to adapter instance | | `state` | `StateAdapter` | *required* | State adapter for subscriptions and locking | | `logger` | `Logger \| LogLevel` | `"info"` | Logger instance or log level (`"debug"`, `"info"`, `"warn"`, `"error"`, `"silent"`) | | `dedupeTtlMs` | `number` | `300000` | TTL in ms for message deduplication (5 minutes) | | `concurrency` | `"drop" \| "queue" \| "debounce" \| "burst" \| "concurrent" \| ConcurrencyConfig` | `"drop"` | Strategy for overlapping messages on the same thread | | `streamingUpdateIntervalMs` | `number` | `500` | Update interval in ms for post+edit streaming | | `fallbackStreamingPlaceholderText` | `string \| null` | `"..."` | Placeholder text while streaming starts. Set to `null` to skip | | `onLockConflict` | `'drop' \| 'force' \| (threadId, message) => 'drop' \| 'force'` | `"drop"` | Behavior when a thread lock is already held. `'force'` releases the existing lock and re-acquires it, enabling interrupt/steerability for long-running handlers | ## Accessing adapters Use `getAdapter` to access platform-specific APIs when you need functionality beyond the unified interface: ```typescript title="lib/bot.ts" lineNumbers import type { SlackAdapter } from "@chat-adapter/slack"; const slack = bot.getAdapter("slack") as SlackAdapter; await slack.setSuggestedPrompts(channelId, threadTs, [ { title: "Get started", message: "What can you help me with?" }, ]); ``` For typed access to the platform's native API client, use the SDK-named getter on each adapter: ```typescript title="lib/bot.ts" lineNumbers const slack = bot.getAdapter("slack").webClient; // WebClient const linear = bot.getAdapter("linear").linearClient; // LinearClient const github = bot.getAdapter("github").octokit; // Octokit ``` The previous `.client` getter still works as a deprecated alias on all three adapters. See [`getAdapter`](/docs/api/chat#getadapter) for multi-tenant constraints. ## Webhook routing The `webhooks` property provides type-safe handlers for each registered adapter. Wire these up to your HTTP framework's routes: ```typescript title="app/api/webhooks/slack/route.ts" lineNumbers import { bot } from "@/lib/bot"; export const POST = bot.webhooks.slack; ``` ```typescript title="app/api/webhooks/teams/route.ts" lineNumbers import { bot } from "@/lib/bot"; export const POST = bot.webhooks.teams; ``` ## Lifecycle The Chat instance initializes lazily on the first webhook. You can also initialize manually: ```typescript title="lib/bot.ts" lineNumbers await bot.initialize(); ``` For graceful shutdown (e.g. in serverless teardown), call `shutdown`: ```typescript title="lib/bot.ts" lineNumbers await bot.shutdown(); ``` ## Singleton pattern Register a singleton when you need to access the Chat instance from multiple files: ```typescript title="lib/bot.ts" lineNumbers const bot = new Chat({ /* ...config */ }).registerSingleton(); export default bot; ``` ```typescript title="lib/utils.ts" lineNumbers import { Chat } from "chat"; const bot = Chat.getSingleton(); ``` ## Direct messaging Open a DM thread with a user by passing their platform user ID or an `Author` object: ```typescript title="lib/bot.ts" lineNumbers const dm = await bot.openDM("U123ABC"); await dm.post("Hey! Just wanted to follow up on your request."); ``` ## Channel access Get a channel directly by its ID: ```typescript title="lib/bot.ts" lineNumbers const channel = bot.channel("slack:C123ABC"); await channel.post("Announcement: deploy complete!"); ```