"use strict"; /** * Copyright (c) 2026 ByteDance Ltd. and/or its affiliates * SPDX-License-Identifier: MIT * * Shared helper functions for Feishu content converters. */ Object.defineProperty(exports, "__esModule", { value: true }); exports.extractMentionOpenId = extractMentionOpenId; exports.buildConvertContextFromItem = buildConvertContextFromItem; exports.resolveMentions = resolveMentions; const user_name_cache_1 = require("../inbound/user-name-cache.js"); const utils_1 = require("./utils.js"); /** 从 mention 的 id 字段提取 open_id(兼容事件推送的对象格式和 API 响应的字符串格式) */ function extractMentionOpenId(id) { if (typeof id === 'string') return id; if (id != null && typeof id === 'object' && 'open_id' in id) { const openId = id.open_id; return typeof openId === 'string' ? openId : ''; } return ''; } /** * Build a {@link ConvertContext} from a raw Feishu API message item. * * Extracts the `mentions` array that the IM API returns on each message * item and maps it into the key→MentionInfo / openId→MentionInfo * structures the converter system expects. */ function buildConvertContextFromItem(item, fallbackMessageId, accountId) { const mentions = new Map(); const mentionsByOpenId = new Map(); for (const m of item.mentions ?? []) { const openId = extractMentionOpenId(m.id); if (!openId) continue; const info = { key: m.key, openId, name: m.name ?? '', isBot: false, }; mentions.set(m.key, info); mentionsByOpenId.set(openId, info); } return { mentions, mentionsByOpenId, messageId: item.message_id ?? fallbackMessageId, accountId, resolveUserName: accountId ? (openId) => (0, user_name_cache_1.getUserNameCache)(accountId).get(openId) : undefined, }; } /** * Resolve mention placeholders in text. * * - Bot self-mention + stripBotMentions: leading-only strip. When the * self-mention sits at the very start of the message, drop it (the * `WasMentioned` envelope field already tells the agent "this message * was addressed to you", so the anchor is redundant). When it appears * mid-text, render it as plain `@Name` so the surrounding context still * reads naturally without leaving an inline anchor the LLM might echo * back into its reply. * - Non-bot mentions: replace the placeholder key with readable `@name`. */ function resolveMentions(text, ctx) { if (ctx.mentions.size === 0) return text; let result = text; for (const [key, info] of ctx.mentions) { if (info.isBot && ctx.stripBotMentions) { result = result.replace(new RegExp((0, utils_1.escapeRegExp)(key), 'g'), `@${info.name}`); const leadingPattern = new RegExp(`^\\s*@${(0, utils_1.escapeRegExp)(info.name)}[\\s,,::]*`); result = result.replace(leadingPattern, '').trimStart(); } else { result = result.replace(new RegExp((0, utils_1.escapeRegExp)(key), 'g'), `@${info.name}`); } } return result; }