Conversation
Ship a messenger-only persistent-connection transport so mainland Feishu and international Lark can pair, mention-route, and send text without a Cloud webhook or custom Desktop UI. Co-authored-by: Cursor <cursoragent@cursor.com>
| mentions: FeishuMention[], | ||
| botOpenId?: string | null, | ||
| ): boolean { | ||
| if (mentions.some((mention) => mention.mentioned_type === "bot")) { |
There was a problem hiding this comment.
match on a field the payload does not have. refer https://open.feishu.cn/document/server-docs/im-v1/message/events/receive
There was a problem hiding this comment.
Nice structure overall — follows the existing channel conventions and skipping
media downloads avoids a lot of trouble. One blocker though.
P0: group @mentions are never detected, so group chat does nothing by default.
isFeishuBotMention() has two ways to detect a mention and both are broken:
// A — field does not exist in the payload
if (mentions.some((m) => m.mentioned_type === "bot")) return true;
// B — never runs: botOpenId is always null
const trimmedBotOpenId = botOpenId?.trim();
if (!trimmedBotOpenId) return false;
return mentions.some((m) => m.id?.open_id === trimmedBotOpenId);There was a problem hiding this comment.
Agreed — thanks for catching this. mentioned_type isn't on the live im.message.receive_v1 mention object, and we were also passing botOpenId: null, so both checks were dead and mention-only groups dropped everything.
Fixed in d6fcaa4: start calls GET /open-apis/bot/v3/info, then isFeishuBotMention() matches mentions[].id.open_id against that bot open_id. mentioned_type is ignored. Tests cover the official-shaped payload (no mentioned_type), a mentioned_type: bot red herring.
Match mentions[].id.open_id from bot/v3/info instead of mentioned_type, which is not present on live im.message.receive_v1 payloads. Co-authored-by: Cursor <cursoragent@cursor.com>
|
Re-reviewed after the update — the P0 is resolved, and the fix is more thorough The regression test is the part I'd single out: keeping a fixture that still One new point — and a correction to my earlier suggestionI argued for failing The current shape has no recovery path, though. A single transient failure at A lazy retry covers both cases better than either fail-fast or warn-once: on the Still open from the earlier passBoth non-blocking as far as I'm concerned:
StandingI'm not a code owner on this repo and can't approve or gate the merge — please Reviewed with Comate CLI (model: Opus 5). Findings were verified |
Summary
feishuchannel (display name Feishu / Lark) over the Open Platform persistent connection (WebSocket). No webhook, cards, Drive, or custom Desktop screens.open_id(ou_*). Groups default to mention-only (matches the default@botevent scope).@allis not a bot mention. Bot/app senders are dropped.domainselects Feishu (open.feishu.cn) vs Lark (open.larksuite.com). Text send goes through the sharedMessageChanneltool.appId/appSecret/domainland on the existing flattenedChannelPluginAccountPatch(same shared create/update path as Signal), not a new discriminated patch union.Closes #4130.
Why
Mainland Feishu and international Lark are the same Open Platform with different consoles. A first-party plugin is what makes
letta channels configure/install/pairwork without a user-plugin manifest. Persistent connection is the local analog of Slack Socket Mode.Limits / non-goals
./channels/feishupackage export (Slack/Telegram subpaths shipped because Cloud needed them). Pureingress.ts/outbound.tsstay SDK-free for a later webhook host.allowBots.accounts.json.Verification
bun run check— 12/12bun test src/channels/feishu src/channels/registry-community-copy.test.ts— 34 passedformatChannelLifecycleErrorMessage(adapter test covers sanitizing before post).message_iddedup, and second App ID start are covered by tests that fail without this change.Live validation
No live Feishu/Lark app probe was run. Harness-only: injected SDK client, ingress/outbound unit tests, and the App ID uniqueness guard.
AI Disclosure
AI Tool(s) Used
Cursor
Human Verification
I have reviewed and understand every change in this pull request and take responsibility for its correctness.
Made with Cursor
Linear: https://linear.app/letta/issue/LET-11920/add-first-party-feishulark-channel-support