review-mark 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +249 -0
- package/dist/cli/review.cjs +710 -0
- package/dist/cli/review.cjs.map +1 -0
- package/dist/cli/review.d.cts +2 -0
- package/dist/cli/review.d.ts +2 -0
- package/dist/cli/review.js +687 -0
- package/dist/cli/review.js.map +1 -0
- package/dist/index.cjs +634 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +53 -0
- package/dist/index.d.ts +53 -0
- package/dist/index.js +597 -0
- package/dist/index.js.map +1 -0
- package/package.json +52 -0
- package/src/cli/review.ts +125 -0
- package/src/constants.ts +7 -0
- package/src/core/BeLinkReview.ts +274 -0
- package/src/core/feishu.ts +271 -0
- package/src/core/git.ts +63 -0
- package/src/core/prompt.ts +12 -0
- package/src/index.ts +2 -0
- package/src/types.ts +18 -0
- package/src/utils/checkCli.ts +127 -0
- package/tsconfig.json +26 -0
- package/tsup.config.ts +30 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/cli/review.ts","../../src/core/BeLinkReview.ts","../../src/utils/checkCli.ts","../../src/core/git.ts","../../src/core/prompt.ts","../../src/core/feishu.ts","../../src/constants.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport { BeLinkReview } from \"../core/BeLinkReview\";\n\nconst program = new Command();\n\nprogram\n .name(\"belink-review\")\n .description(\"AI-powered code review tool\")\n .version(\"1.0.0\")\n .option(\n \"--apiKey <key>\",\n \"Cursor API Key (overrides CURSOR_API_KEY environment variable)\"\n )\n .option(\n \"--agentPath <path>\",\n \"Path to the Cursor CLI agent executable (overrides CURSOR_AGENT_PATH environment variable)\"\n )\n .option(\n \"--ignore <patterns>\",\n \"Comma-separated list of glob patterns to ignore (e.g., *.lock,dist/**)\"\n )\n .option(\n \"--feishu-app-id <appId>\",\n \"Feishu App ID (overrides FEISHU_APP_ID environment variable)\"\n )\n .option(\n \"--feishu-app-secret <appSecret>\",\n \"Feishu App Secret (overrides FEISHU_APP_SECRET environment variable)\"\n )\n .option(\n \"--feishu-receive-id <receiveId>\",\n \"Feishu Receive ID - user open_id or chat_id (overrides FEISHU_RECEIVE_ID environment variable)\"\n )\n .option(\n \"--feishu-receive-id-type <type>\",\n \"Feishu Receive ID Type: open_id, user_id, chat_id, email, union_id (default: chat_id)\"\n )\n .option(\n \"--feishu-type <type>\",\n \"Feishu message type: text, post, or interactive (default: interactive)\"\n )\n .option(\n \"--feishu-title <title>\",\n \"Feishu message title (default: 🔍 Code Review 结果)\"\n )\n .option(\"--no-feishu\", \"Disable Feishu notification\")\n .action(async (options) => {\n try {\n const ignorePatterns = options.ignore\n ? options.ignore.split(\",\")\n : undefined;\n\n const instance = BeLinkReview.getInstance(\n options.apiKey,\n options.agentPath,\n ignorePatterns,\n options.feishu !== false\n );\n await instance.goCli();\n } catch (error: any) {\n console.error(`[be-link-review] Error: ${error.message}`);\n process.exit(1);\n }\n });\n\nprogram\n .command(\"review\")\n .description(\"Perform an AI code review on git diff\")\n .option(\n \"--apiKey <key>\",\n \"Cursor API Key (overrides CURSOR_API_KEY environment variable)\"\n )\n .option(\n \"--agentPath <path>\",\n \"Path to the Cursor CLI agent executable (overrides CURSOR_AGENT_PATH environment variable)\"\n )\n .option(\n \"--ignore <patterns>\",\n \"Comma-separated list of glob patterns to ignore (e.g., *.lock,dist/**)\"\n )\n .option(\n \"--feishu-app-id <appId>\",\n \"Feishu App ID (overrides FEISHU_APP_ID environment variable)\"\n )\n .option(\n \"--feishu-app-secret <appSecret>\",\n \"Feishu App Secret (overrides FEISHU_APP_SECRET environment variable)\"\n )\n .option(\n \"--feishu-receive-id <receiveId>\",\n \"Feishu Receive ID - user open_id or chat_id (overrides FEISHU_RECEIVE_ID environment variable)\"\n )\n .option(\n \"--feishu-receive-id-type <type>\",\n \"Feishu Receive ID Type: open_id, user_id, chat_id, email, union_id (default: chat_id)\"\n )\n .option(\n \"--feishu-type <type>\",\n \"Feishu message type: text, post, or interactive (default: interactive)\"\n )\n .option(\n \"--feishu-title <title>\",\n \"Feishu message title (default: 🔍 Code Review 结果)\"\n )\n .option(\"--no-feishu\", \"Disable Feishu notification\")\n .action(async (options) => {\n try {\n const ignorePatterns = options.ignore\n ? options.ignore.split(\",\")\n : undefined;\n\n const instance = BeLinkReview.getInstance(\n options.apiKey,\n options.agentPath,\n ignorePatterns,\n options.feishu !== false\n );\n await instance.goCli();\n } catch (error: any) {\n console.error(`[be-link-review] Error: ${error.message}`);\n process.exit(1);\n }\n });\n\nprogram.parse(process.argv);\n","import { spawn } from \"node:child_process\";\nimport { readFileSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport type {\n BeLinkReviewOptions,\n BeLinkReviewChatOptions,\n BeLinkReviewEnsureResult,\n} from \"../types\";\nimport { isCheckCliInstall } from \"../utils/checkCli\";\nimport { getGitDiff } from \"./git\";\nimport { generateAIPrompt } from \"./prompt\";\nimport { sendReviewToFeishu } from \"./feishu\";\n\nexport class BeLinkReview {\n static #instance: BeLinkReview | null = null;\n #apiKey: string | undefined;\n #agentPath: string | undefined;\n #ignorePatterns: string[] | undefined;\n #enableFeishu: boolean;\n\n private constructor(\n apiKey?: string,\n agentPath?: string,\n ignorePatterns?: string[],\n enableFeishu: boolean = true\n ) {\n this.#apiKey = apiKey;\n this.#agentPath = agentPath;\n this.#ignorePatterns = ignorePatterns;\n this.#enableFeishu = enableFeishu;\n }\n\n /**\n * 初始化单例并注入参数,在项目入口调用一次即可。\n * 负责保存 apiKey 和自动写入 package.json 脚本。\n * 此方法主要用于在用户项目中设置 apiKey 和脚本,CLI 运行时会优先从环境变量或命令行参数获取。\n */\n static init(options: BeLinkReviewOptions = {}): BeLinkReview {\n if (BeLinkReview.#instance === null) {\n BeLinkReview.#instance = new BeLinkReview(\n options.apiKey,\n options.agentPath,\n options.ignore,\n options.enableFeishu ?? true\n );\n } else {\n BeLinkReview.#instance.#apiKey = options.apiKey; // 允许重新初始化时更新 apiKey\n BeLinkReview.#instance.#agentPath = options.agentPath; // 允许重新初始化时更新 agentPath\n BeLinkReview.#instance.#ignorePatterns = options.ignore; // 允许重新初始化时更新 ignorePatterns\n BeLinkReview.#instance.#enableFeishu = options.enableFeishu ?? true; // 允许重新初始化时更新飞书开关\n }\n BeLinkReview.#instance.#setupProjectScript();\n return BeLinkReview.#instance;\n }\n\n /**\n * 获取单例实例。如果未通过 init() 初始化,则尝试从环境变量 CURSOR_API_KEY 获取。\n * @param cliApiKey 可选的命令行传入的 apiKey\n * @param cliAgentPath 可选的命令行传入的 agentPath\n * @param cliIgnorePatterns 可选的命令行传入的 ignorePatterns\n * @param cliEnableFeishu 可选的命令行传入的飞书开关\n */\n static getInstance(\n cliApiKey?: string,\n cliAgentPath?: string,\n cliIgnorePatterns?: string[],\n cliEnableFeishu?: boolean\n ): BeLinkReview {\n if (BeLinkReview.#instance === null) {\n const apiKey = cliApiKey || process.env.CURSOR_API_KEY;\n const agentPath = cliAgentPath || process.env.CURSOR_AGENT_PATH;\n const ignorePatterns =\n cliIgnorePatterns ||\n (process.env.BE_LINK_REVIEW_IGNORE\n ? process.env.BE_LINK_REVIEW_IGNORE.split(\",\")\n : undefined);\n const enableFeishu = cliEnableFeishu ?? (process.env.FEISHU_ENABLED !== \"false\");\n\n if (!apiKey) {\n throw new Error(\n '[be-link-review] 请先调用 BeLinkReview.init({ apiKey: \"...\" }) 初始化,或设置环境变量 CURSOR_API_KEY,或通过命令行参数 --apiKey 传入。'\n );\n }\n BeLinkReview.#instance = new BeLinkReview(\n apiKey,\n agentPath,\n ignorePatterns,\n enableFeishu\n );\n } else {\n // 如果单例已存在,但参数未设置,且命令行传入了,则更新\n if (cliApiKey && !BeLinkReview.#instance.#apiKey) {\n BeLinkReview.#instance.#apiKey = cliApiKey;\n }\n if (cliAgentPath && !BeLinkReview.#instance.#agentPath) {\n BeLinkReview.#instance.#agentPath = cliAgentPath;\n }\n if (cliIgnorePatterns && !BeLinkReview.#instance.#ignorePatterns) {\n BeLinkReview.#instance.#ignorePatterns = cliIgnorePatterns;\n }\n if (cliEnableFeishu !== undefined) {\n BeLinkReview.#instance.#enableFeishu = cliEnableFeishu;\n }\n }\n return BeLinkReview.#instance;\n }\n\n #getApiKey(): string {\n const apiKey = this.#apiKey || process.env.CURSOR_API_KEY;\n if (!apiKey) {\n throw new Error(\n '[be-link-review] 请先在 init({ apiKey: \"...\" }) 中传入 apiKey,或设置环境变量 CURSOR_API_KEY,或通过命令行参数 --apiKey 传入。'\n );\n }\n return apiKey;\n }\n\n #getAgentPath(): string | undefined {\n return this.#agentPath || process.env.CURSOR_AGENT_PATH;\n }\n\n #getIgnorePatterns(): string[] {\n const envIgnore = process.env.BE_LINK_REVIEW_IGNORE\n ? process.env.BE_LINK_REVIEW_IGNORE.split(\",\")\n : [];\n return this.#ignorePatterns || envIgnore;\n }\n\n #isFeishuEnabled(): boolean {\n return this.#enableFeishu;\n }\n\n /**\n * 自动往用户项目 package.json 写入 script\n */\n async #setupProjectScript() {\n try {\n const packageJsonPath = join(process.cwd(), \"package.json\");\n const packageJson = JSON.parse(readFileSync(packageJsonPath, \"utf-8\"));\n\n if (!packageJson.scripts) {\n packageJson.scripts = {};\n }\n\n if (!packageJson.scripts.review) {\n packageJson.scripts.review = \"belink-review\";\n writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2));\n console.log(\n \"[be-link-review] 已在 package.json 中添加 'review' 脚本。\"\n );\n } else {\n console.log(\"[be-link-review] 'review' 脚本已存在,跳过添加。\");\n }\n } catch (error) {\n console.error(\"[be-link-review] 无法更新 package.json: \", error);\n }\n }\n\n /**\n * 执行一次完整 CLI 流程:获取 git diff → 生成 prompt → 检查/安装 CLI → 与 Cursor 对话并打印结果。\n */\n async goCli(): Promise<string> {\n const apiKey = this.#getApiKey();\n const agentPath = this.#getAgentPath();\n const ignorePatterns = this.#getIgnorePatterns();\n\n const ensureResult = await this.ensureAgentInstalled(false, agentPath);\n\n if (!ensureResult.isInstalled) {\n throw new Error(\n \"[be-link-review] Cursor CLI 未安装且自动安装失败,请手动安装。\"\n );\n }\n\n console.log(\"[be-link-review] Getting git diff...\");\n const diff = await getGitDiff(ignorePatterns, process.cwd());\n\n if (!diff) {\n console.log(\"[be-link-review] No code changes detected\");\n return \"No code changes detected\";\n }\n\n const prompt = generateAIPrompt(diff);\n console.log(\"[be-link-review] Sending to AI...\");\n const response = await this.chat(prompt, {\n agentPath: ensureResult.actualAgentPath,\n force: true,\n });\n console.log(\"===== AI Review =====\");\n console.log(response);\n\n // 如果启用了飞书,发送到飞书\n if (this.#isFeishuEnabled()) {\n try {\n await sendReviewToFeishu(response);\n } catch (error: any) {\n console.error(\n `[be-link-review] 飞书通知发送失败,但不影响 review 结果: ${error.message}`\n );\n }\n }\n\n return response;\n }\n\n /**\n * 检查 Cursor CLI 是否已安装;未安装则自动安装(需网络)。\n * @param silent 为 true 时不打印「已安装」等提示\n * @param agentPath 可选的 agent 可执行文件路径\n */\n async ensureAgentInstalled(\n silent = false,\n agentPath?: string\n ): Promise<BeLinkReviewEnsureResult> {\n return isCheckCliInstall({ apiKey: this.#getApiKey(), silent, agentPath });\n }\n\n /**\n * 通过 Cursor Headless CLI 与 Cursor 对话(发送 prompt,拿到回复)。\n * 默认会先执行 ensureAgentInstalled(检查/安装 CLI),再启动 agent 执行提问。\n * 参考:https://cursor.com/cn/docs/cli/headless\n */\n async chat(\n prompt: string,\n options: BeLinkReviewChatOptions = {}\n ): Promise<string> {\n const actualAgentPath =\n options.agentPath || this.#getAgentPath() || \"agent\";\n const args: string[] = [\"--yolo\", \"-p\", prompt];\n if (options.outputFormat === \"json\") args.push(\"--output-format\", \"json\");\n\n return new Promise((resolve, reject) => {\n const env = { ...process.env, CURSOR_API_KEY: this.#getApiKey() };\n const proc = spawn(actualAgentPath, args, {\n env,\n cwd: process.cwd(),\n shell: false,\n stdio: ['ignore', 'pipe', 'pipe'],\n });\n\n let stdout = \"\";\n let stderr = \"\";\n\n proc.stdout?.on(\"data\", (chunk) => {\n stdout += chunk.toString();\n });\n proc.stderr?.on(\"data\", (chunk) => {\n stderr += chunk.toString();\n });\n\n proc.on(\"error\", (err) => {\n reject(\n new Error(\n `[be-link-review] 无法启动 Cursor CLI (${actualAgentPath}),请先安装:curl https://cursor.com/install -fsS | bash。原始错误: ${err.message}`\n )\n );\n });\n\n proc.on(\"close\", (code) => {\n if (code !== 0) {\n reject(\n new Error(\n `[be-link-review] agent 退出码 ${code}${\n stderr ? `: ${stderr.trim()}` : \"\"\n }`\n )\n );\n return;\n }\n resolve(stdout.trim());\n });\n });\n }\n}\n","import { spawn, exec } from \"node:child_process\";\nimport { promisify } from \"node:util\";\nimport { existsSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { BeLinkReviewEnsureResult } from \"@/types\";\n\nconst execAsync = promisify(exec);\n\ninterface CheckCliInstallOptions {\n apiKey: string;\n silent?: boolean;\n agentPath?: string; // 新增:允许用户指定 agent 可执行文件路径\n}\n\ninterface CheckCliInstallResult {\n isInstalled: boolean;\n message: string;\n actualAgentPath?: string; // 实际找到的 agent 路径\n}\n\n// 常见的 Cursor CLI 安装路径\nconst COMMON_AGENT_PATHS = [\n join(homedir(), \".cursor\", \"agent\"),\n \"/usr/local/bin/agent\", // macOS Homebrew 或手动安装的常见路径\n \"/opt/homebrew/bin/agent\", // macOS Apple Silicon Homebrew 路径\n];\n\nasync function findAgentExecutable(\n userAgentPath?: string\n): Promise<string | null> {\n // 1. 优先使用用户指定的路径\n if (userAgentPath && existsSync(userAgentPath)) {\n return userAgentPath;\n }\n\n // 2. 尝试通过 which 命令在 PATH 中查找\n try {\n const { stdout } = await execAsync(\"which agent\");\n const pathFromWhich = stdout.trim();\n if (pathFromWhich && existsSync(pathFromWhich)) {\n return pathFromWhich;\n }\n } catch (error) {\n // ignore error, continue to next method\n }\n\n // 3. 检查常见安装路径\n for (const path of COMMON_AGENT_PATHS) {\n if (existsSync(path)) {\n return path;\n }\n }\n\n return null;\n}\n\nexport async function isCheckCliInstall(\n options: CheckCliInstallOptions\n): Promise<BeLinkReviewEnsureResult> {\n const { silent = false, agentPath: userAgentPath } = options;\n\n let actualAgentPath = await findAgentExecutable(userAgentPath);\n\n if (actualAgentPath) {\n if (!silent) {\n console.log(\n `[be-link-review] Cursor CLI (agent) 已在 ${actualAgentPath} 找到。`\n );\n }\n return { isInstalled: true, message: \"Cursor CLI 已安装\", actualAgentPath };\n }\n\n if (!silent) {\n console.log(\"[be-link-review] Cursor CLI (agent) 未找到,正在尝试安装...\");\n console.log(\n \"[be-link-review] 执行安装命令: curl https://cursor.com/install -fsS | bash\"\n );\n }\n\n return new Promise((resolve, reject) => {\n const installProcess = spawn(\n \"bash\",\n [\"-c\", \"curl https://cursor.com/install -fsS | bash\"],\n {\n stdio: \"inherit\", // 将安装过程的输出直接显示给用户\n }\n );\n\n installProcess.on(\"close\", async (code) => {\n if (code === 0) {\n // 安装成功后再次检查 agent 命令是否可用\n actualAgentPath = await findAgentExecutable(userAgentPath);\n if (actualAgentPath) {\n if (!silent) {\n console.log(\"[be-link-review] Cursor CLI 安装成功。\");\n }\n resolve({\n isInstalled: true,\n message: \"Cursor CLI 安装成功\",\n actualAgentPath,\n });\n } else {\n reject(\n new Error(\n `[be-link-review] Cursor CLI 安装命令执行成功,但未找到 agent 可执行文件。请手动检查安装:curl https://cursor.com/install -fsS | bash。`\n )\n );\n }\n } else {\n reject(\n new Error(\n `[be-link-review] Cursor CLI 安装失败,退出码 ${code}。请手动安装:curl https://cursor.com/install -fsS | bash。`\n )\n );\n }\n });\n\n installProcess.on(\"error\", (err) => {\n reject(\n new Error(\n `[be-link-review] 无法启动安装进程:${err.message}。请手动安装:curl https://cursor.com/install -fsS | bash`\n )\n );\n });\n });\n}\n","import { exec } from \"node:child_process\";\nimport { promisify } from \"node:util\";\n\nconst execAsync = promisify(exec);\n\n// 固定的忽略文件模式,这些文件将永远不会被审查\nconst FIXED_IGNORE_PATTERNS = [];\n\nexport async function getGitDiff(\n userIgnorePatterns: string[] = [],\n cwd: string = process.cwd()\n): Promise<string> {\n // 检查是否在 git 仓库中\n try {\n await execAsync(\"git rev-parse --git-dir\", { cwd });\n } catch (error) {\n console.error(`[be-link-review] 当前目录不是 git 仓库: ${cwd}`);\n return \"\";\n }\n\n // 合并固定忽略模式和用户提供的忽略模式\n const allIgnorePatterns = [...new Set([...userIgnorePatterns])];\n const excludeArgs = allIgnorePatterns\n .map((pattern) => `:(exclude)${pattern}`)\n .join(\" \");\n\n let diff = \"\";\n const baseCommand = `git diff --no-color --relative ${excludeArgs}`;\n\n try {\n // 优先使用 git diff --cached 获取暂存区的改动\n const { stdout: cachedDiff } = await execAsync(`${baseCommand} --cached`, {\n cwd,\n });\n diff = cachedDiff.trim();\n if (diff) {\n console.log(\"[be-link-review] 检测到暂存区改动\");\n }\n } catch (error: any) {\n console.warn(`[be-link-review] 获取暂存区 diff 失败: ${error.message}`);\n }\n\n if (!diff) {\n try {\n // 如果暂存区没有改动,则获取工作区和 HEAD 的改动\n const { stdout: headDiff } = await execAsync(`${baseCommand} HEAD`, {\n cwd,\n });\n diff = headDiff.trim();\n if (diff) {\n console.log(\"[be-link-review] 检测到工作区改动(相对于 HEAD)\");\n }\n } catch (error: any) {\n console.warn(`[be-link-review] 获取工作区 diff 失败: ${error.message}`);\n }\n }\n\n if (!diff) {\n console.log(\"[be-link-review] 未检测到代码改动(已检查暂存区和工作区)\");\n }\n\n return diff;\n}\n","\nexport function generateAIPrompt(diff: string): string {\n return `你是一名资深软件工程师,请 review 以下代码变更。\nGit diff:\n${diff}\n请分析:\n是否存在 bug\n是否存在潜在逻辑问题\n是否存在性能问题\n是否存在代码风格问题\n给出优化建议`;\n}\n","import * as lark from \"@larksuiteoapi/node-sdk\";\nimport {\n appId,\n appSecret,\n receiveId,\n receiveIdType,\n messageType,\n messageTitle,\n} from \"../constants\";\n\n/**\n * 发送 Code Review 结果到飞书\n * 使用飞书官方 Node.js SDK,所有配置从 constants.ts 读取\n */\nexport async function sendReviewToFeishu(reviewContent: string): Promise<void> {\n console.log(\"[be-link-review] 正在发送消息到飞书...\");\n console.log(`[be-link-review] 消息类型: ${messageType}`);\n\n try {\n // 初始化飞书客户端\n const client = new lark.Client({\n appId,\n appSecret,\n domain: lark.Domain.Feishu,\n });\n\n // 根据消息类型构造消息内容\n let msgContent: string;\n let msgType: string;\n\n if (messageType === \"interactive\") {\n // Interactive 卡片消息(支持 Markdown 渲染)\n msgContent = JSON.stringify({\n config: {\n wide_screen_mode: true,\n },\n header: {\n title: {\n tag: \"plain_text\",\n content: messageTitle,\n },\n template: \"blue\",\n },\n elements: [\n {\n tag: \"div\",\n text: {\n tag: \"lark_md\",\n content: reviewContent,\n },\n },\n {\n tag: \"hr\",\n },\n {\n tag: \"note\",\n elements: [\n {\n tag: \"plain_text\",\n content: `生成时间: ${new Date().toLocaleString(\"zh-CN\", {\n timeZone: \"Asia/Shanghai\",\n })}`,\n },\n ],\n },\n ],\n });\n msgType = \"interactive\";\n } else if (messageType === \"post\") {\n // Post 富文本消息\n msgContent = JSON.stringify({\n zh_cn: {\n title: messageTitle,\n content: convertMarkdownToFeishuPost(reviewContent),\n },\n });\n msgType = \"post\";\n } else if (messageType === \"text\") {\n // Text 纯文本消息\n msgContent = JSON.stringify({\n text: `${messageTitle}\\n\\n${reviewContent}`,\n });\n msgType = \"text\";\n } else {\n throw new Error(`[be-link-review] 不支持的消息类型: ${messageType}`);\n }\n\n // 调试日志\n console.log(`[be-link-review] 发送参数:`);\n console.log(` - receive_id_type: ${receiveIdType}`);\n console.log(` - receive_id: ${receiveId}`);\n console.log(` - msg_type: ${msgType}`);\n\n // 调用发送消息接口\n const response = await client.im.message.create({\n params: {\n receive_id_type: receiveIdType,\n },\n data: {\n receive_id: receiveId,\n msg_type: msgType,\n content: msgContent,\n },\n });\n\n if (response.code !== 0) {\n throw new Error(\n `[be-link-review] 飞书 API 返回错误: ${response.msg || \"未知错误\"}`\n );\n }\n\n console.log(\"[be-link-review] ✅ 飞书消息发送成功\");\n console.log(`[be-link-review] 消息 ID: ${response.data?.message_id || \"未知\"}`);\n } catch (error: any) {\n console.error(`[be-link-review] ❌ 飞书消息发送失败: ${error.message}`);\n throw error;\n }\n}\n\n/**\n * 将 Markdown 格式转换为飞书 post 格式\n * 飞书 post 格式支持富文本样式\n */\nfunction convertMarkdownToFeishuPost(markdown: string): any[][] {\n const lines = markdown.split(\"\\n\");\n const result: any[][] = [];\n\n let inCodeBlock = false;\n let codeBlockContent: string[] = [];\n\n for (const line of lines) {\n // 处理代码块\n if (line.startsWith(\"```\")) {\n if (inCodeBlock) {\n // 代码块结束\n if (codeBlockContent.length > 0) {\n result.push([\n {\n tag: \"text\",\n text: codeBlockContent.join(\"\\n\"),\n style: [\"code\"],\n },\n ]);\n codeBlockContent = [];\n }\n inCodeBlock = false;\n } else {\n // 代码块开始\n inCodeBlock = true;\n }\n continue;\n }\n\n if (inCodeBlock) {\n codeBlockContent.push(line);\n continue;\n }\n\n // 空行\n if (!line.trim()) {\n result.push([{ tag: \"text\", text: \"\" }]);\n continue;\n }\n\n // 标题(加粗 + 加大)\n if (line.startsWith(\"#\")) {\n const level = line.match(/^#+/)?.[0].length || 1;\n const text = line.replace(/^#+\\s*/, \"\");\n result.push([\n {\n tag: \"text\",\n text: text,\n style: level <= 2 ? [\"bold\", \"underline\"] : [\"bold\"],\n },\n ]);\n continue;\n }\n\n // 解析行内样式(加粗、链接等)\n const parsedLine = parseLineStyles(line);\n result.push(parsedLine);\n }\n\n // 如果还在代码块中,添加剩余内容\n if (codeBlockContent.length > 0) {\n result.push([\n {\n tag: \"text\",\n text: codeBlockContent.join(\"\\n\"),\n style: [\"code\"],\n },\n ]);\n }\n\n return result;\n}\n\n/**\n * 解析行内样式(加粗、链接、代码等)\n */\nfunction parseLineStyles(line: string): any[] {\n const elements: any[] = [];\n let currentText = \"\";\n let i = 0;\n\n while (i < line.length) {\n // 处理加粗 **text**\n if (line[i] === \"*\" && line[i + 1] === \"*\") {\n if (currentText) {\n elements.push({ tag: \"text\", text: currentText });\n currentText = \"\";\n }\n const endIndex = line.indexOf(\"**\", i + 2);\n if (endIndex !== -1) {\n const boldText = line.substring(i + 2, endIndex);\n elements.push({ tag: \"text\", text: boldText, style: [\"bold\"] });\n i = endIndex + 2;\n continue;\n }\n }\n\n // 处理行内代码 `code`\n if (line[i] === \"`\" && line[i + 1] !== \"`\") {\n if (currentText) {\n elements.push({ tag: \"text\", text: currentText });\n currentText = \"\";\n }\n const endIndex = line.indexOf(\"`\", i + 1);\n if (endIndex !== -1) {\n const codeText = line.substring(i + 1, endIndex);\n elements.push({\n tag: \"text\",\n text: codeText,\n style: [\"code\"],\n });\n i = endIndex + 1;\n continue;\n }\n }\n\n // 处理链接 [text](url)\n if (line[i] === \"[\") {\n const textEnd = line.indexOf(\"](\", i);\n const urlEnd = line.indexOf(\")\", textEnd + 2);\n if (textEnd !== -1 && urlEnd !== -1) {\n if (currentText) {\n elements.push({ tag: \"text\", text: currentText });\n currentText = \"\";\n }\n const linkText = line.substring(i + 1, textEnd);\n const url = line.substring(textEnd + 2, urlEnd);\n elements.push({\n tag: \"a\",\n text: linkText,\n href: url,\n });\n i = urlEnd + 1;\n continue;\n }\n }\n\n currentText += line[i];\n i++;\n }\n\n if (currentText) {\n elements.push({ tag: \"text\", text: currentText });\n }\n\n return elements.length > 0 ? elements : [{ tag: \"text\", text: line }];\n}\n","// 飞书机器人配置(内置,不需要外部配置)\nexport const appId = \"cli_a93822da7238dbb5\";\nexport const appSecret = \"ZQdcpLUHFb4gFa8cGfrlJfVfSSyGtyzF\";\nexport const receiveId = \"oc_482b6a04f95f4206c4fa9bc61829fd17\";\nexport const receiveIdType = \"chat_id\";\nexport const messageType = \"post\"; // text | post | interactive\nexport const messageTitle = \"🔍 Code Review 结果\";\n"],"mappings":"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","names":["import_node_child_process","import_node_fs","import_node_path","import_node_child_process","import_node_util","execAsync","execAsync"]}
|