hipowork-cli 0.2.0__tar.gz → 0.3.2__tar.gz

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 (39) hide show
  1. hipowork_cli-0.3.2/PKG-INFO +216 -0
  2. hipowork_cli-0.3.2/README.md +183 -0
  3. {hipowork_cli-0.2.0 → hipowork_cli-0.3.2}/pyproject.toml +2 -1
  4. {hipowork_cli-0.2.0 → hipowork_cli-0.3.2}/src/hipowork_cli/__init__.py +5 -3
  5. hipowork_cli-0.3.2/src/hipowork_cli/__main__.py +5 -0
  6. {hipowork_cli-0.2.0 → hipowork_cli-0.3.2}/src/hipowork_cli/scripts/hipo_authorize.py +71 -31
  7. {hipowork_cli-0.2.0 → hipowork_cli-0.3.2}/src/hipowork_cli/scripts/hipo_e2e.py +25 -21
  8. {hipowork_cli-0.2.0 → hipowork_cli-0.3.2}/src/hipowork_cli/scripts/hipo_match_jobs.py +1 -1
  9. {hipowork_cli-0.2.0 → hipowork_cli-0.3.2}/src/hipowork_cli/scripts/hipo_mcp_client.py +31 -6
  10. {hipowork_cli-0.2.0 → hipowork_cli-0.3.2}/src/hipowork_cli/scripts/hipo_publish_job.py +4 -2
  11. {hipowork_cli-0.2.0 → hipowork_cli-0.3.2}/src/hipowork_cli/scripts/hipo_resume_import.py +6 -1
  12. hipowork_cli-0.3.2/src/hipowork_cli.egg-info/PKG-INFO +216 -0
  13. {hipowork_cli-0.2.0 → hipowork_cli-0.3.2}/src/hipowork_cli.egg-info/SOURCES.txt +1 -0
  14. {hipowork_cli-0.2.0 → hipowork_cli-0.3.2}/src/hipowork_cli.egg-info/entry_points.txt +1 -0
  15. hipowork_cli-0.2.0/PKG-INFO +0 -182
  16. hipowork_cli-0.2.0/README.md +0 -149
  17. hipowork_cli-0.2.0/src/hipowork_cli.egg-info/PKG-INFO +0 -182
  18. {hipowork_cli-0.2.0 → hipowork_cli-0.3.2}/setup.cfg +0 -0
  19. {hipowork_cli-0.2.0 → hipowork_cli-0.3.2}/src/hipowork_cli/examples/job.example.json +0 -0
  20. {hipowork_cli-0.2.0 → hipowork_cli-0.3.2}/src/hipowork_cli/examples/resume.example.json +0 -0
  21. {hipowork_cli-0.2.0 → hipowork_cli-0.3.2}/src/hipowork_cli/scripts/hipo_accounts.py +0 -0
  22. {hipowork_cli-0.2.0 → hipowork_cli-0.3.2}/src/hipowork_cli/scripts/hipo_auth.py +0 -0
  23. {hipowork_cli-0.2.0 → hipowork_cli-0.3.2}/src/hipowork_cli/scripts/hipo_close_job.py +0 -0
  24. {hipowork_cli-0.2.0 → hipowork_cli-0.3.2}/src/hipowork_cli/scripts/hipo_healthcheck.py +0 -0
  25. {hipowork_cli-0.2.0 → hipowork_cli-0.3.2}/src/hipowork_cli/scripts/hipo_market.py +0 -0
  26. {hipowork_cli-0.2.0 → hipowork_cli-0.3.2}/src/hipowork_cli/scripts/hipo_match_candidates.py +0 -0
  27. {hipowork_cli-0.2.0 → hipowork_cli-0.3.2}/src/hipowork_cli/scripts/hipo_resume_extract.py +0 -0
  28. {hipowork_cli-0.2.0 → hipowork_cli-0.3.2}/src/hipowork_cli/scripts/hipo_resume_validate.py +0 -0
  29. {hipowork_cli-0.2.0 → hipowork_cli-0.3.2}/src/hipowork_cli/scripts/hipo_search_candidates.py +0 -0
  30. {hipowork_cli-0.2.0 → hipowork_cli-0.3.2}/src/hipowork_cli/scripts/hipo_stats.py +0 -0
  31. {hipowork_cli-0.2.0 → hipowork_cli-0.3.2}/src/hipowork_cli/scripts/hipo_token_refresh.py +0 -0
  32. {hipowork_cli-0.2.0 → hipowork_cli-0.3.2}/src/hipowork_cli/scripts/hipo_token_status.py +0 -0
  33. {hipowork_cli-0.2.0 → hipowork_cli-0.3.2}/src/hipowork_cli/scripts/hipo_token_sync.py +0 -0
  34. {hipowork_cli-0.2.0 → hipowork_cli-0.3.2}/src/hipowork_cli/templates/success.html +0 -0
  35. {hipowork_cli-0.2.0 → hipowork_cli-0.3.2}/src/hipowork_cli.egg-info/dependency_links.txt +0 -0
  36. {hipowork_cli-0.2.0 → hipowork_cli-0.3.2}/src/hipowork_cli.egg-info/requires.txt +0 -0
  37. {hipowork_cli-0.2.0 → hipowork_cli-0.3.2}/src/hipowork_cli.egg-info/top_level.txt +0 -0
  38. {hipowork_cli-0.2.0 → hipowork_cli-0.3.2}/tests/test_hipo_accounts.py +0 -0
  39. {hipowork_cli-0.2.0 → hipowork_cli-0.3.2}/tests/test_hipo_resume_import.py +0 -0
@@ -0,0 +1,216 @@
1
+ Metadata-Version: 2.4
2
+ Name: hipowork-cli
3
+ Version: 0.3.2
4
+ Summary: HiPo Work CLI — Agent 友好的招聘平台命令行工具集(OAuth 授权 / 岗位发布 / 候选人匹配 / 简历导入)
5
+ Author-email: Lin Tong <sexylin2010@gmail.com>
6
+ License: MIT
7
+ Project-URL: Homepage, https://hipowork.com
8
+ Project-URL: Repository, https://github.com/sexylin/hipowork-cli
9
+ Project-URL: Documentation, https://hipowork.com
10
+ Keywords: hipo,hipowork,recruitment,hiring,candidate-matching,cli,ai-agent
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Environment :: Console
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Operating System :: OS Independent
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
21
+ Classifier: Topic :: Office/Business :: Financial :: Investment
22
+ Classifier: Topic :: Utilities
23
+ Requires-Python: >=3.10
24
+ Description-Content-Type: text/markdown
25
+ Requires-Dist: mcp>=1.10
26
+ Requires-Dist: httpx>=0.27
27
+ Provides-Extra: resume
28
+ Requires-Dist: pymupdf>=1.24; extra == "resume"
29
+ Provides-Extra: dev
30
+ Requires-Dist: build>=1.0; extra == "dev"
31
+ Requires-Dist: twine>=5.0; extra == "dev"
32
+ Requires-Dist: pytest>=7.0; extra == "dev"
33
+
34
+ # hipowork-cli
35
+
36
+ <div align="center">
37
+
38
+ # 让你的简历,被 AI 看到
39
+ ### 让机会与人才自然相遇
40
+
41
+ [![PyPI](https://img.shields.io/pypi/v/hipowork-cli?color=blue)](https://pypi.org/project/hipowork-cli/)
42
+ [![Python](https://img.shields.io/badge/Python-3.10%2B-blue)](https://www.python.org/)
43
+ [![OAuth 2.0](https://img.shields.io/badge/Auth-OAuth2.0-green)](https://oauth.net/2/)
44
+ [![License](https://img.shields.io/badge/license-MIT-green)](LICENSE)
45
+
46
+ [中文文档](README.md) · [English](README_EN.md)
47
+
48
+ **官网:** [https://hipowork.com](https://hipowork.com) · [https://www.hipowork.com](https://www.hipowork.com)
49
+ **远程 MCP 服务:** `https://mcp.hipowork.com/mcp`
50
+ **API 服务端点:** `https://api.hipowork.com`
51
+
52
+ </div>
53
+
54
+ ---
55
+
56
+ ## 🌟 平台理念
57
+
58
+ 在传统的招聘求职中,优秀的简历常常沉睡在静态文档或封闭的简历库中,被动等待死板的关键词匹配。
59
+
60
+ **HiPo Work** 致力于改变这一现状:
61
+ - **把简历沉淀为高精度语义资产**:通过 Agent 或客户端工具,求职者的专业技能、独立项目经验、工作职责与落地成果被全量结构化沉淀并生成向量。
62
+ - **让你的简历被 AI 工具随时检索**:不管是 Claude Code、Cursor、OpenAI CodeX、Hermes Agent 还是企业招聘 Agent,都能在秒级通过工具精准检索、评估与连接候选人。
63
+ - **让机会与人才自然相遇**:不再需要海投或盲目筛选,基于真实项目深度与核心能力,实现招聘方与求职者的双向精准触达。
64
+
65
+ ---
66
+
67
+ ## 🔗 相关生态与公开仓库
68
+
69
+ HiPo Work 提供了完整的 Agent 原生招聘生态,涵盖命令行工具、MCP 服务与 Web 控制台:
70
+
71
+ | 项目 / 平台 | 链接 | 说明 |
72
+ |------------|------|------|
73
+ | **官方网站** | [hipowork.com](https://hipowork.com) | 包含求职者中心、招聘方控制台、岗位发布与语义匹配演示 |
74
+ | **hipowork-cli**(本项目) | [github.com/sexylin/hipowork-cli](https://github.com/sexylin/hipowork-cli) | 客户端命令行工具集(PyPI: `pip install hipowork-cli`),提供 `hipo` 与 `hipowork-cli` 终端命令 |
75
+ | **hipo-mcp** | [github.com/sexylin/hipo-mcp](https://github.com/sexylin/hipo-mcp) | 远程 MCP 服务端,遵循 Model Context Protocol 标准,支持 OAuth 2.0 (PKCE) |
76
+ | **MCP Registry** | `io.github.sexylin/hipo-work` | MCP 官方 Registry 认证注册服务坐标 |
77
+
78
+ ---
79
+
80
+ ## 📦 安装
81
+
82
+ ```bash
83
+ # 从 PyPI 安装(推荐,要求 Python 3.10+)
84
+ pip install hipowork-cli
85
+
86
+ # 可选:支持本地简历 PDF 文本提取依赖
87
+ pip install hipowork-cli[resume]
88
+ ```
89
+
90
+ 安装完成后系统提供两个完全等价的命令行入口:`hipo` 与 `hipowork-cli`。
91
+
92
+ ---
93
+
94
+ ## 🚀 快速开始
95
+
96
+ ### 1. 登录与授权
97
+
98
+ ```bash
99
+ # 求职者登录(终端将打印标准引导并在浏览器完成邮箱验证)
100
+ hipowork-cli login --role candidate # 或: hipo login --role candidate
101
+
102
+ # 招聘方登录
103
+ hipowork-cli login --role employer
104
+ ```
105
+
106
+ > **提示**:
107
+ > - 首次授权需要在浏览器完成邮箱验证码登录;如果你已经在 HiPo Work Web 端([hipowork.com](https://hipowork.com))登录过,授权页将直接显示**「确认授权」**,一键放行免重复输入验证码。
108
+ > - 授权完成后 Token 自动刷新与持久化,存放在本机 `~/.hipo_mcp_tokens.json`(0600 权限),无需手动维护。
109
+ > - CLI 授权成功还会自动打开 Web Handoff 页面直接进入对应的 Profile 档案页。
110
+
111
+ ### 2. 状态检查与账户管理
112
+
113
+ ```bash
114
+ hipo status # 查看当前登录身份、Token 有效期与 Scope 权限
115
+ hipo refresh # 强制轮换 Access Token
116
+ hipo accounts list # 查看已登录的多账户(支持多邮箱、多角色随时切换)
117
+ ```
118
+
119
+ ### 3. 日常使用
120
+
121
+ ```bash
122
+ # 求职者:根据简历智能匹配在招岗位
123
+ hipo match-jobs
124
+
125
+ # 求职者:导入结构化简历并上传本地附件
126
+ hipo resume-import --json my_resume.json --attachment my_resume.pdf
127
+
128
+ # 招聘方:发布招聘岗位
129
+ hipo publish-job --json examples/job.example.json
130
+
131
+ # 招聘方:自然语言搜索候选人
132
+ hipo search "成都 5年经验 熟悉Solidity和Go的全栈"
133
+ ```
134
+
135
+ ---
136
+
137
+ ## 📋 命令速查表
138
+
139
+ ### 认证与凭据
140
+ | 命令 | 说明 |
141
+ |---|---|
142
+ | `hipowork-cli login --role candidate/employer` | 统一登录入口(打印格式化引导并打开浏览器授权) |
143
+ | `hipo authorize --role candidate/employer` | OAuth 授权(login 别名,PKCE + 邮箱验证码) |
144
+ | `hipo status` | 查看当前 Token 状态、角色、权限与过期时间 |
145
+ | `hipo refresh` | 强制刷新 Access Token |
146
+ | `hipo token-sync [--refresh]` | 导出 Token 供浏览器前端调试使用(Base64 格式) |
147
+ | `hipo accounts list/current/switch/delete` | 多账户管理(支持多个角色与邮箱多凭据隔离存储) |
148
+
149
+ ### 求职者(Candidate)
150
+ | 命令 | 说明 |
151
+ |---|---|
152
+ | `hipo match-jobs [--json]` | 根据我的简历匹配全平台岗位,输出按匹配度排序的列表及多维度评分 |
153
+ | `hipo resume-extract <file.pdf> [--out x.txt]` | 本地提取简历文本(支持 PDF、DOCX、TXT) |
154
+ | `hipo resume-validate <resume.json>` | 导入前校验 JSON 结构(包括 duration_months、projects 完整性等) |
155
+ | `hipo resume-import --json <resume.json> [--attachment file.pdf]` | **核心推荐**:直接导入本地结构化简历,支持携带原件附件存档 |
156
+ | `hipo resume-import --text <resume.txt>` | 传入简历纯文本,走平台后端 AI 服务解析后导入 |
157
+
158
+ ### 招聘方(Employer)
159
+ | 命令 | 说明 |
160
+ |---|---|
161
+ | `hipo publish-job --title x --text "..." [--json file]` | 发布招聘需求(支持结构化条件与面议设置) |
162
+ | `hipo close-job <job_id>` | 关闭已发布的职位(关闭后不再被候选人检索或参与匹配) |
163
+ | `hipo search "自然语言描述" [--max n]` | 自然语言直接检索候选人人格与经历 |
164
+ | `hipo match-candidates --text "..." / --json cond.json / --job <id>` | 结构化多维度候选人匹配(支持技能硬过滤与向量语义检索) |
165
+ | `hipo market --keyword python [--industry tech]` | 技能与行业人才市场供需热度分析 |
166
+ | `hipo stats` | 平台统计概览(在招职位、人才分布等) |
167
+
168
+ ### 运维与端到端诊断
169
+ | 命令 | 说明 |
170
+ |---|---|
171
+ | `hipo healthcheck` | 一键体检:检查 API / MCP / OAuth metadata / Embedding 全链路连通性 |
172
+ | `hipo e2e` | 完整端到端冒烟测试:Token 校验 → REST /auth/me → MCP 会话 → 受保护工具调用 |
173
+
174
+ > 任意命令均可添加 `--help` 查看完整参数;大部分命令支持 `--json` 输出结构化数据,方便与自动化脚本结合。
175
+
176
+ ---
177
+
178
+ ## 📄 简历导入的最佳实践
179
+
180
+ ### 1. 推荐方式:`--json`(带独立项目经历与原始附件)
181
+ 使用你本地的 LLM 或 Agent 将简历提炼为结构化 JSON(参考 `examples/resume.example.json`),重点保留:
182
+ - **`projects`**:独立作品、开源项目、商业落地专项等(作为一等公民数据独立呈现);
183
+ - **`work_experiences`**:职责、成果、技术栈及精确的 `duration_months`(用于累计工作年限);
184
+ - **`--attachment`**:携带本地原始 PDF/Word 附件,自动上传加密存储并供招聘方预览。
185
+
186
+ ```bash
187
+ hipo resume-import --json my_resume.json --attachment my_resume.pdf
188
+ ```
189
+
190
+ ### 2. 文本解析方式:`--text`
191
+ 如果你不想手动组织 JSON,也可以直接提取文本由后端 AI 统一解析:
192
+ ```bash
193
+ hipo resume-extract my_resume.pdf --out resume.txt
194
+ hipo resume-import --text resume.txt
195
+ ```
196
+
197
+ ---
198
+
199
+ ## 🛠️ 本地开发与源码运行
200
+
201
+ ```bash
202
+ git clone git@github.com:sexylin/hipowork-cli.git
203
+ cd hipowork-cli
204
+
205
+ python3 -m venv .venv
206
+ .venv/bin/pip install -e .[resume]
207
+
208
+ # 运行完整单元测试套件
209
+ .venv/bin/python -m unittest discover -s tests
210
+ ```
211
+
212
+ ---
213
+
214
+ ## 📄 License
215
+
216
+ 本项目基于 [MIT License](LICENSE) 开源。
@@ -0,0 +1,183 @@
1
+ # hipowork-cli
2
+
3
+ <div align="center">
4
+
5
+ # 让你的简历,被 AI 看到
6
+ ### 让机会与人才自然相遇
7
+
8
+ [![PyPI](https://img.shields.io/pypi/v/hipowork-cli?color=blue)](https://pypi.org/project/hipowork-cli/)
9
+ [![Python](https://img.shields.io/badge/Python-3.10%2B-blue)](https://www.python.org/)
10
+ [![OAuth 2.0](https://img.shields.io/badge/Auth-OAuth2.0-green)](https://oauth.net/2/)
11
+ [![License](https://img.shields.io/badge/license-MIT-green)](LICENSE)
12
+
13
+ [中文文档](README.md) · [English](README_EN.md)
14
+
15
+ **官网:** [https://hipowork.com](https://hipowork.com) · [https://www.hipowork.com](https://www.hipowork.com)
16
+ **远程 MCP 服务:** `https://mcp.hipowork.com/mcp`
17
+ **API 服务端点:** `https://api.hipowork.com`
18
+
19
+ </div>
20
+
21
+ ---
22
+
23
+ ## 🌟 平台理念
24
+
25
+ 在传统的招聘求职中,优秀的简历常常沉睡在静态文档或封闭的简历库中,被动等待死板的关键词匹配。
26
+
27
+ **HiPo Work** 致力于改变这一现状:
28
+ - **把简历沉淀为高精度语义资产**:通过 Agent 或客户端工具,求职者的专业技能、独立项目经验、工作职责与落地成果被全量结构化沉淀并生成向量。
29
+ - **让你的简历被 AI 工具随时检索**:不管是 Claude Code、Cursor、OpenAI CodeX、Hermes Agent 还是企业招聘 Agent,都能在秒级通过工具精准检索、评估与连接候选人。
30
+ - **让机会与人才自然相遇**:不再需要海投或盲目筛选,基于真实项目深度与核心能力,实现招聘方与求职者的双向精准触达。
31
+
32
+ ---
33
+
34
+ ## 🔗 相关生态与公开仓库
35
+
36
+ HiPo Work 提供了完整的 Agent 原生招聘生态,涵盖命令行工具、MCP 服务与 Web 控制台:
37
+
38
+ | 项目 / 平台 | 链接 | 说明 |
39
+ |------------|------|------|
40
+ | **官方网站** | [hipowork.com](https://hipowork.com) | 包含求职者中心、招聘方控制台、岗位发布与语义匹配演示 |
41
+ | **hipowork-cli**(本项目) | [github.com/sexylin/hipowork-cli](https://github.com/sexylin/hipowork-cli) | 客户端命令行工具集(PyPI: `pip install hipowork-cli`),提供 `hipo` 与 `hipowork-cli` 终端命令 |
42
+ | **hipo-mcp** | [github.com/sexylin/hipo-mcp](https://github.com/sexylin/hipo-mcp) | 远程 MCP 服务端,遵循 Model Context Protocol 标准,支持 OAuth 2.0 (PKCE) |
43
+ | **MCP Registry** | `io.github.sexylin/hipo-work` | MCP 官方 Registry 认证注册服务坐标 |
44
+
45
+ ---
46
+
47
+ ## 📦 安装
48
+
49
+ ```bash
50
+ # 从 PyPI 安装(推荐,要求 Python 3.10+)
51
+ pip install hipowork-cli
52
+
53
+ # 可选:支持本地简历 PDF 文本提取依赖
54
+ pip install hipowork-cli[resume]
55
+ ```
56
+
57
+ 安装完成后系统提供两个完全等价的命令行入口:`hipo` 与 `hipowork-cli`。
58
+
59
+ ---
60
+
61
+ ## 🚀 快速开始
62
+
63
+ ### 1. 登录与授权
64
+
65
+ ```bash
66
+ # 求职者登录(终端将打印标准引导并在浏览器完成邮箱验证)
67
+ hipowork-cli login --role candidate # 或: hipo login --role candidate
68
+
69
+ # 招聘方登录
70
+ hipowork-cli login --role employer
71
+ ```
72
+
73
+ > **提示**:
74
+ > - 首次授权需要在浏览器完成邮箱验证码登录;如果你已经在 HiPo Work Web 端([hipowork.com](https://hipowork.com))登录过,授权页将直接显示**「确认授权」**,一键放行免重复输入验证码。
75
+ > - 授权完成后 Token 自动刷新与持久化,存放在本机 `~/.hipo_mcp_tokens.json`(0600 权限),无需手动维护。
76
+ > - CLI 授权成功还会自动打开 Web Handoff 页面直接进入对应的 Profile 档案页。
77
+
78
+ ### 2. 状态检查与账户管理
79
+
80
+ ```bash
81
+ hipo status # 查看当前登录身份、Token 有效期与 Scope 权限
82
+ hipo refresh # 强制轮换 Access Token
83
+ hipo accounts list # 查看已登录的多账户(支持多邮箱、多角色随时切换)
84
+ ```
85
+
86
+ ### 3. 日常使用
87
+
88
+ ```bash
89
+ # 求职者:根据简历智能匹配在招岗位
90
+ hipo match-jobs
91
+
92
+ # 求职者:导入结构化简历并上传本地附件
93
+ hipo resume-import --json my_resume.json --attachment my_resume.pdf
94
+
95
+ # 招聘方:发布招聘岗位
96
+ hipo publish-job --json examples/job.example.json
97
+
98
+ # 招聘方:自然语言搜索候选人
99
+ hipo search "成都 5年经验 熟悉Solidity和Go的全栈"
100
+ ```
101
+
102
+ ---
103
+
104
+ ## 📋 命令速查表
105
+
106
+ ### 认证与凭据
107
+ | 命令 | 说明 |
108
+ |---|---|
109
+ | `hipowork-cli login --role candidate/employer` | 统一登录入口(打印格式化引导并打开浏览器授权) |
110
+ | `hipo authorize --role candidate/employer` | OAuth 授权(login 别名,PKCE + 邮箱验证码) |
111
+ | `hipo status` | 查看当前 Token 状态、角色、权限与过期时间 |
112
+ | `hipo refresh` | 强制刷新 Access Token |
113
+ | `hipo token-sync [--refresh]` | 导出 Token 供浏览器前端调试使用(Base64 格式) |
114
+ | `hipo accounts list/current/switch/delete` | 多账户管理(支持多个角色与邮箱多凭据隔离存储) |
115
+
116
+ ### 求职者(Candidate)
117
+ | 命令 | 说明 |
118
+ |---|---|
119
+ | `hipo match-jobs [--json]` | 根据我的简历匹配全平台岗位,输出按匹配度排序的列表及多维度评分 |
120
+ | `hipo resume-extract <file.pdf> [--out x.txt]` | 本地提取简历文本(支持 PDF、DOCX、TXT) |
121
+ | `hipo resume-validate <resume.json>` | 导入前校验 JSON 结构(包括 duration_months、projects 完整性等) |
122
+ | `hipo resume-import --json <resume.json> [--attachment file.pdf]` | **核心推荐**:直接导入本地结构化简历,支持携带原件附件存档 |
123
+ | `hipo resume-import --text <resume.txt>` | 传入简历纯文本,走平台后端 AI 服务解析后导入 |
124
+
125
+ ### 招聘方(Employer)
126
+ | 命令 | 说明 |
127
+ |---|---|
128
+ | `hipo publish-job --title x --text "..." [--json file]` | 发布招聘需求(支持结构化条件与面议设置) |
129
+ | `hipo close-job <job_id>` | 关闭已发布的职位(关闭后不再被候选人检索或参与匹配) |
130
+ | `hipo search "自然语言描述" [--max n]` | 自然语言直接检索候选人人格与经历 |
131
+ | `hipo match-candidates --text "..." / --json cond.json / --job <id>` | 结构化多维度候选人匹配(支持技能硬过滤与向量语义检索) |
132
+ | `hipo market --keyword python [--industry tech]` | 技能与行业人才市场供需热度分析 |
133
+ | `hipo stats` | 平台统计概览(在招职位、人才分布等) |
134
+
135
+ ### 运维与端到端诊断
136
+ | 命令 | 说明 |
137
+ |---|---|
138
+ | `hipo healthcheck` | 一键体检:检查 API / MCP / OAuth metadata / Embedding 全链路连通性 |
139
+ | `hipo e2e` | 完整端到端冒烟测试:Token 校验 → REST /auth/me → MCP 会话 → 受保护工具调用 |
140
+
141
+ > 任意命令均可添加 `--help` 查看完整参数;大部分命令支持 `--json` 输出结构化数据,方便与自动化脚本结合。
142
+
143
+ ---
144
+
145
+ ## 📄 简历导入的最佳实践
146
+
147
+ ### 1. 推荐方式:`--json`(带独立项目经历与原始附件)
148
+ 使用你本地的 LLM 或 Agent 将简历提炼为结构化 JSON(参考 `examples/resume.example.json`),重点保留:
149
+ - **`projects`**:独立作品、开源项目、商业落地专项等(作为一等公民数据独立呈现);
150
+ - **`work_experiences`**:职责、成果、技术栈及精确的 `duration_months`(用于累计工作年限);
151
+ - **`--attachment`**:携带本地原始 PDF/Word 附件,自动上传加密存储并供招聘方预览。
152
+
153
+ ```bash
154
+ hipo resume-import --json my_resume.json --attachment my_resume.pdf
155
+ ```
156
+
157
+ ### 2. 文本解析方式:`--text`
158
+ 如果你不想手动组织 JSON,也可以直接提取文本由后端 AI 统一解析:
159
+ ```bash
160
+ hipo resume-extract my_resume.pdf --out resume.txt
161
+ hipo resume-import --text resume.txt
162
+ ```
163
+
164
+ ---
165
+
166
+ ## 🛠️ 本地开发与源码运行
167
+
168
+ ```bash
169
+ git clone git@github.com:sexylin/hipowork-cli.git
170
+ cd hipowork-cli
171
+
172
+ python3 -m venv .venv
173
+ .venv/bin/pip install -e .[resume]
174
+
175
+ # 运行完整单元测试套件
176
+ .venv/bin/python -m unittest discover -s tests
177
+ ```
178
+
179
+ ---
180
+
181
+ ## 📄 License
182
+
183
+ 本项目基于 [MIT License](LICENSE) 开源。
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "hipowork-cli"
7
- version = "0.2.0"
7
+ version = "0.3.2"
8
8
  description = "HiPo Work CLI — Agent 友好的招聘平台命令行工具集(OAuth 授权 / 岗位发布 / 候选人匹配 / 简历导入)"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -41,6 +41,7 @@ Documentation = "https://hipowork.com"
41
41
 
42
42
  [project.scripts]
43
43
  hipo = "hipowork_cli:main"
44
+ hipowork-cli = "hipowork_cli:main"
44
45
 
45
46
  [tool.setuptools]
46
47
  package-dir = { "" = "src" }
@@ -15,12 +15,13 @@ import subprocess
15
15
  import sys
16
16
  from pathlib import Path
17
17
 
18
- __version__ = "0.2.0"
18
+ __version__ = "0.3.2"
19
19
 
20
20
  SCRIPTS_DIR = Path(__file__).resolve().parent / "scripts"
21
21
 
22
22
  # 命令名 → 对应脚本文件(不含 .py)
23
23
  COMMANDS = {
24
+ "login": "hipo_authorize",
24
25
  "authorize": "hipo_authorize",
25
26
  "status": "hipo_token_status",
26
27
  "refresh": "hipo_token_refresh",
@@ -42,7 +43,8 @@ COMMANDS = {
42
43
 
43
44
  # 各命令的一句话说明(help 输出用)
44
45
  HELP = {
45
- "authorize": "OAuth 授权(打开浏览器完成邮箱验证码登录)",
46
+ "login": "登录/授权(在终端提供链接并在浏览器完成邮箱验证)",
47
+ "authorize": "OAuth 授权(login 的别名)",
46
48
  "status": "查看 token 状态(角色/scope/过期)",
47
49
  "refresh": "强制刷新 token",
48
50
  "token-sync": "导出 token 到浏览器 localStorage(4 个 base64)",
@@ -72,7 +74,7 @@ def _print_help() -> None:
72
74
  print("HiPo Work CLI — 统一入口")
73
75
  print("用法: hipo <command> [args...]\n")
74
76
  print("认证与令牌:")
75
- for k in ("authorize", "status", "refresh", "token-sync", "accounts"):
77
+ for k in ("login", "authorize", "status", "refresh", "token-sync", "accounts"):
76
78
  print(f" {k:<16} {HELP[k]}")
77
79
  print("\n招聘方:")
78
80
  for k in ("publish-job", "close-job", "search", "match-candidates", "market", "stats"):
@@ -0,0 +1,5 @@
1
+ from hipowork_cli import main
2
+ import sys
3
+
4
+ if __name__ == "__main__":
5
+ sys.exit(main())
@@ -117,34 +117,35 @@ class CallbackServer:
117
117
 
118
118
 
119
119
  async def redirect_handler(url: str) -> None:
120
- print("\n=== 请在浏览器完成授权(邮箱验证码登录)===")
121
- print("授权 URL:")
122
- print(url)
123
- print()
120
+ print("\nTo authenticate, please:")
121
+ print(f"1. Go to: {url}")
122
+ print("\n2. Complete email verification and authorize in the browser.")
123
+ print("3. Waiting for authentication callback...\n")
124
124
  try:
125
125
  webbrowser.open(url)
126
- print("(已尝试自动打开浏览器;若未打开请手动复制上面的 URL)")
126
+ print("(Attempting to automatically open the browser; if it doesn't open, copy and paste the URL above.)")
127
127
  except Exception:
128
128
  pass
129
129
 
130
130
 
131
131
  async def run(port: int, role: str, email: str) -> int:
132
+ import httpx2
132
133
  from mcp import ClientSession
133
134
  from mcp.client.auth import OAuthClientProvider
134
- from mcp.client.streamable_http import streamablehttp_client
135
- from mcp.shared.auth import OAuthClientMetadata
135
+ from mcp.client.streamable_http import streamable_http_client, create_mcp_http_client
136
+ from mcp.shared.auth import OAuthClientMetadata, AuthorizationCodeResult
136
137
 
137
138
  cb = CallbackServer(port, role)
138
139
  cb.start()
139
140
 
140
- async def callback_handler() -> tuple[str, str | None]:
141
+ async def callback_handler() -> AuthorizationCodeResult:
141
142
  print("\n等待浏览器授权回调...")
142
143
  await asyncio.to_thread(cb.received.wait, 600)
143
144
  code, state = cb.code, cb.state
144
145
  if not code:
145
146
  raise RuntimeError("回调未收到授权码(可能超时或用户取消)")
146
147
  print(f"收到回调 code={code[:12]}... state={state[:12]}...")
147
- return code, state
148
+ return AuthorizationCodeResult(code=code, state=state)
148
149
 
149
150
  metadata = OAuthClientMetadata(
150
151
  client_name="hipowork-cli",
@@ -162,32 +163,71 @@ async def run(port: int, role: str, email: str) -> int:
162
163
  storage=_StorageAdapter(store),
163
164
  redirect_handler=redirect_handler,
164
165
  callback_handler=callback_handler,
165
- timeout=600,
166
166
  )
167
167
 
168
168
  print(f"连接 {DEFAULT_MCP_URL} ...")
169
169
  try:
170
- async with streamablehttp_client(DEFAULT_MCP_URL, timeout=30, auth=oauth) as (read, write, _sid):
171
- async with ClientSession(read, write) as session:
172
- init = await session.initialize()
173
- print("\nMCP INIT OK")
174
- print(" server:", init.serverInfo.name, init.serverInfo.version)
175
- tools = await session.list_tools()
176
- print(f"\nTOOLS ({len(tools.tools)}):")
177
- for t in tools.tools:
178
- first = (t.description or "").splitlines()[0]
179
- print(f" - {t.name}: {first}")
180
-
181
- # token 已在 storage 落盘;补记 email/role 到账户信息
182
- acc = store.get_account()
183
- if acc is not None:
184
- if email:
185
- acc["email"] = email
186
- acc["role"] = role
187
- store.set_account(store.default_account(), acc)
188
- print("\n✅ 授权完成,token 已保存到本地仓库。")
189
- print(" 后续可用 hipo_token_status.py / hipo_token_sync.py / hipo_mcp_client.py 复用。")
190
- return 0
170
+ http_client = create_mcp_http_client(auth=oauth, timeout=httpx2.Timeout(30.0, read=600.0))
171
+ async with http_client:
172
+ async with streamable_http_client(DEFAULT_MCP_URL, http_client=http_client) as (read, write):
173
+ async with ClientSession(read, write) as session:
174
+ init = await session.initialize()
175
+ print("\nMCP INIT OK")
176
+ print(" server:", init.server_info.name, init.server_info.version)
177
+ tools = await session.list_tools()
178
+ print(f"\nTOOLS ({len(tools.tools)}):")
179
+ for t in tools.tools:
180
+ first = (t.description or "").splitlines()[0]
181
+ print(f" - {t.name}: {first}")
182
+
183
+ # token 已在 storage 落盘;补记 email/role 到账户信息。
184
+ # P1-12: 角色以服务端 /auth/me 返回的真实角色为准(本地 --role
185
+ # 只是授权页初选,服务端可能因角色选择页/已有档案而不同)。
186
+ acc = store.get_account()
187
+ if acc is not None:
188
+ if email:
189
+ acc["email"] = email
190
+ try:
191
+ from hipo_auth import api_request, DEFAULT_API_BASE
192
+ me = api_request("GET", "/auth/me", token=store.tokens().get("access_token"), api_base=DEFAULT_API_BASE)
193
+ server_role = str(me.get("role") or "").strip()
194
+ if server_role:
195
+ acc["role"] = server_role
196
+ if me.get("email"):
197
+ acc["email"] = me["email"]
198
+ except Exception as exc: # noqa: BLE001
199
+ # /auth/me 不可用时回退到本地角色(降级但不阻塞授权完成)
200
+ print(f" ⚠️ 读取服务端角色失败,回退本地角色: {type(exc).__name__}: {str(exc)[:200]}")
201
+ acc["role"] = role
202
+ store.set_account(store.default_account(), acc)
203
+
204
+ # CLI/MCP 授权成功 → 桥接 Web 登录态:自动打开 /oauth/handoff。
205
+ # 方案A:payload 只传 access_token + client_id,不传 refresh_token。
206
+ # CLI 的 refresh 是旋转式一次性凭证(任一端刷新都会作废旧值),
207
+ # 与浏览器共享同一根 refresh 会在下一次刷新时互相作废(does not
208
+ # exist)。因此这里给浏览器的是"限时浏览会话":access 过期后前端
209
+ # 不再自动刷新,引导走标准 PKCE 拿 Web 自己的链。
210
+ try:
211
+ import base64 as _b64
212
+ toks = store.tokens()
213
+ cinfo = store.client_info()
214
+ if toks.get("access_token") and cinfo.get("client_id"):
215
+ payload_json = json.dumps({
216
+ "access_token": toks["access_token"],
217
+ "client_id": cinfo["client_id"],
218
+ "expires_in": toks.get("expires_in") or 900,
219
+ }).encode()
220
+ # base64url(无填充,与前端 atob 前补 '=' 的逻辑匹配)
221
+ payload_b64 = _b64.urlsafe_b64encode(payload_json).rstrip(b"=").decode()
222
+ handoff_url = f"https://www.hipowork.com/oauth/handoff#payload={payload_b64}"
223
+ webbrowser.open(handoff_url)
224
+ print("\n🌐 已在浏览器打开 HiPo Work Web 登录态并跳转到个人中心(限时会话,access 过期后引导重新登录)。")
225
+ except Exception as exc: # noqa: BLE001
226
+ print(f" ⚠️ 打开 Web 登录态失败(不影响 CLI 授权):{type(exc).__name__}: {str(exc)[:200]}")
227
+
228
+ print("\n✅ 授权完成,token 已保存到本地仓库。")
229
+ print(" 后续可用 hipo_token_status.py / hipo_token_sync.py / hipo_mcp_client.py 复用。")
230
+ return 0
191
231
  except Exception as exc:
192
232
  print(f"授权失败: {type(exc).__name__}: {str(exc)[:800]}")
193
233
  return 1