Files
vercel__chat/LIMITATIONS.md
T
Malte Ubl d2ffcc2cbe The great rename
We've acquired `chat` on npm. This plan covers renaming all packages and setting up automated publishing.

| Current Name | New Name | Version |
|--------------|----------|---------|
| `chat-sdk` | `chat` | 4.0.0 |
| `@chat-sdk/slack` | `@chat-adapter/slack` | 4.0.0 |
| `@chat-sdk/gchat` | `@chat-adapter/gchat` | 4.0.0 |
| `@chat-sdk/teams` | `@chat-adapter/teams` | 4.0.0 |
| `@chat-sdk/state-memory` | `@chat-adapter/state-memory` | 4.0.0 |
| `@chat-sdk/state-redis` | `@chat-adapter/state-redis` | 4.0.0 |
| `@chat-sdk/state-ioredis` | `@chat-adapter/state-ioredis` | 4.0.0 |

1. **Main package** (`packages/chat-sdk/package.json`):
   - Change `"name": "chat-sdk"` → `"name": "chat"`
   - Change `"version": "0.1.0"` → `"version": "4.0.0"`

2. **Adapter packages**:
   - `packages/adapter-slack/package.json`: `@chat-sdk/slack` → `@chat-adapter/slack`
   - `packages/adapter-gchat/package.json`: `@chat-sdk/gchat` → `@chat-adapter/gchat`
   - `packages/adapter-teams/package.json`: `@chat-sdk/teams` → `@chat-adapter/teams`
   - Update all versions to `4.0.0`
   - Update dependency on `chat-sdk` → `chat`

3. **State packages**:
   - `packages/state-memory/package.json`: `@chat-sdk/state-memory` → `@chat-adapter/state-memory`
   - `packages/state-redis/package.json`: `@chat-sdk/state-redis` → `@chat-adapter/state-redis`
   - `packages/state-ioredis/package.json`: `@chat-sdk/state-ioredis` → `@chat-adapter/state-ioredis`
   - Update all versions to `4.0.0`
   - Update dependency on `chat-sdk` → `chat`

Update `peerDependencies` and `dependencies` in each package:

```json
// Before
"peerDependencies": {
  "chat-sdk": "workspace:*"
}

// After
"peerDependencies": {
  "chat": "workspace:*"
}
```

Search and replace across the codebase:

| Find | Replace |
|------|---------|
| `from "chat-sdk"` | `from "chat"` |
| `from 'chat-sdk'` | `from 'chat'` |
| `import("chat-sdk")` | `import("chat")` |
| `from "@chat-sdk/slack"` | `from "@chat-adapter/slack"` |
| `from "@chat-sdk/gchat"` | `from "@chat-adapter/gchat"` |
| `from "@chat-sdk/teams"` | `from "@chat-adapter/teams"` |
| `from "@chat-sdk/state-memory"` | `from "@chat-adapter/state-memory"` |
| `from "@chat-sdk/state-redis"` | `from "@chat-adapter/state-redis"` |
| `from "@chat-sdk/state-ioredis"` | `from "@chat-adapter/state-ioredis"` |

Update any references to old package names in:
- `pnpm-workspace.yaml`
- `turbo.json` (task filters)
- Root `package.json` scripts

1. **README.md files** in each package
2. **Examples** (`examples/nextjs-chat/`)
3. **AGENTS.md** and other docs
4. **JSDoc comments** referencing package names

1. **Install changesets**:
   ```bash
   pnpm add -D @changesets/cli
   pnpm changeset init
   ```

2. **Configure `.changeset/config.json`**:
   ```json
   {
     "$schema": "https://unpkg.com/@changesets/config@3.0.0/schema.json",
     "changelog": "@changesets/cli/changelog",
     "commit": false,
     "fixed": [],
     "linked": [
       ["chat", "@chat-adapter/*"]
     ],
     "access": "public",
     "baseBranch": "main",
     "updateInternalDependencies": "patch",
     "ignore": ["example-nextjs-chat"]
   }
   ```

3. **Add GitHub Action** (`.github/workflows/release.yml`):
   ```yaml
   name: Release

   on:
     push:
       branches:
         - main

   concurrency: ${{ github.workflow }}-${{ github.ref }}

   jobs:
     release:
       name: Release
       runs-on: ubuntu-latest
       steps:
         - uses: actions/checkout@v4
         - uses: pnpm/action-setup@v2
           with:
             version: 9
         - uses: actions/setup-node@v4
           with:
             node-version: 20
             cache: 'pnpm'

         - run: pnpm install
         - run: pnpm build
         - run: pnpm test

         - name: Create Release Pull Request or Publish
           uses: changesets/action@v1
           with:
             publish: pnpm changeset publish
           env:
             GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
             NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
   ```

4. **Add publish config to each package.json**:
   ```json
   "publishConfig": {
     "access": "public"
   }
   ```

1. Run full build: `pnpm build`
2. Run typecheck: `pnpm typecheck`
3. Run lint: `pnpm lint`
4. Run tests: `pnpm test`
5. Test local linking in example app

| File | Changes |
|------|---------|
| `packages/chat-sdk/package.json` | Rename to `chat`, version 4.0.0 |
| `packages/adapter-slack/package.json` | Rename to `@chat-adapter/slack`, update deps |
| `packages/adapter-gchat/package.json` | Rename to `@chat-adapter/gchat`, update deps |
| `packages/adapter-teams/package.json` | Rename to `@chat-adapter/teams`, update deps |
| `packages/state-memory/package.json` | Rename to `@chat-adapter/state-memory`, update deps |
| `packages/state-redis/package.json` | Rename to `@chat-adapter/state-redis`, update deps |
| `packages/state-ioredis/package.json` | Rename to `@chat-adapter/state-ioredis`, update deps |
| `examples/nextjs-chat/package.json` | Update all dependencies |
| `packages/integration-tests/package.json` | Update all dependencies |
| `turbo.json` | Update package references |
| All `*.ts` files | Update import statements |
| All `README.md` files | Update package names in docs |
| `.changeset/config.json` | Create new |
| `.github/workflows/release.yml` | Create new |

1. Update all `package.json` files (names, versions, dependencies)
2. Run `pnpm install` to update lockfile
3. Update all import statements in source files
4. Update all import statements in test files
5. Update documentation
6. Set up changesets
7. Run full validation
8. Create initial changeset for 4.0.0 release
9. Commit and push

If issues arise:
1. Git revert the rename commit
2. Run `pnpm install` to restore lockfile
3. Previous npm versions remain available
2026-01-02 13:56:55 -08:00

7.2 KiB

Platform Limitations

This document outlines the capabilities and limitations of each chat platform adapter.

Feature Support Matrix

Feature Slack Teams Google Chat
postMessage ✅ ✅ ✅
editMessage ✅ ✅ ✅
deleteMessage ✅ ✅ ✅
addReaction ✅ ❌ ⚠️*
removeReaction ✅ ❌ ⚠️*
onReaction events ✅ ✅ ✅*
startTyping ❌ ✅ ❌
fetchMessages ✅ ❌ ✅
fetchThread ✅ ✅ ✅

Platform-Specific Details

Slack

Limitations:

  • Typing indicators: Slack does not provide an API for bots to show typing indicators. The startTyping method is a no-op.

Notes:

  • Bot user ID is auto-discovered via auth.test API call during initialization
  • Supports both bot_id and user fields for message author identification
  • File attachments require appropriate OAuth scopes (files:read)

Microsoft Teams

Limitations:

  • Adding reactions: Teams Bot Framework does not expose APIs for bots to add reactions. addReaction and removeReaction will throw NotImplementedError.
  • Message history: Teams does not provide a bot API to fetch message history. fetchMessages will throw NotImplementedError.

Supported:

  • Reaction events: Bots can receive MessageReaction activities when users add/remove reactions via onReaction().
  • Typing indicators: Supported via ActivityTypes.Typing

Notes:

  • Bot identification uses appId matching against activity.from.id
  • Service URL varies by tenant and must be preserved per conversation
  • Proactive messaging requires storing conversation references

Google Chat

Limitations:

  • Typing indicators: Google Chat does not provide an API for typing indicators. The startTyping method is a no-op.
  • Reactions (addReaction/removeReaction): The Google Chat API does not support service account (app) authentication for adding or removing reactions. To use these methods, you must use domain-wide delegation to impersonate a user, but the reaction will appear as coming from that user, not the bot. This is a Google Chat API limitation.

Notes:

  • Bot user ID is learned dynamically from message annotations (when bot is @mentioned)
  • Supports both HTTP endpoint and Pub/Sub delivery modes
  • Workspace Events API subscriptions are auto-managed for Pub/Sub mode
  • removeReaction works by listing reactions and finding by emoji (extra API call)

isMe Detection

Each adapter detects if a message is from the bot itself using a helper method isMessageFromSelf():

Slack

  • Checks event.user === botUserId (primary - for messages sent as bot user)
  • Checks event.bot_id === botId (secondary - for bot_message subtypes)
  • Both IDs are fetched during initialize() via auth.test
  • Returns false if neither ID is known (safe default)

Teams

  • Checks exact match: activity.from.id === appId
  • Checks suffix match: activity.from.id ends with :{appId} (handles 28:{appId} format)
  • The app ID is always known from configuration
  • Returns false if appId is not configured (safe default)

Google Chat

  • Checks exact match: message.sender.name === botUserId
  • Bot user ID is learned dynamically from message annotations when bot is @mentioned
  • No fallback: Returns false if bot ID is not yet learned (safer than assuming all BOT messages are from self)
  • Bot ID is persisted to state for serverless environments

Error Handling

All adapters throw errors on API failures. Specific error types:

  • RateLimitError: Thrown when platform rate limits are exceeded (429 responses)
  • NotImplementedError: Thrown when calling unsupported features

Reaction Events

The SDK provides onReaction() to handle emoji reaction events. Support varies by platform:

Platform Support

Platform Supported Notes
Slack ✅ Via reaction_added and reaction_removed events
Teams ✅ Via reactionsAdded and reactionsRemoved in MessageReaction activities
Google Chat ✅* Requires Workspace Events API (Pub/Sub subscription)

*Google Chat reaction events are only delivered via Pub/Sub (Workspace Events API), not direct HTTP webhooks.

GChat addReaction limitation: The Google Chat API does not support adding reactions with service account authentication. Bots can receive reaction events but cannot add reactions as themselves. To add reactions, use domain-wide delegation to impersonate a user (the reaction will appear from that user, not the bot).

Emoji Normalization

Platforms use different formats for emoji:

  • Slack: Names like +1, thumbsup, fire
  • Teams: Names like like, heart, laugh
  • Google Chat: Unicode like 👍, 🔥

The SDK normalizes these to EmojiValue objects with a common name property:

Normalized Name Slack Teams Google Chat
thumbs_up +1, thumbsup like 👍
thumbs_down -1, thumbsdown dislike 👎
heart heart heart ❤️, ❤
fire fire - 🔥
check white_check_mark - ✅, ✔️
rocket rocket - 🚀
... (86 total well-known emoji)

Extending Emoji Types

You can extend the emoji system with custom emoji using createEmoji():

import { createEmoji, emoji } from "chat";

// Create custom emoji with cross-platform mappings
const myEmoji = createEmoji({
  unicorn: { slack: "unicorn_face", gchat: "🦄" },
  company_logo: { slack: "company", gchat: "🏢" },
});

// Use type-safe emoji values in reactions
chat.onReaction([emoji.thumbs_up, myEmoji.unicorn], async (event) => {
  // event.emoji is an EmojiValue object
  console.log(event.emoji.name); // "thumbs_up" or "unicorn"
});

For TypeScript module augmentation to extend the global emoji helper:

declare module "chat" {
  interface CustomEmojiMap {
    unicorn: true;
    custom_team_emoji: true;
  }
}

ReactionEvent Properties

Property Type Description
emoji EmojiValue Normalized emoji object with name, unicode, etc.
rawEmoji string Platform-specific emoji (e.g., +1, like, or 👍)
added boolean true if reaction was added, false if removed
user Author The user who added/removed the reaction
messageId string ID of the message that was reacted to
threadId string Thread ID for the message
adapter Adapter The adapter that received the event
raw unknown Raw platform event data

Markdown Support

Feature Slack Teams Google Chat
Bold ✅ *text* ✅ **text** ✅ *text*
Italic ✅ _text_ ✅ _text_ ✅ _text_
Strikethrough ✅ ~text~ ✅ ~~text~~ ✅ ~text~
Code ✅ `code` ✅ `code` ✅ `code`
Code blocks ✅ ✅ ✅
Links ✅ <url|text> ✅ [text](url) ✅ [text](url)
Lists ✅ ✅ ✅
Blockquotes ✅ > ✅ > ⚠️ Simulated with > prefix
Mentions ✅ <@USER> ✅ <at>name</at> ✅ <users/{id}>