Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .changeset/brave-dragons-fly.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@chat-adapter/feishu": minor
"chat": patch
"@chat-adapter/shared": patch
---

Add Feishu (Lark) adapter for chat SDK
7 changes: 6 additions & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ pnpm --filter chat build
pnpm --filter @chat-adapter/slack build
pnpm --filter @chat-adapter/gchat build
pnpm --filter @chat-adapter/teams build
pnpm --filter @chat-adapter/feishu build

# Run tests for a specific package
pnpm --filter chat test
Expand All @@ -59,6 +60,7 @@ This is a **pnpm monorepo** using **Turborepo** for build orchestration. All pac
- **`packages/adapter-slack`** - Slack adapter using `@slack/web-api`
- **`packages/adapter-gchat`** - Google Chat adapter using `googleapis`
- **`packages/adapter-teams`** - Microsoft Teams adapter using `botbuilder`
- **`packages/adapter-feishu`** - Feishu (Lark) adapter using direct fetch
- **`packages/state-memory`** - In-memory state adapter (for development/testing)
- **`packages/state-redis`** - Redis state adapter (for production)
- **`packages/integration-tests`** - Integration tests against real platform APIs
Expand All @@ -67,7 +69,7 @@ This is a **pnpm monorepo** using **Turborepo** for build orchestration. All pac
### Core Concepts

1. **Chat** (`packages/chat-sdk/src/chat.ts` in `chat` package) - Main entry point that coordinates adapters and handlers
2. **Adapter** - Platform-specific implementations (Slack, Teams, Google Chat). Each adapter:
2. **Adapter** - Platform-specific implementations (Slack, Teams, Google Chat, Feishu). Each adapter:
- Handles webhook verification and parsing
- Converts platform-specific message formats to/from normalized format
- Provides `FormatConverter` for markdown/AST transformations
Expand All @@ -82,6 +84,7 @@ All thread IDs follow the pattern: `{adapter}:{channel}:{thread}`
- Slack: `slack:C123ABC:1234567890.123456`
- Teams: `teams:{base64(conversationId)}:{base64(serviceUrl)}`
- Google Chat: `gchat:spaces/ABC123:{base64(threadName)}`
- Feishu: `feishu:oc_abc123:om_msg456`

### Message Handling Flow

Expand Down Expand Up @@ -160,6 +163,7 @@ cat /tmp/recording.json | jq '[.[] | select(.type == "webhook")] | group_by(.pla
cat /tmp/recording.json | jq '[.[] | select(.type == "webhook" and .platform == "teams") | .body | fromjson]' > /tmp/teams-webhooks.json
cat /tmp/recording.json | jq '[.[] | select(.type == "webhook" and .platform == "slack") | .body | fromjson]' > /tmp/slack-webhooks.json
cat /tmp/recording.json | jq '[.[] | select(.type == "webhook" and .platform == "gchat") | .body | fromjson]' > /tmp/gchat-webhooks.json
cat /tmp/recording.json | jq '[.[] | select(.type == "webhook" and .platform == "feishu") | .body | fromjson]' > /tmp/feishu-webhooks.json

# Inspect specific webhook fields (e.g., Teams channelData)
cat /tmp/teams-webhooks.json | jq '[.[] | {type, text, channelData, value}]'
Expand Down Expand Up @@ -208,6 +212,7 @@ Key env vars used (see `turbo.json` for full list):
- `SLACK_BOT_TOKEN`, `SLACK_SIGNING_SECRET` - Slack credentials
- `TEAMS_APP_ID`, `TEAMS_APP_PASSWORD`, `TEAMS_APP_TENANT_ID` - Teams credentials
- `GOOGLE_CHAT_CREDENTIALS` or `GOOGLE_CHAT_USE_ADC` - Google Chat auth
- `FEISHU_APP_ID`, `FEISHU_APP_SECRET` - Feishu credentials
- `REDIS_URL` - Redis connection for state adapter
- `BOT_USERNAME` - Default bot username

Expand Down
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
[![npm downloads](https://img.shields.io/npm/dm/chat)](https://www.npmjs.com/package/chat)
[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)

A unified TypeScript SDK for building chat bots across Slack, Microsoft Teams, Google Chat, Discord, GitHub, and Linear. Write your bot logic once, deploy everywhere.
A unified TypeScript SDK for building chat bots across Slack, Microsoft Teams, Google Chat, Discord, GitHub, Linear, and Feishu (Lark). Write your bot logic once, deploy everywhere.

## Installation

Expand All @@ -15,7 +15,7 @@ npm install chat
Install adapters for your platforms:

```bash
npm install @chat-adapter/slack @chat-adapter/teams @chat-adapter/gchat @chat-adapter/discord
npm install @chat-adapter/slack @chat-adapter/teams @chat-adapter/gchat @chat-adapter/discord @chat-adapter/feishu
```

## Usage
Expand Down Expand Up @@ -55,6 +55,7 @@ See the [Getting Started guide](https://chat-sdk.dev/docs/getting-started) for a
| Discord | `@chat-adapter/discord` | Yes | Yes | Yes | No | Post+Edit | Yes |
| GitHub | `@chat-adapter/github` | Yes | Yes | No | No | No | No |
| Linear | `@chat-adapter/linear` | Yes | Yes | No | No | No | No |
| Feishu | `@chat-adapter/feishu` | Yes | Yes | Yes | No | Post+Edit | Yes |

## Features

Expand All @@ -80,6 +81,7 @@ See the [Getting Started guide](https://chat-sdk.dev/docs/getting-started) for a
| `@chat-adapter/discord` | [Discord adapter](https://chat-sdk.dev/docs/adapters/discord) |
| `@chat-adapter/github` | [GitHub adapter](https://chat-sdk.dev/docs/adapters/github) |
| `@chat-adapter/linear` | [Linear adapter](https://chat-sdk.dev/docs/adapters/linear) |
| `@chat-adapter/feishu` | [Feishu adapter](https://chat-sdk.dev/docs/adapters/feishu) |
| `@chat-adapter/state-redis` | [Redis state adapter](https://chat-sdk.dev/docs/state/redis) (production) |
| `@chat-adapter/state-ioredis` | [ioredis state adapter](https://chat-sdk.dev/docs/state/ioredis) (alternative) |
| `@chat-adapter/state-memory` | [In-memory state adapter](https://chat-sdk.dev/docs/state/memory) (development) |
Expand Down
6 changes: 6 additions & 0 deletions examples/nextjs-chat/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -42,5 +42,11 @@ BOT_USERNAME=mybot
# LINEAR_WEBHOOK_SECRET=your-webhook-secret
# LINEAR_BOT_USERNAME=my-bot

# Feishu / Lark (optional)
# FEISHU_APP_ID=your-app-id
# FEISHU_APP_SECRET=your-app-secret
# FEISHU_ENCRYPT_KEY=your-encryption-key
# FEISHU_VERIFICATION_TOKEN=your-verification-token

# Redis (for production state persistence)
# REDIS_URL=redis://localhost:6379
8 changes: 6 additions & 2 deletions examples/nextjs-chat/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Next.js Chat Example

A full-featured example app demonstrating the Chat SDK with Next.js. Integrates with Slack, Microsoft Teams, Google Chat, Discord, GitHub, and Linear — configure whichever platforms you need via environment variables.
A full-featured example app demonstrating the Chat SDK with Next.js. Integrates with Slack, Microsoft Teams, Google Chat, Discord, GitHub, Linear, and Feishu (Lark) — configure whichever platforms you need via environment variables.

## Getting started

Expand Down Expand Up @@ -46,7 +46,7 @@ The app runs at `http://localhost:3000`. Platform webhooks should point to `/api
- **Ephemeral messages** — user-only visible messages with DM fallback
- **DMs** — programmatic direct message initiation
- **File uploads** — attachment detection and display
- **Multi-platform** — same bot logic across all six platforms
- **Multi-platform** — same bot logic across all seven platforms

## Project structure

Expand Down Expand Up @@ -82,6 +82,10 @@ Copy `.env.example` for the full list. At minimum, set `BOT_USERNAME` and creden
| `DISCORD_PUBLIC_KEY` | Discord interaction verification key |
| `GITHUB_TOKEN` | GitHub PAT or App credentials |
| `LINEAR_API_KEY` | Linear API key |
| `FEISHU_APP_ID` | Feishu app ID |
| `FEISHU_APP_SECRET` | Feishu app secret |
| `FEISHU_ENCRYPT_KEY` | Feishu event encryption key (optional) |
| `FEISHU_VERIFICATION_TOKEN` | Feishu webhook verification token (optional) |
| `REDIS_URL` | Redis connection string |

See the [Chat SDK docs](https://chat-sdk.dev/docs) for full platform setup guides.
Expand Down
1 change: 1 addition & 0 deletions examples/nextjs-chat/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
},
"dependencies": {
"@chat-adapter/discord": "workspace:*",
"@chat-adapter/feishu": "workspace:*",
"@chat-adapter/gchat": "workspace:*",
"@chat-adapter/github": "workspace:*",
"@chat-adapter/linear": "workspace:*",
Expand Down
22 changes: 22 additions & 0 deletions examples/nextjs-chat/src/lib/adapters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {
createDiscordAdapter,
type DiscordAdapter,
} from "@chat-adapter/discord";
import { createFeishuAdapter, type FeishuAdapter } from "@chat-adapter/feishu";
import {
createGoogleChatAdapter,
type GoogleChatAdapter,
Expand All @@ -18,6 +19,7 @@ const logger = new ConsoleLogger("info");

export interface Adapters {
discord?: DiscordAdapter;
feishu?: FeishuAdapter;
gchat?: GoogleChatAdapter;
github?: GitHubAdapter;
linear?: LinearAdapter;
Expand All @@ -36,6 +38,15 @@ const DISCORD_METHODS = [
"openDM",
"fetchMessages",
];
const FEISHU_METHODS = [
"postMessage",
"editMessage",
"deleteMessage",
"addReaction",
"removeReaction",
"startTyping",
"fetchMessages",
];
const SLACK_METHODS = [
"postMessage",
"editMessage",
Expand Down Expand Up @@ -187,5 +198,16 @@ export function buildAdapters(): Adapters {
}
}

// Feishu adapter (optional) - env vars: FEISHU_APP_ID, FEISHU_APP_SECRET
if (process.env.FEISHU_APP_ID) {
adapters.feishu = withRecording(
createFeishuAdapter({
logger: logger.child("feishu"),
}),
"feishu",
FEISHU_METHODS
);
}

return adapters;
}
56 changes: 56 additions & 0 deletions packages/adapter-feishu/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
{
"name": "@chat-adapter/feishu",
"version": "4.14.0",
"description": "Feishu (Lark) adapter for chat",
"type": "module",
"main": "./dist/index.js",
"module": "./dist/index.js",
"types": "./dist/index.d.ts",
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.js"
}
},
"files": [
"dist"
],
"scripts": {
"build": "tsup",
"dev": "tsup --watch",
"test": "vitest run --coverage",
"test:watch": "vitest",
"typecheck": "tsc --noEmit",
"clean": "rm -rf dist"
},
"dependencies": {
"@chat-adapter/shared": "workspace:*",
"chat": "workspace:*"
},
"devDependencies": {
"@types/node": "^22.10.2",
"tsup": "^8.3.5",
"typescript": "^5.7.2",
"vitest": "^2.1.8"
},
"repository": {
"type": "git",
"url": "git+https://github.com/vercel/chat.git",
"directory": "packages/adapter-feishu"
},
"homepage": "https://github.com/vercel/chat#readme",
"bugs": {
"url": "https://github.com/vercel/chat/issues"
},
"publishConfig": {
"access": "public"
},
"keywords": [
"chat",
"feishu",
"lark",
"bot",
"adapter"
],
"license": "MIT"
}
Loading