/** * 「这个模块是不是被直接执行的入口?」——**必须比真实路径**。 * * # 为什么不能直接比 `import.meta.url === 'file://' + process.argv[1]` * * ESM 的 `import.meta.url` 已经是**解析过软链的真实路径**,而 `process.argv[1]` * 是命令行里写的那个(可能是软链)。两者在软链下不相等,于是入口判断为假、 * `main()` 从不执行 —— 没有输出、没有报错、**退出码 0**。 * * 这不是假设:生产部署的布局就是软链(`/opt/agentmail/plugins//current` * → 某个时间戳目录),第一次从快照起 MCP 服务器时正是这样「握手 0 个工具、 * stderr 一个字都没有」。而同一个文件从仓库路径跑是正常的 —— * 因为仓库路径没有软链。 * * 这类缺陷的特点是**只在部署形态下出现**,本地怎么试都是对的; * 而它的表现(静默成功)与「功能没被调用」完全一样。 * * # 为什么两边都要 realpath * * 只解析一侧仍会在「argv 是软链、真身是另一个软链」这类组合下失配。 * 两侧都归一到真实路径,判断才是「同一个文件」这个语义本身。 */ import { realpathSync } from 'node:fs'; import { fileURLToPath } from 'node:url'; /** * @param {string} metaUrl 调用方传 `import.meta.url` * @param {string} [argv1] 默认 `process.argv[1]` * @returns {boolean} */ export function isMainModule(metaUrl, argv1 = process.argv[1]) { if (!metaUrl || !argv1) return false; try { return realpathSync(fileURLToPath(metaUrl)) === realpathSync(argv1); } catch { // 文件不存在 / 权限不足:**当作不是**入口(保守)。 // 判错的代价:要么该跑的没跑(静默),要么被 import 时误跑一遍。 // 后者会带来副作用(起服务、改状态),更危险。 return false; } }