Files
geekgeekrun/plan/recruiter_debug_tool.md
rqi14 95c1e54c66 recruiter: add boss auto browse/chat flows, webhook, and candidate tables
- Add recruiter-side automation core and run-core entry
- Extend sqlite-plugin with candidate info + contact logs
- Add UI routes/pages, IPC handlers, progress + log panel
- Document current status and plans under plan/

Made-with: Cursor
2026-03-18 17:37:24 +08:00

215 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 招聘端调试工具
> **定位**:用于在沟通页手动调试简历相关操作(在线简历、附件简历、下载 PDF 等),以及 LLM 简历筛选Rubric 评估、Rubric 生成)。与正式运行的 `bossChatPageMain` 使用完全一致的技术栈Puppeteer + ghost-cursor + Canvas hook
> 最后更新2026-03-18
---
## 1. 概述
招聘端调试工具是一套**独立于自动化主流程**的调试环境,可单独启动浏览器到 BOSS 沟通页,然后通过 GUI 按钮逐条执行调试命令,验证:
- 在线简历的打开、关闭、Canvas hook 提取
- 附件简历的请求、同意、预览与下载
- 各类弹窗的关闭(意向沟通、在线简历等)
**与正式运行的一致性**:所有页面操作均通过 `createHumanCursor`ghost-cursor拟人轨迹点击`chat-page-processor.mjs` / `chat-page-resume.mjs` 的实现完全一致,便于在无自动化干扰下排查 DOM 选择器、时序问题。
---
## 2. 架构
```
┌─────────────────────────────────────────────────────────────────────┐
│ Renderer: BossDebugTool/index.vue │
│ - 启动浏览器 / 关闭浏览器 按钮 │
│ - Tab A「简历操作」9 个调试命令按钮(获取姓名、在线简历、附件简历等) │
│ - Tab B「LLM 筛选」:提取简历文本 / 运行 Rubric / 生成 Rubric 按钮 │
│ - 统一操作日志区域 │
└─────────────────────────────────────────────────────────────────────┘
│ IPC: open-boss-chat-debug / boss-debug-command / close-boss-chat-debug
┌─────────────────────────────────────────────────────────────────────┐
│ Main: ipc/index.ts │
│ - 管理 bossChatDebugProcess子进程
│ - 通过 stdio fd3/fd4 与 worker 通信JSON 行协议) │
└─────────────────────────────────────────────────────────────────────┘
│ spawn(..., --mode=bossChatDebugMain, stdio[3,4]=pipe)
┌─────────────────────────────────────────────────────────────────────┐
│ Worker: flow/BOSS_CHAT_DEBUG_MAIN/index.ts │
│ - Electron 子进程app.dock?.hide()
│ - initPuppeteer + launch 非无头浏览器 │
│ - 注入 Cookie + localStorage打开 BOSS_CHAT_PAGE_URL │
│ - 监听 fd3 读取命令,执行后通过 fd4 写回响应 │
└─────────────────────────────────────────────────────────────────────┘
```
**进程路由**`src/main/index.ts` 根据 `--mode=bossChatDebugMain` 加载 `flow/BOSS_CHAT_DEBUG_MAIN/index.ts`,调用 `waitForProcessHandShakeAndRunDebug()`
---
## 3. 通信协议
### 3.1 进程间 stdio
主进程 spawn 时 `stdio: ['inherit','inherit','inherit','pipe','pipe']`
| fd | 方向 | 用途 |
|----|------|------|
| fd3 | 主进程 → 子进程 | 主进程写入命令 |
| fd4 | 子进程 → 主进程 | 子进程写入 READY/响应 |
每条消息为 **一行 JSON**,以 `\n` 结尾。
### 3.2 命令格式(主 → 子)
```json
{ "type": "ping", "id": "abc123" }
{ "type": "open-online-resume", "id": "xyz789" }
```
- `type`(必填):命令类型
- `id`(必填):由主进程生成,用于匹配响应
### 3.3 响应格式(子 → 主)
**就绪通知**(子进程启动完成后发一次):
```json
{ "type": "READY", "ok": true }
{ "type": "READY", "ok": false, "error": "NO_BROWSER" }
```
**命令响应**
```json
{ "id": "abc123", "ok": true, "result": { "name": "张三" } }
{ "id": "xyz789", "ok": false, "error": "未找到在线简历按钮" }
```
### 3.4 命令超时
主进程发命令后,若 30 秒内未收到响应,视为超时,返回 `{ ok: false, error: 'timeout' }`
---
## 4. 支持的调试命令
### 4.1 Tab A — 简历操作命令
| type | 说明 | 成功时 result |
|------|------|---------------|
| `ping` | 探活 | `'pong'` |
| `get-panel-name` | 获取右侧面板当前候选人姓名 | `{ name: string }` |
| `dismiss-intent-dialog` | 关闭「意向沟通」弹窗 | `{ found: boolean }` |
| `close-online-resume` | 关闭在线简历弹窗 | `{ found: boolean }` |
| `open-online-resume` | 打开当前会话的在线简历 | `{ opened: boolean }` |
| `check-attach-resume` | 检查当前会话是否有「点击预览附件简历」按钮 | `{ hasAttachment: boolean }` |
| `request-attach-resume` | 请求附件简历(点击按钮 + 确认弹窗) | `{ requested: boolean, ... }` |
| `download-attach-resume` | 预览并下载当前会话已有的附件简历 | `{ clickedDownload: boolean, ... }` |
| `accept-incoming-attach-resume` | 同意对方发来的附件简历请求(仅当出现「是否同意」弹窗时) | `{ found: boolean, accepted: boolean }` |
**附件简历流程说明**(与 `plan/chat_page_resume_flow.md` 一致):
- **看在线简历**`open-online-resume`,无需对方同意,点开即可。
- **下载 PDF**:需先 `request-attach-resume` → 对方同意 → PDF 作为新消息出现在聊天里 → `download-attach-resume`
- **同意请求**:若对方先发起附件简历请求,会出现「对方想发送附件简历给您,您是否同意」弹窗,用 `accept-incoming-attach-resume` 同意。
### 4.2 Tab B — LLM 筛选命令
| type | 说明 | payload | 成功时 result |
|------|------|---------|---------------|
| `extract-resume-text` | 打开当前会话的在线简历并用 Canvas hook 提取纯文本 | 无 | `{ resumeText: string, charCount: number }` |
| `llm-screen-resume` | 对指定简历文本运行 Rubric 评估(使用当前职位的 `resumeLlmConfig` | `{ resumeText: string, jobId?: string }` | `{ isPassed: boolean, totalScore: number, reason: string, rawResponse: string }` |
| `llm-generate-rubric` | 根据 JD 文本生成 Rubric 结构(不依赖浏览器,仅调 LLM API | `{ sourceJd: string }` | `{ rubric: { knockouts: string[], dimensions: [...] } }` |
**命令使用说明:**
- `extract-resume-text`在子进程Worker侧执行需要浏览器已就绪且已手动选中一条会话。内部调用 `openOnlineResume` + Canvas hook 提取文本,提取完后**关闭简历弹窗**,将文本返回给主进程。
- `llm-screen-resume`:在**主进程**侧执行(不经过子进程),直接调用 `evaluateResumeByRubric``jobId` 用于从 `boss-jobs-config.json` 载入对应的 `resumeLlmConfig`;若不传 `jobId`,则 UI 侧提供手动填写 Rubric JSON 的区域,将其序列化为 payload 传入。
- `llm-generate-rubric`:同样在**主进程**侧执行,调用 `generateRubricFromJd`,读取 `boss-llm.json``rubric_generation` 用途的模型(未配置时会回退到默认/第一个启用模型)。
---
## 5. 文件与入口
| 路径 | 说明 |
|------|------|
| `packages/ui/src/main/flow/BOSS_CHAT_DEBUG_MAIN/index.ts` | Worker 入口,启动浏览器并监听 stdio 命令 |
| `packages/ui/src/renderer/src/page/MainLayout/BossDebugTool/index.vue` | GUI 页面(含 Tab A 简历操作、Tab B LLM 筛选) |
| `packages/ui/src/main/flow/OPEN_SETTING_WINDOW/ipc/index.ts` | IPC 处理器:`open-boss-chat-debug``boss-debug-command``close-boss-chat-debug` |
| `packages/ui/src/renderer/src/router/index.ts` | 路由 `BossDebugTool` |
| `packages/ui/src/renderer/src/page/MainLayout/LeftNavBar/RecruiterPart.vue` | 左侧导航「招聘端调试工具」入口 |
**依赖的核心包**(与 `bossChatPageMain` 相同):
- `@geekgeekrun/boss-auto-browse-and-chat/index.mjs``initPuppeteer`
- `@geekgeekrun/boss-auto-browse-and-chat/chat-page-resume.mjs``openOnlineResume``requestAttachmentResume``acceptIncomingAttachResume``openPreviewAndDownloadPdf`
- `@geekgeekrun/boss-auto-browse-and-chat/resume-extractor.mjs``setupCanvasTextHook`
- `@geekgeekrun/boss-auto-browse-and-chat/constant.mjs`:选择器常量
- `@geekgeekrun/boss-auto-browse-and-chat/humanMouse.mjs``createHumanCursor`
- `@geekgeekrun/boss-auto-browse-and-chat/runtime-file-utils.mjs``readStorageFile``ensureStorageFileExist`
- `@geekgeekrun/boss-auto-browse-and-chat/llm-rubric.mjs``evaluateResumeByRubric``generateRubricFromJd`Tab B LLM 命令,**主进程侧调用**
**存储**:与正式流程共用 `~/.geekgeekrun/storage/boss-cookies.json``boss-local-storage.json`
---
## 6. 使用流程
### 6.1 Tab A — 简历操作
1. 打开设置窗口 → 左侧导航选择「招聘端调试工具」
2. 点击「启动浏览器」→ 主进程 spawn `bossChatDebugMain` 子进程,子进程启动 Puppeteer、注入 Cookie/localStorage、打开沟通页、发 READY
3. 在 BOSS 沟通页**手动选择一条会话**(左侧会话列表点击,右侧展示该候选人)
4. 点击调试按钮执行命令,如「打开在线简历」「检查附件简历」等
5. 查看操作日志和命令返回值
6. 测试完成后点击「关闭浏览器」,主进程 kill 子进程
**注意事项**
- 启动前需已配置浏览器路径(与推荐页/沟通页一致,若未配置会弹窗引导)
- 子进程退出(用户关闭浏览器)时,主进程会发送 `boss-chat-debug-exited` 到 RendererGUI 自动将状态置为「未就绪」
### 6.2 Tab B — LLM 筛选调试
Tab B 分为三个子功能区域:
**区域 1提取简历文本**
> 依赖浏览器已就绪,且已在 BOSS 沟通页手动选中一条会话。
1. 确认浏览器已就绪,沟通页已选中目标会话
2. 点击「📄 提取当前简历文本」
3. 主进程发送 `extract-resume-text` 命令到子进程,子进程打开在线简历 → Canvas hook 提取 → 关闭弹窗 → 返回文本
4. 提取到的文本显示在下方只读 Textarea可手动选中复制
5. 文本自动填入「区域 2」的输入框供后续 LLM 评估使用
**区域 2运行 Rubric 评估**
> 不依赖浏览器,直接在主进程调用 LLM API。
- **职位选择器**:下拉选择 `boss-jobs-config.json` 中已启用 `resumeLlmEnabled` 的职位,用于自动加载其 `resumeLlmConfig`
- **或**:展开「手动填写 Rubric JSON」折叠区直接粘贴 rubric 对象(`{ knockouts, dimensions, passThreshold }`
- **简历文本输入框**(来自区域 1 自动填充或手动粘贴)
- 点击「🤖 运行 LLM 评估」→ 主进程调用 `llm-screen-resume` → 返回结果展示:
- **通过 / 未通过** 状态标签
- 总分(如 `78 / 100`
- 判断理由
- 展开「原始 LLM 响应」折叠区查看 raw JSON
**区域 3生成 Rubric**
> 不依赖浏览器,直接在主进程调用 LLM API。需已配置 `boss-llm.json`。
- **JD 输入框**`el-input` textarea粘贴岗位描述
- 点击「✨ 生成 Rubric」→ 主进程调用 `llm-generate-rubric` → 将生成的 Rubric JSON 格式化展示在只读文本框
- 提供「📋 复制 JSON」按钮方便直接粘贴到 `boss-jobs-config.json` 或 BossJobConfig UI
---
## 7. 与 recruiter_architecture 的关系
招聘端调试工具**不参与** daemon/worker 调度,是主进程直接 spawn 的独立子进程,用于本地开发与问题排查。架构总览(`recruiter_architecture.md`)中未单独列出,可在此文档中查阅其设计与用法。