From e722c9233aeead00c85ec0d974debd6cb1e78a72 Mon Sep 17 00:00:00 2001 From: maxwell <> Date: Thu, 29 Jan 2026 18:11:33 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=94=AF=E6=8C=81=E7=BE=A4=E8=81=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/channels/feishu.md | 1 + extensions/feishu/src/monitor.ts | 62 ++++++++++++++++++++----- src/config/types.feishu.ts | 2 + src/config/zod-schema.providers-core.ts | 1 + 4 files changed, 55 insertions(+), 11 deletions(-) diff --git a/docs/channels/feishu.md b/docs/channels/feishu.md index cf191b4e9..1d648cca5 100644 --- a/docs/channels/feishu.md +++ b/docs/channels/feishu.md @@ -57,3 +57,4 @@ Multi-account example: - `channels.feishu.dm.allowFrom`: allowlist for DMs when policy is `allowlist` or `open`. - `channels.feishu.groupPolicy`: `open`, `allowlist`, or `disabled`. - `channels.feishu.groups`: per-chat overrides keyed by `chat_id` (supports `requireMention`, `tools`, `users`). +- `channels.feishu.sessionPerMessage`: start a new session for each inbound message (no history). diff --git a/extensions/feishu/src/monitor.ts b/extensions/feishu/src/monitor.ts index 5b7c9b375..c25811861 100644 --- a/extensions/feishu/src/monitor.ts +++ b/extensions/feishu/src/monitor.ts @@ -32,6 +32,12 @@ type FeishuSender = { }; }; +type FeishuMention = { + id?: { open_id?: string; user_id?: string; union_id?: string }; + key?: string; + name?: string; +}; + type FeishuMessage = { chat_id?: string; chat_type?: string; @@ -41,11 +47,13 @@ type FeishuMessage = { create_time?: string; root_id?: string; parent_id?: string; + mentions?: FeishuMention[]; }; type FeishuMessageEvent = { message?: FeishuMessage; sender?: FeishuSender; + mentions?: FeishuMention[]; }; type FeishuCoreRuntime = ReturnType; @@ -91,18 +99,27 @@ function resolveSenderInfo( return null; } -function parseMessageText(params: { +type ParsedMessageContent = { + text: string; + hasAnyMention: boolean; +}; + +function parseMessageContent(params: { content: string; runtime: FeishuRuntimeEnv; accountId: string; -}): string | null { +}): ParsedMessageContent | null { const trimmed = params.content.trim(); if (!trimmed) return null; try { const parsed = JSON.parse(trimmed) as unknown; if (!parsed || typeof parsed !== "object") return null; const text = (parsed as { text?: unknown }).text; - return typeof text === "string" ? text : null; + if (typeof text !== "string") return null; + const mentions = (parsed as { mentions?: unknown }).mentions; + const hasMentions = Array.isArray(mentions) && mentions.length > 0; + const hasInlineMention = / 0; +} + +function resolvePerMessageSessionKey(baseKey: string, message: FeishuMessage): string { + const messageId = message.message_id?.trim(); + const messageTime = message.create_time?.trim(); + const suffix = messageId || messageTime || String(Date.now()); + return `${baseKey}:msg:${suffix}`.toLowerCase(); +} + +function resolveMentionState(params: { + text: string; + hasAnyMention?: boolean; +}): { hasAnyMention: boolean; wasMentioned: boolean } { + const hasAnyMention = params.hasAnyMention ?? / { diff --git a/src/config/types.feishu.ts b/src/config/types.feishu.ts index 7497db231..63074eb54 100644 --- a/src/config/types.feishu.ts +++ b/src/config/types.feishu.ts @@ -78,6 +78,8 @@ export type FeishuAccountConfig = { mediaMaxMb?: number; /** Control reply threading when reply tags are present (off|first|all). */ replyToMode?: ReplyToMode; + /** Start a new session for every inbound message (no history). */ + sessionPerMessage?: boolean; dm?: FeishuDmConfig; groups?: Record; /** Heartbeat visibility settings for this channel. */ diff --git a/src/config/zod-schema.providers-core.ts b/src/config/zod-schema.providers-core.ts index 29e04df7b..6cdacaaf6 100644 --- a/src/config/zod-schema.providers-core.ts +++ b/src/config/zod-schema.providers-core.ts @@ -333,6 +333,7 @@ export const FeishuAccountSchema = z blockStreamingCoalesce: BlockStreamingCoalesceSchema.optional(), mediaMaxMb: z.number().positive().optional(), replyToMode: ReplyToModeSchema.optional(), + sessionPerMessage: z.boolean().optional(), dm: FeishuDmSchema.optional(), groups: z.record(z.string(), FeishuGroupSchema.optional()).optional(), heartbeat: ChannelHeartbeatVisibilitySchema,