Skip to content
dsh.fish
Bundle

dsh-find-jobs

dsh 个人求职 Agent 插件:搜索岗位、读取 JD、按 job-match 技能做业务匹配评估与推荐,内置 mock 数据与 bsk 实时抓取。

Source
nicklin99
License
MIT
Updated
Updated 19 hours ago

Readme

# dsh-find-jobs — Personal Job Hunter(DSH 插件)

一个运行在 **DeepSeek Harness(dsh)** 上的**个人求职 Agent** 插件。

> 它不是一个求职网站,也不是一个“AI 聊天框”。告诉它你的求职目标,它会持续为你找到**真正值得投递**的工作:理解画像 → 搜索 → 精读 JD → 匹配评估 → 只报值得投的 Top N(附原因)。

> 如果这个项目对你有帮助,欢迎点个 **Star ⭐**,谢谢支持 🙏

详细 Spec(产品定义 / 档位词表 / 阶段计划 / 工程约定)见 **[AGENTS.md](./AGENTS.md)**。

---

## 前置依赖:BrowserSkill(实时抓取必需)

实时抓取(`mock: false`)依赖腾讯开源的 **BrowserSkill(bsk)**:用你**本机真实浏览器 + 登录态**去抓 Boss直聘 / 小红书。

```bash
# 1. 安装 bsk CLI(Node.js 18+)
npm install -g @tencent/browserskill     # 以官方 README 为准:https://github.com/Tencent/BrowserSkill

# 2. 浏览器安装 BrowserSkill 扩展(Chrome 扩展商店),保持浏览器开启

# 3. 自检
bsk doctor
```

然后:用目标站点(Boss直聘 / 小红书)的账号在你的浏览器里登录即可被复用。
`search_jobs` 会打开**新标签页**抓取并关闭,不影响你正在用的页面;抓取只在会话目录里存档文本,不对外发送任何数据。

> 默认 `mock: false`(实时抓取),因此 BrowserSkill 是**必装前置**;仅离线演示 / 单测时置 `mock: true`(内置演示岗位)才不依赖它。

---

## 快速开始(在 dsh 里跑起来)

```bash
# 1) 注册插件(dsh 无 init 脚手架,add 即注册)
dsh plugin --profile web add "$(pwd)"

# 2) 技能随插件自动注册(job-hunter / job-search / job-match),无需手动复制;
#    若宿主未走运行时技能注册,才需要把 skills/ 下三个 SKILL.md 复制到 ~/.dsh/skills/<name>/

# 3) 验证与运行
dsh web --dump-config | grep -i find-jobs   # 层已加载
dsh web                                      # Web UI,对 Agent 说一句:
#   “帮我找适合我的工作。”
```

卸载:`dsh plugin --profile web remove dsh-find-jobs`。

---

## 怎么问(意图示例)

| 你想 | 可以这样说 |
| --- | --- |
| 先了解我,再找适合我的工作 | “帮我找适合我的工作。” |
| 找最值得投的 Top N | “最近有什么值得投的?给我 Top 5。” |
| 只搜岗位、不评估 | “搜一下小红书上的 AI 工程师,5 个。” |
| 带地点 / 远程 / 薪资等条件 | “帮我找美国 Remote 的 AI Engineer,5 年经验,180K 以上。” |
| 评估已有岗位 | “这个岗位适合我吗?”(附链接,或指之前搜到的) |
| 追问某个岗位 | “为什么这个岗位适合我?” |

Agent 会先看你的求职画像,缺关键信息时再问你(岗位 / 技能 / 年限 / 地点 / 远程 / 最低薪资,薪资会问清币种与周期),然后按意图执行最合适的工作流。它只做**搜索、匹配与推荐**,不会自动投递。

---

## 模块说明

### 技能(三层编排,用户无需手动触发子技能)

```text
job-hunter            总工作流(编排器)
   ├── job-search     搜索:识别参数 → 并行搜多源 → 自动存档
   └── job-match      匹配评估:5 步业务判断 → 统一结果卡
```

| 模块 | 类型 | 作用 | 位置 |
| --- | --- | --- | --- |
| `job-hunter` | 工作流技能 | 求职任务编排:先看画像 → 意图选最小工作流 → 分流(复用/精读)→ Top N 推荐与汇报 | `skills/job-hunter/SKILL.md` |
| `job-search` | 技能 | 把用户原话转 `search_jobs` 参数(源 / 数量 / save_dir),多源并行,返回即自动存档 | `skills/job-search/SKILL.md` |
| `job-match` | 技能 | 把 JD 硬性要求与画像逐项对照(5 步),输出统一结果卡并写回岗位档案 | `skills/job-match/SKILL.md` |

### 工具 / 库

| 模块 | 类型 | 作用 |
| --- | --- | --- |
| `get_job_profile` / `update_job_profile` | 工具 | 求职画像记忆,持久化到 `$DSH_HOME/profiles/<profile>/jobhunter_profile.json` |
| `search_jobs` | 工具 | 一次搜一个数据源,搜索成功即自动落盘 `<dir>/<id>.json` + `index.json`,返回**轻量摘要**(省 token,完整 JD 只在文件里) |
| `jobsArchive` | lib | 落盘的确定性实现:按 id 去重合并、保留后补 match/note、进程内串行防并发覆盖 |

### 匹配档位(业务建议)

`match_score`:`>85 strong_match · 70–85 good_match · 55–70 stretch · <55 low_match`;`recommendation` = `apply`(值得投)/ `skip`(不值得投)。`match` 结果卡作为岗位档案 `<id>.json` 的顶层字段——**既是评估结果,也是缓存**(画像未变则复用,不重复评估)。

### 岗位清单(运行时落盘)

```text
<cwd>/jobs/
├── index.json       # 索引(reference):id → file、first/last_seen、match 轻量标识
└── <id>.json        # 每岗完整记录(唯一真源):search 字段 + 完整 JD + match / note
```

由 `search_jobs(save_dir=<pwd>/jobs)` 自动维护。

---

## 数据源(默认实时抓取)

目前支持实时抓取:**Boss直聘(`boss-zhipin`)**、**小红书(`xiaohongshu`)**,可按需在 `sources` 里启用。

默认 `mock: false`(实时),无需切换;仅离线演示 / 单测时把 `mock` 置为 `true`(内置演示岗位)。

实时抓取按 `Config.sources` 勾选来源(本仓库 `cordis.patch.yml` 即为默认值,profile 层可覆盖):

```yaml
- insert:
    - id: dsh-find-jobs
      config:
        mock: false
        sources: [boss-zhipin, xiaohongshu]   # 可勾选增删,顺序即优先级
```

注意:
- 依赖 **bsk daemon + 浏览器扩展在线 + 站点登录态**(`bsk doctor` 自检);
- 站点解析器(Boss直聘 / 小红书)按当前 DOM 编写、属**实验性**——解析失败时 `search_jobs` 会带页面片段报错,便于校准;
- 小红书链接带 **`xsec_token`(有时效)**,汇报时原样引用完整 url。
- 列表页无限滚动:滚动机制在 `bskRunner` 里通用,按 `listScroll.mode` 分流——`append`(Boss:DOM 只增不减,滚到底)与 `virtualized`(小红书:DOM 只保留视口,`documentElement.scrollTop += 300` × ≤20 轮 + evaluate `.note-item` outerHTML + `data-note-id` 去重,实测 43 条通过)。后续目标:统一抽象为 `scroll-load-more` / `pagination` / `virtual-list` strategy。

---

## 开发

```bash
pnpm install
pnpm typecheck     # tsc --noEmit
pnpm test          # 离线单测(不联网)
pnpm test:boss     # 只看 Boss 解析单测
pnpm test:xhs      # 只看小红书解析单测
pnpm live:boss     # 实跑 Boss(需 bsk 在线 + 登录态)
pnpm live:xhs      # 实跑小红书(同上)
pnpm live:scroll   # 只实跑 Boss 列表无限滚动(不抓详情,验证能加载出超首屏的岗位)
pnpm live:parallel # 并行实跑 Boss + 小红书(同运行域内命令级串行;多用户/会话各自独立,互不抢窗口)
pnpm build         # typecheck + tsdown → lib/
```

> `src/` 改动后必须 `pnpm build` 才进 `lib/`(dsh 加载 `package.json main: ./lib/index.js`);skills/*.md 由运行时直接读取,改后重启 dsh 即可。

---

## 目录结构

```text
src/
├── index.ts            # 插件入口(name/inject/Config/apply,ctx.logger 记日志)
├── config.ts           # JobHunterConfig + Schema(mock 门控 + sources 勾选)
├── types.ts            # 领域类型契约
├── data/mockJobs.ts    # 离线 mock 岗位库(保持 Job 形状)
├── lib/
│   ├── profileStore.ts # 画像持久化
│   ├── search.ts       # mock 搜索纯函数
│   ├── sanitize.ts     # 无损 JSON 序列化
│   ├── jobsArchive.ts  # search_jobs 自动落盘(<id>.json + index.json,进程内串行)
│   └── skillRegister.ts# 运行时注册内置技能
├── provider/           # bskRunner(会话+抓取) · 站点适配器(bossZhipin/xiaohongshu) · HTML/薪资解析
└── tools/              # searchJobs(save_dir 必填自动落盘)/ jobProfile
skills/
├── job-hunter/         # 总工作流技能
├── job-search/         # 搜索技能
└── job-match/          # 匹配评估技能
test/                   # 离线单测;test/live/* 需 bsk 实跑
```

## 扩展更多数据源(新增适配器,如猎聘 / 拉勾)

1. 仿照 `src/provider/bossZhipin.ts` 实现 `SiteAdapter`(`buildSearchUrl` / `parseListPage` / `parseDetailText` 纯函数);
2. 在 `src/provider/site.ts` 的 `ADAPTERS` 注册表登记;
3. 在 `src/config.ts` 的 `sources` union 与 `cordis.patch.yml` 中启用;
4. 若列表靠滚动懒加载更多岗位,在适配器声明 `listScroll`(`append` 给 `countExpression`;`virtualized` 走 300px 自然滚动快照合并;分页站点后续走 `pagination` strategy,滚动抓取复用通用实现,无需重写);
5. 纯解析部分写单测(无需真实浏览器)。

## Roadmap

- **Phase 2(当前)**:真实 Job Search(bsk 实时浏览 Boss直聘 / 小红书,已实站校准)+ `save_dir` 自动存档与轻量返回
- **Phase 3**:持续 Job Search + 个人 Memory(已看岗位去重 / 定时跑)
- **Phase 4**:自建 Web UI 包装(先吃透 dsh web 再决定)

## 安全与隐私

- 实时抓取只读你已登录的招聘站,从**不外发**数据;存档文本在本地会话目录。
- 岗位链接可能含平台凭据参数(token),`jobs/` 目录请勿提交(已 gitignore)。
- 使用 bsk 即把浏览器控制权交给本工具进程,请只在可信环境运行。

## License

MIT

Install

dsh plugin --profile web add github:nicklin99/dsh-find-jobs

Profile: web

  • This package builds from source on install. pnpm will ask you to allow its build script — that is permission to run the package’s code on your machine, outside the agent sandbox. Only allow sources you trust.
  • This source has no pinned commit, so a later push upstream changes what installs. Prefer pinning a commit.
Source