From e9eda754b41650e0cf891d6803c84c8cbbe22670 Mon Sep 17 00:00:00 2001 From: Johnny Date: Mon, 26 Jan 2026 17:12:14 +0800 Subject: [PATCH] docs(feishu): document long connection mode --- docs/channels/feishu.md | 40 ++++++++-- docs/channels/index.md | 2 +- extensions/feishu/docs/feishu.md | 40 ++++++++-- extensions/feishu/spec/design.md | 10 ++- extensions/feishu/spec/proposal.md | 122 ++--------------------------- extensions/feishu/spec/spec.md | 16 +++- extensions/feishu/spec/tasks.md | 11 ++- 7 files changed, 101 insertions(+), 140 deletions(-) diff --git a/docs/channels/feishu.md b/docs/channels/feishu.md index 6095e951c..93f18b732 100644 --- a/docs/channels/feishu.md +++ b/docs/channels/feishu.md @@ -2,12 +2,12 @@ summary: "Feishu bot support status, capabilities, and configuration" read_when: - You want to connect Clawdbot to Feishu - - You are debugging Feishu webhook callbacks + - You are debugging Feishu webhook callbacks or long connection events --- # Feishu (Bot API) -Status: experimental. HTTP callback only. Text messages only (V1). +Status: experimental. Text messages only (V1). Supports HTTP callback and long connection. ## Plugin required @@ -26,16 +26,40 @@ Feishu ships as a plugin and is not bundled with the core install. - `appId` - `appSecret` 3. Configure event subscription: - - Callback URL: `https://gateway.example.com/feishu` - Events: subscribe to `im.message.receive_v1` - - Set either a **verification token** or an **encrypt key** -4. Configure Clawdbot: + - Choose one delivery mode: + - **Long connection** (no public URL required) + - **HTTP callback** (public HTTPS webhook required) +4. Configure Clawdbot (choose one): + +### Long connection (mode: ws) ```json5 { channels: { feishu: { enabled: true, + mode: "ws", + appId: "cli_xxx", + appSecret: "xxx", + dm: { policy: "pairing" }, + groupPolicy: "allowlist", + groups: { + oc_xxx: { allow: true, requireMention: true }, + }, + }, + }, +} +``` + +### HTTP callback (mode: http) + +```json5 +{ + channels: { + feishu: { + enabled: true, + mode: "http", appId: "cli_xxx", appSecret: "xxx", verificationToken: "xxx", // or encryptKey: "xxx" @@ -50,10 +74,10 @@ Feishu ships as a plugin and is not bundled with the core install. } ``` -5. Start the gateway. Feishu will POST to the webhook path. +5. Start the gateway. In HTTP callback mode, Feishu will POST to the webhook path. 6. DM access is pairing by default; approve the pairing code on first contact. -## Webhook security +## Webhook security (mode: http) The plugin validates webhook requests using one of: @@ -98,6 +122,7 @@ Provider options: - `channels.feishu.enabled`: enable/disable the channel. - `channels.feishu.appId`: Feishu appId. - `channels.feishu.appSecret`: Feishu appSecret. +- `channels.feishu.mode`: `http | ws` (default `http`). - `channels.feishu.verificationToken`: webhook verification token. - `channels.feishu.encryptKey`: webhook encrypt key (signature validation + optional decryption). - `channels.feishu.webhookPath`: webhook path on the gateway HTTP server (default `/feishu`). @@ -111,6 +136,7 @@ Multi-account options: - `channels.feishu.accounts..appId` - `channels.feishu.accounts..appSecret` +- `channels.feishu.accounts..mode` - `channels.feishu.accounts..verificationToken` - `channels.feishu.accounts..encryptKey` - `channels.feishu.accounts..webhookPath` diff --git a/docs/channels/index.md b/docs/channels/index.md index 9542bb52c..f3328d6d5 100644 --- a/docs/channels/index.md +++ b/docs/channels/index.md @@ -17,7 +17,7 @@ Text is supported everywhere; media and reactions vary by channel. - [Discord](/channels/discord) — Discord Bot API + Gateway; supports servers, channels, and DMs. - [Slack](/channels/slack) — Bolt SDK; workspace apps. - [Google Chat](/channels/googlechat) — Google Chat API app via HTTP webhook. -- [Feishu](/channels/feishu) — Feishu Bot API via HTTP callback (plugin, installed separately). +- [Feishu](/channels/feishu) — Feishu Bot API via webhook or long connection (plugin, installed separately). - [Mattermost](/channels/mattermost) — Bot API + WebSocket; channels, groups, DMs (plugin, installed separately). - [Signal](/channels/signal) — signal-cli; privacy-focused. - [BlueBubbles](/channels/bluebubbles) — **Recommended for iMessage**; uses the BlueBubbles macOS server REST API with full feature support (edit, unsend, effects, reactions, group management — edit currently broken on macOS 26 Tahoe). diff --git a/extensions/feishu/docs/feishu.md b/extensions/feishu/docs/feishu.md index e60b3e21c..11e55e55a 100644 --- a/extensions/feishu/docs/feishu.md +++ b/extensions/feishu/docs/feishu.md @@ -2,12 +2,12 @@ summary: "Feishu bot support status, capabilities, and configuration" read_when: - You want to connect Clawdbot to Feishu - - You are debugging Feishu webhook callbacks + - You are debugging Feishu webhook callbacks or long connection events --- # Feishu (Bot API) -Status: experimental. HTTP callback only. Text messages only (V1). +Status: experimental. Text messages only (V1). Supports HTTP callback and long connection. ## Plugin required @@ -25,16 +25,40 @@ Feishu ships as a plugin and is not bundled with the core install. - `appId` - `appSecret` 3. Configure event subscription: - - Callback URL: `https://gateway.example.com/feishu` - Events: subscribe to `im.message.receive_v1` - - Set either a **verification token** or an **encrypt key** -4. Configure Clawdbot: + - Choose one delivery mode: + - **Long connection** (no public URL required) + - **HTTP callback** (public HTTPS webhook required) +4. Configure Clawdbot (choose one): + +### Long connection (mode: ws) ```json5 { channels: { feishu: { enabled: true, + mode: "ws", + appId: "cli_xxx", + appSecret: "xxx", + dm: { policy: "pairing" }, + groupPolicy: "allowlist", + groups: { + oc_xxx: { allow: true, requireMention: true }, + }, + }, + }, +} +``` + +### HTTP callback (mode: http) + +```json5 +{ + channels: { + feishu: { + enabled: true, + mode: "http", appId: "cli_xxx", appSecret: "xxx", verificationToken: "xxx", // or encryptKey: "xxx" @@ -49,10 +73,10 @@ Feishu ships as a plugin and is not bundled with the core install. } ``` -5. Start the gateway. Feishu will POST to the webhook path. +5. Start the gateway. In HTTP callback mode, Feishu will POST to the webhook path. 6. DM access is pairing by default; approve the pairing code on first contact. -## Webhook security +## Webhook security (mode: http) The plugin validates webhook requests using one of: @@ -83,6 +107,7 @@ Provider options: - `channels.feishu.enabled`: enable/disable the channel. - `channels.feishu.appId`: Feishu appId. - `channels.feishu.appSecret`: Feishu appSecret. +- `channels.feishu.mode`: `http | ws` (default `http`). - `channels.feishu.verificationToken`: webhook verification token. - `channels.feishu.encryptKey`: webhook encrypt key (signature validation + optional decryption). - `channels.feishu.webhookPath`: webhook path on the gateway HTTP server (default `/feishu`). @@ -96,6 +121,7 @@ Multi-account options: - `channels.feishu.accounts..appId` - `channels.feishu.accounts..appSecret` +- `channels.feishu.accounts..mode` - `channels.feishu.accounts..verificationToken` - `channels.feishu.accounts..encryptKey` - `channels.feishu.accounts..webhookPath` diff --git a/extensions/feishu/spec/design.md b/extensions/feishu/spec/design.md index bafffa941..4d3945371 100644 --- a/extensions/feishu/spec/design.md +++ b/extensions/feishu/spec/design.md @@ -4,11 +4,11 @@ Implement `@clawdbot/feishu` as a channel extension that: -- Registers a channel plugin (`api.registerChannel`) and an HTTP webhook handler (`api.registerHttpHandler`). -- Starts a per-account “monitor” on gateway start (via `plugin.gateway.startAccount`) that registers webhook targets and manages runtime status. +- Registers a channel plugin (`api.registerChannel`) and an HTTP handler (`api.registerHttpHandler`). +- Starts a per-account “monitor” on gateway start (via `plugin.gateway.startAccount`) that runs until aborted and manages runtime status. - Uses the existing Clawdbot reply pipeline (`runtime.channel.reply.dispatchReplyWithBufferedBlockDispatcher`) to route inbound messages to an agent and send outbound replies back to Feishu. -This follows the proven “webhook channel” structure in `extensions/googlechat`. +This follows the proven “webhook channel” structure in `extensions/googlechat`, with an additional long-connection transport option. ## Architecture @@ -27,6 +27,10 @@ This follows the proven “webhook channel” structure in `extensions/googlecha - Parses raw body, validates signature/token, decrypts if needed. - Handles `url_verification`. - Handles `im.message.receive_v1` text messages. +- **Long connection monitor**: `extensions/feishu/src/ws.ts` + - Fetches long-connection endpoint config from Feishu. + - Connects to Feishu’s event WebSocket and acknowledges events quickly. +- **Inbound processing + routing**: `extensions/feishu/src/inbound.ts` - Applies DM + group policies and mention gating. - Builds inbound context and calls reply dispatcher. - Sends replies via Feishu REST API. diff --git a/extensions/feishu/spec/proposal.md b/extensions/feishu/spec/proposal.md index 4bae2f861..b6163fdf7 100644 --- a/extensions/feishu/spec/proposal.md +++ b/extensions/feishu/spec/proposal.md @@ -7,7 +7,7 @@ Clawdbot already supports several chat surfaces (e.g. Slack, Google Chat, Telegr ## Goals - Ship a Feishu **channel plugin** under `extensions/` (installable from npm) that can: - - Receive inbound messages (DM + group) via Feishu event subscription callback. + - Receive inbound messages (DM + group) via Feishu event subscription (HTTP callback or long connection). - Respond with text replies (agent replies + `clawdbot message send`). - Respect Clawdbot’s DM security model (pairing/allowlist/open/disabled). - Support group allowlists + mention gating behavior consistent with other channels. @@ -31,14 +31,15 @@ Single human operator running Clawdbot for personal use, inside one Feishu tenan 1. User installs and enables the Feishu plugin. 2. User creates a Feishu app (self-built/internal) with Bot capability enabled. -3. User configures event subscription callback URL (served by Clawdbot Gateway). +3. User configures event subscription delivery (HTTP callback or long connection). 4. User DMs the bot; unknown DMs get pairing code; after approval bot answers. 5. User adds bot to a group; bot responds only when allowed and mention-gated. ## Functional requirements (high-level) - Inbound: - - HTTP handler for Feishu event subscription callback. + - HTTP handler for Feishu event subscription callback (`mode="http"`). + - Long connection listener for Feishu event subscription (`mode="ws"`). - Support `url_verification` challenge handshake. - Validate inbound requests (signature and/or verification token). - Handle `im.message.receive_v1` events. @@ -64,7 +65,7 @@ Single human operator running Clawdbot for personal use, inside one Feishu tenan ## Decisions (confirmed) 1. **Region**: Feishu only. -2. **Inbound transport**: HTTP callback (event subscription webhook). +2. **Inbound transport**: HTTP callback and long connection. 3. **V1 scope**: text-only. ## Risks and mitigations @@ -73,52 +74,6 @@ Single human operator running Clawdbot for personal use, inside one Feishu tenan - Secret leakage: never log app secrets; store secrets only in config. - Rate limits: cache tokens; chunk outbound messages via existing chunker helpers. -\*\*\* Add File: extensions/feishu/spec/design.md - -# Tech design: Feishu (飞书) channel plugin - -## Summary - -Implement `@clawdbot/feishu` as a channel extension that: - -- Registers a channel plugin (`api.registerChannel`) and an HTTP webhook handler (`api.registerHttpHandler`). -- Starts a per-account “monitor” on gateway start (via `plugin.gateway.startAccount`) that registers webhook targets and manages runtime status. -- Uses the existing Clawdbot reply pipeline (`runtime.channel.reply.dispatchReplyWithBufferedBlockDispatcher`) to route inbound messages to an agent and send outbound replies back to Feishu. - -This follows the proven “webhook channel” structure in `extensions/googlechat`. - -## Architecture - -### Components - -- **Feishu plugin entrypoint**: `extensions/feishu/index.ts` - - Stores `PluginRuntime` (like `extensions/googlechat/src/runtime.ts`). - - Registers channel + HTTP handler. -- **Channel plugin**: `extensions/feishu/src/channel.ts` - - Config adapter (accounts, enabled/configured, allowFrom formatting). - - Outbound adapter (sendText). - - Security adapter (DM policy warnings, group policy warnings). - - Status adapter (probe + runtime snapshot). - - Gateway adapter (startAccount → register webhook target). -- **Monitor / webhook handler**: `extensions/feishu/src/monitor.ts` - - Parses raw body, validates signature/token, decrypts if needed. - - Handles `url_verification`. - - Handles `im.message.receive_v1` text messages. - - Applies DM + group policies and mention gating. - - Builds inbound context and calls reply dispatcher. - - Sends replies via Feishu REST API. -- **API client**: `extensions/feishu/src/api.ts` - - Token manager: `tenant_access_token/internal` (self-built apps). - - Send message / reply message endpoints. - - Bot info (`/open-apis/bot/v3/info`) to detect mentions. - -## Webhook verification and decryption - -### URL verification - -- Feishu sends a payload (plain or encrypted) where `type === "url_verification"` and includes `challenge`. -- The handler responds `200` with JSON: `{"challenge":""}`. - ### Decrypt algorithm - If payload has `encrypt`: @@ -154,16 +109,6 @@ Colocate tests in `extensions/feishu/src/` (Vitest). - Target normalization. - URL verification and event parsing. -\*\*\* Add File: extensions/feishu/spec/spec.md - -# Spec: Feishu channel extension - -## Requirements - -### Requirement: Channel plugin availability - -The system SHALL provide a Feishu chat channel as a Clawdbot extension plugin that can be installed and enabled without modifying core channel code. - #### Scenario: Plugin appears in onboarding catalog - **GIVEN** a user runs `clawdbot onboard` in a workspace that contains the Feishu plugin (local path) or can access it on npm @@ -241,60 +186,3 @@ The system SHALL expose Feishu channel health via `clawdbot channels status`, in - **GIVEN** the plugin is enabled but credentials are invalid - **WHEN** the user runs `clawdbot channels status --probe` - **THEN** the Feishu channel shows `probe=error` with an actionable message (e.g. token fetch failed) - -\*\*\* Add File: extensions/feishu/spec/tasks.md - -# Tasks: Add Feishu (飞书) channel extension - -## 1. Extension scaffold - -- [x] Create `extensions/feishu/` workspace package (`package.json`, `clawdbot.plugin.json`, `index.ts`, `src/`). -- [x] Add plugin catalog metadata in `extensions/feishu/package.json` (`clawdbot.channel` + `clawdbot.install`) so onboarding can install it. - -## 2. Config + normalization - -- [x] Define Feishu config Zod schema (extension-local) and expose it as `configSchema` via `buildChannelConfigSchema`. -- [x] Implement target normalization (`user:`, `chat:`) and allowlist formatting. -- [x] Implement account model (start with default account; keep `accounts` extensible). - -## 3. Token manager + API client - -- [x] Implement tenant access token fetch + cache (`/auth/v3/tenant_access_token/internal`). -- [x] Implement Feishu “bot info” fetch (`/bot/v3/info`) for mention gating. -- [x] Implement send message (`/im/v1/messages`) and reply message (`/im/v1/messages/:message_id/reply`). - -## 4. Webhook handler - -- [x] Implement `handleFeishuWebhookRequest(req,res)` and register via `api.registerHttpHandler`. -- [x] Support `url_verification` challenge response (plain + encrypted). -- [x] Implement secure validation: - - [x] Raw-body capture with size limit. - - [x] Signature verification when `encryptKey` is configured. - - [x] Verification token checks when `encryptKey` is not configured. -- [x] Implement decrypt for payloads with `encrypt`. - -## 5. Event processing + routing - -- [x] Handle `im.message.receive_v1` (text-only V1): - - [x] DM policy + pairing store integration (mirror GoogleChat monitor behavior). - - [x] Group policy allowlists + mention gating integration. - - [x] Control command gating for group chats. -- [x] Build inbound context via `runtime.channel.reply.finalizeInboundContext` and dispatch replies via buffered dispatcher. - -## 6. Outbound adapters - -- [x] Implement `outbound.sendText` for `clawdbot message send` and heartbeats. - -## 7. Status + probe - -- [x] Implement `status` adapter snapshot + summary. -- [x] Implement `probeAccount` to validate credentials (token + bot info). - -## 8. Onboarding - -- [x] Add onboarding adapter with prompts for app id/secret and webhook settings. - -## 9. Tests - -- [x] Add unit tests for: signature, decrypt, target normalization. -- [ ] Add unit tests for: url_verification, event parsing. diff --git a/extensions/feishu/spec/spec.md b/extensions/feishu/spec/spec.md index b4ce05d74..873231f1a 100644 --- a/extensions/feishu/spec/spec.md +++ b/extensions/feishu/spec/spec.md @@ -12,7 +12,7 @@ The system SHALL provide a Feishu chat channel as a Clawdbot extension plugin th - **WHEN** the user reaches the channel selection step - **THEN** Feishu is listed as an installable channel plugin with a docs link -### Requirement: Webhook endpoint and URL verification +### Requirement: Webhook endpoint and URL verification (mode: http) The system SHALL accept Feishu event subscription callbacks over HTTP and complete the platform “request URL verification” handshake. @@ -22,7 +22,7 @@ The system SHALL accept Feishu event subscription callbacks over HTTP and comple - **WHEN** Clawdbot receives the POST at the configured webhook path - **THEN** the response status is `200` and the response body is `{"challenge":""}` (JSON) -### Requirement: Request validation +### Requirement: Request validation (mode: http) The system SHALL validate inbound callback requests before processing events. @@ -32,7 +32,7 @@ The system SHALL validate inbound callback requests before processing events. - **WHEN** the request is received - **THEN** the request is rejected with `401` and no message processing occurs -### Requirement: Encrypted payload support +### Requirement: Encrypted payload support (mode: http) When configured with an encrypt key, the system SHALL decrypt payloads that use the `encrypt` envelope. @@ -83,3 +83,13 @@ The system SHALL expose Feishu channel health via `clawdbot channels status`, in - **GIVEN** the plugin is enabled but credentials are invalid - **WHEN** the user runs `clawdbot channels status --probe` - **THEN** the Feishu channel shows `probe=error` with an actionable message (e.g. token fetch failed) + +### Requirement: Long connection mode (mode: ws) + +The system SHALL support receiving Feishu events over long connection when `channels.feishu.mode="ws"` is configured. + +#### Scenario: Long connection receives events without public URL + +- **GIVEN** `channels.feishu.mode="ws"` and `channels.feishu.appId/appSecret` are configured +- **WHEN** the gateway starts +- **THEN** the plugin establishes a long connection to Feishu and can receive `im.message.receive_v1` events without an exposed webhook URL diff --git a/extensions/feishu/spec/tasks.md b/extensions/feishu/spec/tasks.md index 4cbe53612..22ba0d636 100644 --- a/extensions/feishu/spec/tasks.md +++ b/extensions/feishu/spec/tasks.md @@ -8,6 +8,7 @@ ## 2. Config + normalization - [x] Define Feishu config Zod schema (extension-local) and expose it as `configSchema` via `buildChannelConfigSchema`. +- [x] Add `mode: http | ws` to select HTTP callback vs long connection. - [x] Implement target normalization (`user:`, `chat:`) and allowlist formatting. - [x] Implement account model (start with default account; keep `accounts` extensible). @@ -46,9 +47,15 @@ ## 8. Onboarding -- [x] Add onboarding adapter with prompts for app id/secret and webhook settings. +- [x] Add onboarding adapter with prompts for app id/secret and delivery mode. -## 9. Tests +## 9. Long connection (WebSocket) + +- [x] Implement long connection transport (`mode="ws"`) for event subscriptions. +- [x] Acknowledge events quickly and process messages asynchronously. + +## 10. Tests - [x] Add unit tests for: signature, decrypt, target normalization. - [x] Add unit tests for: url_verification, event parsing. +- [x] Add unit tests for: long connection frame codec + monitor lifecycle.