@viyzhu/boss-cli-fork 0.7.3 → 0.8.1

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.
Files changed (40) hide show
  1. package/AGENTS.md +119 -85
  2. package/CHANGELOG.md +57 -0
  3. package/LICENSE +674 -674
  4. package/README.md +346 -284
  5. package/dist/browser/cdp_browser.d.ts +170 -170
  6. package/dist/browser/cdp_browser.js +674 -674
  7. package/dist/cli/cliRouter.d.ts.map +1 -1
  8. package/dist/cli/cliRouter.js +119 -67
  9. package/dist/cli/cliRouter.js.map +1 -1
  10. package/dist/common/auth.js +49 -49
  11. package/dist/common/boss_modal.js +42 -42
  12. package/dist/common/boss_page_guards.js +247 -247
  13. package/dist/common/boss_paywall_popup.js +87 -87
  14. package/dist/common/boss_session_page.js +14 -14
  15. package/dist/common/boss_sidebar_nav.d.ts.map +1 -1
  16. package/dist/common/boss_sidebar_nav.js +38 -29
  17. package/dist/common/boss_sidebar_nav.js.map +1 -1
  18. package/dist/common/c_resume_capture.js +61 -61
  19. package/dist/toolset/action.d.ts.map +1 -1
  20. package/dist/toolset/action.js +238 -233
  21. package/dist/toolset/action.js.map +1 -1
  22. package/dist/toolset/chat.js +437 -437
  23. package/dist/toolset/deep-search.js +574 -572
  24. package/dist/toolset/deep-search.js.map +1 -1
  25. package/dist/toolset/index.d.ts +4 -1
  26. package/dist/toolset/index.d.ts.map +1 -1
  27. package/dist/toolset/index.js +3 -2
  28. package/dist/toolset/index.js.map +1 -1
  29. package/dist/toolset/jd.js +132 -132
  30. package/dist/toolset/list.js +48 -48
  31. package/dist/toolset/normal-search.d.ts +167 -1
  32. package/dist/toolset/normal-search.d.ts.map +1 -1
  33. package/dist/toolset/normal-search.js +1276 -165
  34. package/dist/toolset/normal-search.js.map +1 -1
  35. package/dist/toolset/recommend.js +211 -209
  36. package/dist/toolset/recommend.js.map +1 -1
  37. package/package.json +70 -69
  38. package/skills/boss-frontend-analysis/SKILL.md +58 -58
  39. package/skills/boss-frontend-analysis/agents/openai.yaml +4 -4
  40. package/skills/boss-frontend-analysis/scripts/capture_boss_frontend.mjs +604 -604
package/AGENTS.md CHANGED
@@ -1,85 +1,119 @@
1
- # 项目协作规则
2
-
3
- ## 基本原则
4
-
5
- - 禁止添加任何回退逻辑(fallback)。
6
- - 禁止添加掩盖根因的“胶水代码”。
7
- - 默认采用单一路径、可预测行为;未经明确要求,不引入隐式分支。
8
-
9
- ## 失败处理
10
-
11
- - 失败应直接暴露,不做静默兜底。
12
- - 错误信息必须清晰、可定位,日志应包含关键上下文。
13
- - 发现问题优先修复根因,不通过绕路方案规避。
14
-
15
- ### 已登记的例外(只有这一处,别再扩)
16
-
17
- **`cdp_browser.ts` 的 `warnBreakawayUnavailable()`:WMI 拉不起浏览器时,刷屏级告警后退回普通
18
- `spawn`。** 这是上面「禁止回退逻辑 / 不做静默兜底」的一处**有意例外**,删它之前先读完这段。
19
-
20
- - **禁的是「静默」**。这里的告警是 72 字符分隔线的整块输出,含原因、影响、自查命令、缓解办法,
21
- 用户不可能看不见,不属于「掩盖根因」。
22
- - **硬失败比退回更糟**——这是**设计论证,不依赖任何一台机器的观测**:`spawnViaWmi` 一旦硬失败,
23
- `search` / `recommend` / `list` 全部不可用,用户唯一的出路是自己翻到 `BOSS_SPAWN_BREAKAWAY=false`;
24
- 而那个开关 = 根本不试 WMI = 必然退回普通 spawn = 把 #43 原样装回去,**还绕过了本该提醒他的告警**。
25
- 即:硬失败把用户推向一个比退回更坏、且更难察觉的状态。
26
- 权衡:退回 = 浏览器可能被连带杀掉(可恢复,重扫一次码,且有告警);硬失败 = CLI 完全不能用
27
- (不可恢复,除非用户自己翻到那个环境变量,然后掉进更坏的状态)。
28
- - **退回的边界很窄**:只覆盖「WMI 创建进程」这一步。进程已创建但调试端口没起来仍然硬失败——
29
- 那时端口上可能已有一只正在启动的 Chrome,再 spawn 一只会撞车。
30
- - **回归保护**:本路径在 WMI 正常的机器上**跑不到**,所以靠 stub 测(把 powershell 换成必定失败的
31
- 可执行文件),见 `tests/breakaway-fallback.test.mjs`。别指望真实环境验收能覆盖它。
32
-
33
- > **史料更正(2026-09-21)**:本节最初写的立论依据是 recruiting-copilot#43 报告人「那台机器
34
- > `Invoke-CimMethod Win32_Process Create` 返回 `ReturnValue=2`」。**该观测已被报告人当日撤回**——
35
- > 那是他独立探测脚本的行为,不是 boss 实际调用路径的行为;boss 自己调用 WMI 在他那台是通的
36
- > (Chrome 父进程 `WmiPrvSE.exe`,活过调用边界,登录态保住)。他上午观测到的「Chrome 每次被杀」
37
- > 也有一半来自他为绕开硬失败而设的 `BOSS_SPAWN_BREAKAWAY=false`。
38
- > **例外本身保留**:上面那条权衡不依赖这个观测,换任何 WMI 创建被拒的环境都成立。
39
- > 留这段是因为——引用一条已撤回的事实,会让整条例外在下一个人核对时失去可信度。
40
-
41
- 新增别的回退前,先确认它同时满足「告警足够响」「硬失败的代价明显更大」「退回边界能说清楚」
42
- 三条,并登记到本节;说不清就别加。
43
-
44
- ## 变更约束
45
-
46
- - 小步修改,保持最小必要改动。
47
- - 不在未被要求的范围内扩散改动。
48
- - 规则优先级:用户明确要求 > 本文件约束。
49
-
50
- ## 文档索引
51
-
52
- - 页面 URL、命令功能和当前位置要求记录在 `docs/boss-url-map.md`。
53
- - 修改导航、命令入口、当前位置校验或 help 文案前,先查阅并同步更新该文档。
54
-
55
- ## 浏览器默认无头(重要)
56
-
57
- 浏览器**默认以无头方式启动**,看不见窗口。有头窗口一启动就抢键盘焦点,会打断用户正在做的事,所以默认隐藏。
58
-
59
- 开关优先级(`resolveHeadlessFromEnv()`,`src/browser/cdp_browser.ts`):
60
-
61
- 1. `BOSS_BROWSER_HEADLESS` —— 本 CLI 专属,显式覆盖,认 `true/1/yes/y` 与 `false/0/no/n`
62
- 2. `RECRUIT_BROWSER_HIDDEN` —— 招聘工具链共读的单一来源(boss-cli / liepin-cli / DSH 面板都认),设 `false` 退回有头
63
- 3. 都没设 → **无头**
64
-
65
- **要让浏览器可见时**(用户说"我看不到浏览器"、"让我看看它在干什么"、需要人工介入页面):
66
-
67
- ```bash
68
- RECRUIT_BROWSER_HIDDEN=false boss <cmd> # 或 BOSS_BROWSER_HEADLESS=false
69
- ```
70
-
71
- 已经有一只无头实例在跑时,换了变量也**不会**自动变可见 —— 端口上已有实例会被直接复用。先 `boss shutdown` 关掉那只,下条命令才会按新模式重启。
72
-
73
- 浏览器**跨命令常驻**(一次性命令结束只 detach CDP,不关窗口),`boss shutdown` 是唯一的显式退出口。别在命令路径里加关浏览器的逻辑。名字不叫 `quit` 是因为交互模式里 `exit` / `quit` 已经是退出 REPL 的别名。
74
-
75
- **判断在跑的实例是什么模式**:读 `http://127.0.0.1:53470/json/version` 的 `User-Agent`,含 `HeadlessChrome` 即无头(`probeRemoteHeadless()`)。**不要**用进程内变量判断 —— 一次性命令刚起进程时那些变量都是空的,`login.ts` 曾因此把登录页开在看不见的浏览器里。
76
-
77
- `login` 是例外:扫码必须可见,它会自己探测并把无头实例关掉重启为有头。登录态在 `~/.boss-cli/.cache/` 的 user-data-dir 里,重启不丢。
78
-
79
- 无头下额外带 `--screen-info={0,0 1920x1080 workAreaBottom=40}`:无头虚拟屏默认 800x600 是已知的强自动化指纹,而 `--window-size` 抬不动它,只有 `--screen-info` 能(Chrome 142+,仅无头有效)。**四个 workArea 参数必须分开写**(`workAreaTop/Bottom/Left/Right`),写成 `workArea=` 会让 Chrome 直接启动失败。
80
-
81
- ## Puppeteer evaluate 约束(重要)
82
-
83
- - 在工具代码中,避免使用 `page.evaluate(() => { ... })` / `page.waitForFunction(() => { ... })` 的函数写法。
84
- - 统一改为字符串脚本写法(如 `page.evaluate("(() => { ... })()")`),避免构建后注入辅助符号导致浏览器上下文报错 `__name is not defined`。
85
- - 出现 `__name is not defined` 时,优先检查最近新增的 evaluate / waitForFunction 回调并改成字符串脚本,不要加兜底掩盖问题。
1
+ # 项目协作规则
2
+
3
+ ## 基本原则
4
+
5
+ - 禁止添加任何回退逻辑(fallback)。
6
+ - 禁止添加掩盖根因的“胶水代码”。
7
+ - 默认采用单一路径、可预测行为;未经明确要求,不引入隐式分支。
8
+
9
+ ## 失败处理
10
+
11
+ - 失败应直接暴露,不做静默兜底。
12
+ - 错误信息必须清晰、可定位,日志应包含关键上下文。
13
+ - 发现问题优先修复根因,不通过绕路方案规避。
14
+
15
+ ### 已登记的例外(只有这一处,别再扩)
16
+
17
+ **`cdp_browser.ts` 的 `warnBreakawayUnavailable()`:WMI 拉不起浏览器时,刷屏级告警后退回普通
18
+ `spawn`。** 这是上面「禁止回退逻辑 / 不做静默兜底」的一处**有意例外**,删它之前先读完这段。
19
+
20
+ - **禁的是「静默」**。这里的告警是 72 字符分隔线的整块输出,含原因、影响、自查命令、缓解办法,
21
+ 用户不可能看不见,不属于「掩盖根因」。
22
+ - **硬失败比退回更糟**——这是**设计论证,不依赖任何一台机器的观测**:`spawnViaWmi` 一旦硬失败,
23
+ `search` / `recommend` / `list` 全部不可用,用户唯一的出路是自己翻到 `BOSS_SPAWN_BREAKAWAY=false`;
24
+ 而那个开关 = 根本不试 WMI = 必然退回普通 spawn = 把 #43 原样装回去,**还绕过了本该提醒他的告警**。
25
+ 即:硬失败把用户推向一个比退回更坏、且更难察觉的状态。
26
+ 权衡:退回 = 浏览器可能被连带杀掉(可恢复,重扫一次码,且有告警);硬失败 = CLI 完全不能用
27
+ (不可恢复,除非用户自己翻到那个环境变量,然后掉进更坏的状态)。
28
+ - **退回的边界很窄**:只覆盖「WMI 创建进程」这一步。进程已创建但调试端口没起来仍然硬失败——
29
+ 那时端口上可能已有一只正在启动的 Chrome,再 spawn 一只会撞车。
30
+ - **回归保护**:本路径在 WMI 正常的机器上**跑不到**,所以靠 stub 测(把 powershell 换成必定失败的
31
+ 可执行文件),见 `tests/breakaway-fallback.test.mjs`。别指望真实环境验收能覆盖它。
32
+
33
+ > **史料更正(2026-09-21)**:本节最初写的立论依据是 recruiting-copilot#43 报告人「那台机器
34
+ > `Invoke-CimMethod Win32_Process Create` 返回 `ReturnValue=2`」。**该观测已被报告人当日撤回**——
35
+ > 那是他独立探测脚本的行为,不是 boss 实际调用路径的行为;boss 自己调用 WMI 在他那台是通的
36
+ > (Chrome 父进程 `WmiPrvSE.exe`,活过调用边界,登录态保住)。他上午观测到的「Chrome 每次被杀」
37
+ > 也有一半来自他为绕开硬失败而设的 `BOSS_SPAWN_BREAKAWAY=false`。
38
+ > **例外本身保留**:上面那条权衡不依赖这个观测,换任何 WMI 创建被拒的环境都成立。
39
+ > 留这段是因为——引用一条已撤回的事实,会让整条例外在下一个人核对时失去可信度。
40
+
41
+ 新增别的回退前,先确认它同时满足「告警足够响」「硬失败的代价明显更大」「退回边界能说清楚」
42
+ 三条,并登记到本节;说不清就别加。
43
+
44
+ ## 变更约束
45
+
46
+ - 小步修改,保持最小必要改动。
47
+ - 不在未被要求的范围内扩散改动。
48
+ - 规则优先级:用户明确要求 > 本文件约束。
49
+
50
+ ## 文档索引
51
+
52
+ - 页面 URL、命令功能和当前位置要求记录在 `docs/boss-url-map.md`。
53
+ - 修改导航、命令入口、当前位置校验或 help 文案前,先查阅并同步更新该文档。
54
+
55
+ ## 浏览器默认无头(重要)
56
+
57
+ 浏览器**默认以无头方式启动**,看不见窗口。有头窗口一启动就抢键盘焦点,会打断用户正在做的事,所以默认隐藏。
58
+
59
+ 开关优先级(`resolveHeadlessFromEnv()`,`src/browser/cdp_browser.ts`):
60
+
61
+ 1. `BOSS_BROWSER_HEADLESS` —— 本 CLI 专属,显式覆盖,认 `true/1/yes/y` 与 `false/0/no/n`
62
+ 2. `RECRUIT_BROWSER_HIDDEN` —— 招聘工具链共读的单一来源(boss-cli / liepin-cli / DSH 面板都认),设 `false` 退回有头
63
+ 3. 都没设 → **无头**
64
+
65
+ **要让浏览器可见时**(用户说"我看不到浏览器"、"让我看看它在干什么"、需要人工介入页面):
66
+
67
+ ```bash
68
+ RECRUIT_BROWSER_HIDDEN=false boss <cmd> # 或 BOSS_BROWSER_HEADLESS=false
69
+ ```
70
+
71
+ 已经有一只无头实例在跑时,换了变量也**不会**自动变可见 —— 端口上已有实例会被直接复用。先 `boss shutdown` 关掉那只,下条命令才会按新模式重启。
72
+
73
+ 浏览器**跨命令常驻**(一次性命令结束只 detach CDP,不关窗口),`boss shutdown` 是唯一的显式退出口。别在命令路径里加关浏览器的逻辑。名字不叫 `quit` 是因为交互模式里 `exit` / `quit` 已经是退出 REPL 的别名。
74
+
75
+ **判断在跑的实例是什么模式**:读 `http://127.0.0.1:53470/json/version` 的 `User-Agent`,含 `HeadlessChrome` 即无头(`probeRemoteHeadless()`)。**不要**用进程内变量判断 —— 一次性命令刚起进程时那些变量都是空的,`login.ts` 曾因此把登录页开在看不见的浏览器里。
76
+
77
+ `login` 是例外:扫码必须可见,它会自己探测并把无头实例关掉重启为有头。登录态在 `~/.boss-cli/.cache/` 的 user-data-dir 里,重启不丢。
78
+
79
+ 无头下额外带 `--screen-info={0,0 1920x1080 workAreaBottom=40}`:无头虚拟屏默认 800x600 是已知的强自动化指纹,而 `--window-size` 抬不动它,只有 `--screen-info` 能(Chrome 142+,仅无头有效)。**四个 workArea 参数必须分开写**(`workAreaTop/Bottom/Left/Right`),写成 `workArea=` 会让 Chrome 直接启动失败。
80
+
81
+ ## Puppeteer evaluate 约束(重要)
82
+
83
+ - 在工具代码中,避免使用 `page.evaluate(() => { ... })` / `page.waitForFunction(() => { ... })` 的函数写法。
84
+ - 统一改为字符串脚本写法(如 `page.evaluate("(() => { ... })()")`),避免构建后注入辅助符号导致浏览器上下文报错 `__name is not defined`。
85
+ - 出现 `__name is not defined` 时,优先检查最近新增的 evaluate / waitForFunction 回调并改成字符串脚本,不要加兜底掩盖问题。
86
+
87
+ ### ⚠️ 字符串脚本**收不到入参**(2026-09-21 实测)
88
+
89
+ 上面这条约束有个配套陷阱:**`evaluate(字符串, 入参)` 的入参会被静默丢弃**。puppeteer 对字符串形式的
90
+ pageFunction 是直接 `Runtime.evaluate` 当表达式求值的,压根不走 `callFunctionOn`,后面的参数无处可去。
91
+
92
+ ```ts
93
+ await frame.evaluate(`((x) => ({ got: x }))`, 'HELLO'); // → {} ,不是 { got: 'HELLO' }
94
+ await frame.waitForFunction(`((x) => x === "NEVER")`, { timeout: 3000 }, 'NO'); // → 6ms 就通过
95
+ ```
96
+
97
+ 两种后果都很阴:`evaluate` 拿到的是**函数对象**(`{}`,所有 `r.ok` 判断恒假);`waitForFunction`
98
+ 的判据是**函数对象**(恒真,等待变空转)。两者都不报错。
99
+
100
+ **唯一正确写法:把值 `JSON.stringify` 内联进脚本字符串。**
101
+
102
+ ```ts
103
+ await frame.evaluate(`(() => ({ got: ${JSON.stringify(value)} }))()`);
104
+ ```
105
+
106
+ **全仓库已清干净(2026-09-21)**,新增代码别再写回去。当时修掉的八处,以及它们坏成什么样:
107
+
108
+ | 位置 | 原来的症状 |
109
+ |---|---|
110
+ | `normal-search.ts` 城市选项匹配 | 功能性坏掉:`picked` 恒为 `{}`,每次都报「城市查无此项」,只有城市本来就是目标值、走早退分支时才像是好的 |
111
+ | `normal-search.ts` 关键词回填校验 / 岗位切换校验 | 判据恒真,等待空转 |
112
+ | `boss_sidebar_nav.ts` 菜单点击 + 两处 path 等待 | **整个函数等于没执行**:`clicked` 拿到函数对象(真值)所以「未找到菜单」永不报、点击其实没发生,随后的 path 等待又恒真直接 return,连 `goto` 兜底都跑不到 |
113
+ | `action.ts` 备注回填校验 | 「备注输入未生效」这句校验永远不触发 |
114
+ | `recommend.ts` 岗位联想 / 岗位已选 两处等待 | 判据恒真,切岗位后不等渲染就往下走 |
115
+ | `deep-search.ts` 同上两处 | 同上(该页已被平台下线,实际跑不到) |
116
+
117
+ 验收方式:`boss recommend <岗位>`(切岗位成功)、把页面挪到 `/web/chat/index` 后跑 `boss jd`
118
+ (能自己导航回 `/web/chat/job/list`)、备注校验在临时空白页上用同形状表达式验证真假值
119
+ (不拿真实候选人试写备注)。
package/CHANGELOG.md ADDED
@@ -0,0 +1,57 @@
1
+ # 更新日志
2
+
3
+ 本文件从 0.8.0 开始记,更早的版本看 git tag 和 GitHub Releases。
4
+
5
+ 只记**会改变你使用方式的东西**:行为变更、新参数、以及那些「看起来一直在工作、其实从来没生效」的修复。
6
+ 纯内部重构不记。
7
+
8
+ ## 0.8.1
9
+
10
+ ### 修复
11
+
12
+ - **侧栏导航整段没在工作。** `clickBossSidebarMenuToPath` 里的点击拿到的是个函数对象而不是布尔值,
13
+ 于是「未找到菜单」永远不报错、而点击其实根本没发生;紧接着的「等待跳转完成」判据同样恒为真,
14
+ 直接 return,连 `page.goto` 兜底都跑不到。整个函数等于什么都没做还报成功。影响 `boss jd`。
15
+ - **`boss recommend <岗位>` 切岗位后不等列表渲染就往下读**,同一个原因(等待空转)。
16
+ - **`boss action remark` 的「备注输入未生效」校验从来没触发过**,同一个原因。
17
+
18
+ 三处根因相同:puppeteer 对**字符串形式**的 pageFunction 是当表达式求值的,
19
+ `evaluate(脚本, 入参)` 后面的入参会被静默丢弃,求值结果是个函数对象——当判据恒为真,当返回值恒为真值。
20
+ 全仓库已清干净,写法约定见 `AGENTS.md`。
21
+
22
+ ## 0.8.0
23
+
24
+ ### ⚠️ 行为变更(相对 0.7.x)
25
+
26
+ - **`boss search` 每次都会先点一次「清空筛选」**,再按本次参数重设。
27
+ 筛选条件存在平台侧、原本跨命令粘着:上一条命令设过的学历/院校等会继续生效,
28
+ 而结果标题打的是入参,所以界面上看不出来。现在这一轮生效的条件只有你这条命令里写的。
29
+ - **`boss search` 不传 `--job` 会切「不限职位」**,不再沿用平台上残留的岗位。
30
+ 原来同一条命令跑两次可能搜的是两个池子。
31
+ - 结果标题里的每一项都改成**从页面实时读**,不再回显入参——标题里没写的条件就是真没生效。
32
+
33
+ ### 新增
34
+
35
+ `boss search` 补齐了平台侧的筛选项:
36
+
37
+ | 参数 | 说明 |
38
+ |---|---|
39
+ | `--city` | 搜索城市,默认读环境变量 `BOSS_SEARCH_CITY` |
40
+ | `--degree` / `--degree-range` | 学历预设档位 / 自定义区间(如 `大专-本科`) |
41
+ | `--school` | 院校要求,可多选 |
42
+ | `--exp` / `--exp-range` | 经验预设档位 / 自定义区间(如 `3-8`) |
43
+ | `--age` / `--age-range` | 年龄预设档位 / 自定义区间(如 `23-27`) |
44
+ | `--status` | 求职状态,可多选 |
45
+ | `--job-hop` | 跳槽频率 |
46
+ | `--major` | 专业,可多选,最多 10 个 |
47
+
48
+ `-range` 系列与对应的预设参数互斥(页面上本来就是二选一)。取值和注意事项见 README 的「搜索筛选条件」。
49
+
50
+ ### 修复
51
+
52
+ - **`--city` 的城市匹配一直是坏的**:选项匹配拿不到入参,恒为空对象,每次都报「城市查无此项」;
53
+ 只有城市本来就是目标值、走早退分支时才像是好的。
54
+
55
+ ### 已知不支持
56
+
57
+ 平台上的「性别」「薪资区间」「牛人活跃度」「牛人职位要求」没做;「资格证书」平台自身是隐藏的。