公开仓库只发布二进制与使用说明,BUILD.md 仅存在于源码仓库, README 里改为文字指引,避免公开页面出现失效链接。 Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
5.0 KiB
5.0 KiB
AGENTS
面向在本仓库工作的 AI 代理。约定之外的部分按代码里的既有写法照做。
项目性质
Electron 桌面应用:多源文献检索 + 本地书库 + 内置阅读器(PDF/EPUB/MOBI/AZW)+ 批注笔记 + AI 助手。
Windows x64 免安装版,用户数据在程序同级 data/。
语言与风格
- 界面文案、提交信息、注释一律中文;标识符英文。
- 默认不写注释。只在原因不显然时写:隐藏约束、易踩的坑、绕过某个具体 bug 的原因。不要复述代码在做什么。
- 不用 emoji。散文里避免破折号。
- 回复简洁,不主动扩展用户没要求的事。
硬性约束
安全边界不可绕过
- 渲染层永远不能传任意路径读盘。所有文件访问必须过
main.js的resolveReadable(),它只放行书库中真实登记的条目。 - 分段读取会话(
src/reader/range-sessions.js)与 sender 绑定,句柄不透明,webContents 销毁即回收。新增 IPC 时必须校验 sender。 - 所有
ipcMain.handle走wrap(),同步抛出也要变成{ ok:false },否则渲染层的await无 catch,界面会永远卡在加载中。 - 不要把密钥、token 写进日志或错误信息。AI Key 经
safeStorage加密后落盘。
依赖
- 前端第三方库全部 vendored 在
src/ui/vendor/,版本在package.json中锁死(不用^)。不要引入新的运行时依赖,除非用户明确要求。 src/ui/vendor/pdf.worker.range.mjs是手工 patch 过的 PDF.js worker,不要用上游文件覆盖。见下文。
PDF 分段读取(易踩坑)
超大 PDF 不整文件读入内存,走 reader:rangeOpen/rangeRead/rangeClose。reader:bytes 直接拒绝 PDF。
worker 选择策略在 pdf-adapter.mjs:
- ≤256 MB:用官方 worker(
pdf.worker.min.mjs),即使是 range 模式。 -
256 MB:用稀疏 worker(
pdf.worker.range.mjs)。
稀疏 worker 的基础缓冲区是空的(new Uint8Array(0)),因此任何对 stream.bytes.buffer 直接建视图的代码都会抛 RangeError。已知踩过的坑:preEvaluateFont 里的 ToUnicode 哈希,错误表现是字体静默降级成不可见的 ErrorFont(文本项数量正常,但画布上没有墨迹)。必须用 stream.getByteRange(start, end)。
改动这个 worker 后,用真实 PDF 对比三条路径的渲染结果(文本项数 + 非白像素数):官方 worker 全量数据 / 官方 worker range / 稀疏 worker range。三者应一致。
AI 助手
- 上下文范围:
selection | page | document | page-image | region-image。 - 只有
selection需要选中文本;page和document不依赖选区。 document无论多短都强制弹确认框,并提示可能超出模型上下文限制。- 正文在
ai-client.js按MAX_CHARS截断,保留首尾(结论常在末尾,只留开头会让模型答非所问)。 - 图像只用 JPEG 单一编码路径,1600px / 目标 400 KB。不要加格式回退(PNG 等),维护成本高于收益;视觉模型按像素图块计费,格式不影响费用。
- 三种协议:Anthropic
/messages、OpenAI Responses/responses、兼容 Chat/chat/completions。图像负载格式各不相同,改动时三条都要验。
测试
npm test # Node 单测
npx electron src/_test/electron/<name>.integration.js # Electron 集成
集成套件:ai-scope、reader-features、library-notes、annotation、download、cover、startup。
要求:
- 完成任务前跑单测 + 相关集成套件。
- 单测里有对源码的正则断言(锁死关键约定)。改了被断言的代码要同步更新断言,不要为了让测试过而弱化断言。
- 集成测试断言"真正离开进程的内容"(真实本地 HTTP 服务收到的 body、真实渲染出的像素),不要 stub 渲染层。
- 不要为了测试往生产代码里加
window.__test之类的全局钩子,通过真实 UI 断言。 library-notes偶发失败,重跑确认再判断。
构建
npm run build # 输出 dist/PeopleLib-windows-x64/
- 输出目录固定,不带版本号。改名会导致
data/被遗留在旧目录。 - 构建保留
data/,但会清空其余内容。构建前必须退出该目录下运行中的PeopleLib.exe,否则清理到一半失败,目录处于不完整状态。 - 涉及
data/的操作前后做逐文件哈希比对,确认书库、笔记、批注未被改动。
仓库
两个远端,用途不同:
github(公开):只放 README 与截图,不推源码、不推BUILD.md。历史与本地无共同祖先,用独立的 orphan/docs 提交推送。origin(私有):完整源码。
其他:
dist/已 gitignore。诊断产物(*-diagnostic.png、probe*.json)也已忽略,不要提交。- 未跟踪文件视为用户资产,不要删除或覆盖。清理前先看
git status --porcelain。 - 提交前
git diff --cached检查是否混入密钥。