phocinae-cli 0.1.0__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.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 phocinae CLI contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,276 @@
1
+ Metadata-Version: 2.4
2
+ Name: phocinae-cli
3
+ Version: 0.1.0
4
+ Summary: 斑海豹 Phocinae CLI — 一行命令本地决策(phocinae-server /v1/systemone 客户端,含 fail-closed 命令审批门)
5
+ Author: Phocinae
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/Phocinae/phocinae-cli
8
+ Project-URL: Repository, https://github.com/Phocinae/phocinae-cli
9
+ Project-URL: Bug Tracker, https://github.com/Phocinae/phocinae-cli/issues
10
+ Project-URL: Model card, https://huggingface.co/Phocinae/Phocinae-Largha-150M-v1
11
+ Project-URL: Server, https://github.com/Phocinae/phocinae-server
12
+ Project-URL: Guard, https://github.com/Phocinae/phocinae-guard
13
+ Keywords: decision-model,system-one,phocinae,typed-decisions,local-inference,cli
14
+ Classifier: Development Status :: 4 - Beta
15
+ Classifier: Environment :: Console
16
+ Classifier: Intended Audience :: Developers
17
+ Classifier: Natural Language :: Chinese (Simplified)
18
+ Classifier: Natural Language :: English
19
+ Classifier: Operating System :: OS Independent
20
+ Classifier: Programming Language :: Python :: 3
21
+ Classifier: Programming Language :: Python :: 3.9
22
+ Classifier: Programming Language :: Python :: 3.10
23
+ Classifier: Programming Language :: Python :: 3.11
24
+ Classifier: Programming Language :: Python :: 3.12
25
+ Classifier: Programming Language :: Python :: 3.13
26
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
27
+ Classifier: Topic :: Utilities
28
+ Requires-Python: >=3.9
29
+ Description-Content-Type: text/markdown
30
+ License-File: LICENSE
31
+ Requires-Dist: typer>=0.9
32
+ Requires-Dist: rich>=13
33
+ Requires-Dist: httpx>=0.24
34
+ Provides-Extra: dev
35
+ Requires-Dist: build>=1.2; extra == "dev"
36
+ Requires-Dist: twine>=5; extra == "dev"
37
+ Dynamic: license-file
38
+
39
+ # phocinae CLI
40
+
41
+ 斑海豹(Phocinae)生态的命令行工具:**一行命令本地决策**。
42
+ 对接本机 [phocinae-server](https://github.com/Phocinae/phocinae-server)
43
+ (默认 `http://127.0.0.1:8155`)的 TypeSafe System One 决策协议
44
+ (`POST /v1/systemone`),面向 144.3M 本地 typed decision 模型
45
+ `Phocinae-Largha-150M-v1`。所有推理都在本机完成,不上云。
46
+
47
+ - **子命令**:`decide` / `classify` / `route` / `score` / `gate` / `ping`
48
+ - **技术栈**:Python ≥ 3.8 + [typer](https://typer.tiangolo.com/)(CLI)+
49
+ [rich](https://rich.readthedocs.io/)(表格/着色)+
50
+ [httpx](https://www.python-httpx.org/)(重试/超时/错误分类)
51
+ - **单文件零依赖版**:`phocinae.py`(argparse + urllib,
52
+ 纯标准库,功能子集 decide / ping / gate)
53
+ - **退出码**:`0` 成功(gate: allow)· `1` 错误 · `2` gate deny · `3` gate ask
54
+
55
+ ## 安装
56
+
57
+ ```bash
58
+ pip install phocinae-cli # 从 PyPI 安装(提供 phocinae 命令)
59
+ phocinae --version # phocinae CLI 0.1.0
60
+ ```
61
+
62
+ 或从源码装(开发用):
63
+
64
+ ```bash
65
+ git clone https://github.com/Phocinae/phocinae-cli
66
+ cd phocinae-cli && pip install -e .
67
+ ```
68
+
69
+ 单文件版无需安装(纯标准库,Python ≥ 3.8 即可):
70
+
71
+ ```bash
72
+ python3 phocinae.py --help
73
+ ```
74
+
75
+ ### 前置:启动 phocinae-server
76
+
77
+ ```bash
78
+ # 官方包方式(默认端口 8155,仅监听 127.0.0.1)
79
+ pip install phocinae-server && bash <其 run_server.sh>
80
+ # 或源码方式
81
+ PHOC_MODEL_DIR=<hf_repo 路径> python -m phocinae.main --host 127.0.0.1 --port 8155
82
+ ```
83
+
84
+ ## 快速上手(三命令)
85
+
86
+ ```bash
87
+ # 1. 服务健康检查
88
+ phocinae ping
89
+
90
+ # 2. 一行命令本地决策:state + 三题型
91
+ phocinae decide --state "The agent restarted nginx after checking the logs." \
92
+ --noul ok:0.65 --choice act:allow,ask,deny --score risk
93
+
94
+ # 3. 命令审批门(shell hook / 包装器友好:退出码即判定)
95
+ phocinae gate --command "git status" # exit 0(L0 白名单)
96
+ phocinae gate --command "rm -rf /" # exit 2(L0 黑名单)
97
+ ```
98
+
99
+ ## 子命令说明
100
+
101
+ ### decide —— state + questions → answers
102
+
103
+ 题目 DSL(可重复、可混用;协议约束在客户端前置校验):
104
+
105
+ | 参数 | 语法 | 说明 |
106
+ |---|---|---|
107
+ | `--noul ID[:T]` | `ok` / `ok:0.65` | 是非题(threshold ∈ [0,1],默认 0.5) |
108
+ | `--choice ID:o1,o2` | `act:allow,ask,deny` | 单选题(选项逗号分隔,1–255 个) |
109
+ | `--score ID` | `risk` | 评分题(答案 2–10) |
110
+ | `--questions-json` | 内联 JSON 数组 / 文件路径 | 完整规格(可带 instructions/criteria 等扩展键) |
111
+
112
+ ```bash
113
+ phocinae decide --state "..." --noul ok --choice act:allow,ask,deny --score risk
114
+ phocinae --json decide --state "..." --noul ok # 原始 JSON(全局选项在子命令前)
115
+ phocinae decide --state "..." --choice act:a,b,c --perm # 4 排列平均(/permute)
116
+ phocinae decide --state "..." --verbose # 附每题完整选项概率
117
+ ```
118
+
119
+ **管道模式**:不带 `--state` 且 stdin 被管道时,从 stdin 读 state
120
+ (`--state -` 强制从 stdin 读)。
121
+
122
+ ```bash
123
+ echo "The service is down and users are reporting errors." \
124
+ | phocinae decide --noul ok --choice act:allow,ask,deny
125
+ ```
126
+
127
+ **批量模式**:`--batch` 读 stdin 每行一条 state(JSON 对象行取 `state` 键),
128
+ 经 `POST /v1/systemone/batch` 提交,自动按 64 条分片。
129
+
130
+ ```bash
131
+ printf 'state one\nstate two\n{"state": "state three"}\n' \
132
+ | phocinae decide --batch --noul ok --choice act:x,y
133
+ ```
134
+
135
+ ### classify —— state + labels → 单选标签
136
+
137
+ ```bash
138
+ phocinae classify --state "Customer says the account was hacked." \
139
+ --labels allow,ask,deny
140
+ ```
141
+
142
+ 输出:选中标签 + 标定置信度 + 各标签概率 + escalate 提示
143
+ (E1 升级门 τ=0.6:置信度低于 τ 建议升级外部模型)。
144
+
145
+ ### route —— state + 工具列表 → 工具选择
146
+
147
+ canonical 口径(与 phocinae-router 一致):`name` 或 `name:描述`(逗号分隔,
148
+ ≤10 个,JevBench tool_selection 域界),默认走 4 排列平均抑制顺序翻转。
149
+
150
+ ```bash
151
+ phocinae route --state "User asks for the current weather in Paris." \
152
+ --tools "web_search:搜索公开网络,read_file:读取本地文件"
153
+ ```
154
+
155
+ ### score —— state + criteria → 2–10 分
156
+
157
+ ```bash
158
+ phocinae score --state "The agent will delete production tables." \
159
+ --criteria "评估该操作的破坏性风险"
160
+ ```
161
+
162
+ 输出:分值(2–10)+ 各档标定概率 + 置信度。criteria 随题面发送
163
+ (question 的 instructions 扩展键,服务端渲染进提示)。
164
+
165
+ ### gate —— 命令审批门(allow / deny / ask + fail-closed)
166
+
167
+ 与 [phocinae-guard](https://github.com/Phocinae/phocinae-guard) 同口径的
168
+ 三层判定,面向 shell hook / 包装器集成:
169
+
170
+ ```
171
+ L0 纯离线确定性表(白名单精确 + 前缀 + 黑名单正则)→ allow / deny
172
+ L1(--l1) L0 不能定夺时 POST /v1/systemone 两问(noul 放行 + score 风险
173
+ 2–10)→ 阈值映射(noul≥0.65 放行;score≥7 deny,≥4 ask)
174
+ fail-closed 服务不可用 → 除白名单外一律 --fail-closed(默认 deny)
175
+ ```
176
+
177
+ ```bash
178
+ phocinae gate --command "git status" # exit 0
179
+ echo "sudo rm -rf /etc" | phocinae gate --json # 管道 + JSON,exit 2
180
+ phocinae gate --l1 --command "pip install requests" # 灰区交模型(exit 0/2/3)
181
+ phocinae gate --l1 --confirm --command "..." # 人工确认:ask → allow
182
+ phocinae gate --fail-closed ask ... # 服务不可用兜底 ask(exit 3)
183
+ phocinae gate --table my_l0.json ... # 自定义 L0 表(覆盖内置各节)
184
+ ```
185
+
186
+ > ⚠ **P0 口径**(与 guard 一致):150M 权重未做过命令审批域校准,L1 信号 ≈ 噪声,
187
+ > 故默认只走 L0 + fail-closed;`--l1` 显式启用才把灰区交给模型。
188
+
189
+ ### ping —— 健康检查
190
+
191
+ ```bash
192
+ phocinae ping # GET /health + /v1/models,表格展示,exit 0
193
+ phocinae ping --json # JSON
194
+ ```
195
+
196
+ ## 全局选项与环境变量
197
+
198
+ ```
199
+ --server URL 服务基地址(env PHOC_SERVER;默认 http://127.0.0.1:8155)
200
+ --timeout N 总请求超时秒数(默认 30;gate 的 L1 固定 2s,fail-closed 要快)
201
+ --retries N 连接错误/5xx 重试次数(默认 3,指数退避;4xx 不重试)
202
+ --model NAME 模型名(默认 Phocinae-Largha-150M-v1)
203
+ --json 原始 JSON 输出(默认富表格)
204
+ --verbose 显示重试与完整选项概率
205
+ ```
206
+
207
+ 环境变量:`PHOC_SERVER`(服务地址)、`PHOC_BEARER_TOKEN`(服务设了
208
+ Bearer 鉴权时自动携带)。全局选项放子命令之前:`phocinae --json decide ...`。
209
+
210
+ **错误分类**(httpx 客户端):连接拒绝 → 提示启动服务;超时 → 提示加
211
+ `--timeout`;422 → 原样展示服务端校验 detail;响应缺 answers/结构异常 → 明确报错。
212
+ 服务未启动给可行动提示(含启动命令)。
213
+
214
+ ## 退出码约定
215
+
216
+ | 码 | 含义 | 适用 |
217
+ |---|---|---|
218
+ | 0 | 成功 / gate allow | 全部命令 |
219
+ | 1 | 错误(用法/网络/协议/服务端 4xx-5xx) | 全部命令 |
220
+ | 2 | gate deny(含 fail-closed deny) | gate |
221
+ | 3 | gate ask(需人工确认;`--confirm` 可升级 allow) | gate |
222
+
223
+ > 与 phocinae-guard(deny=1 / ask=2)的差异是**有意为之**:本任务口径规定
224
+ > deny=2。集成 shell hook 时请按本表判读。
225
+
226
+ ## 单文件零依赖版 phocinae.py
227
+
228
+ ```bash
229
+ python3 phocinae.py ping --server http://127.0.0.1:8155
230
+ python3 phocinae.py decide --state "..." --noul ok --choice act:a,b --score risk
231
+ echo "text" | python3 phocinae.py decide --noul ok # 管道
232
+ python3 phocinae.py gate --command "rm -rf /" # exit 2
233
+ python3 phocinae.py gate --command "pip install x" --l1 --fail-closed ask
234
+ ```
235
+
236
+ 功能子集:decide / ping / gate。协议、退出码与包版一致;`--json` / `--perm`
237
+ (decide)可用;无批量与 classify/route/score。全局选项(--server/--timeout/
238
+ --retries/--model/--json)放子命令之前。
239
+
240
+ ## 测试
241
+
242
+ ```bash
243
+ bash tests/run_smoke.sh > tests/smoke_output.txt 2>&1 # 全量冒烟
244
+ ```
245
+
246
+ 冒烟测试自起 `tests/mock_server.py`(纯标准库 mock,响应形状与真实服务逐键
247
+ 对齐,md5 播种确定性答案,含 422 校验与 /permute 排列平均),覆盖 6 个子命令、
248
+ 管道/批量/JSON/perm、错误分类与可行动提示、gate L0/L1/fail-closed 全部退出码、
249
+ 单文件版;gate L1 的确定性用例用 `find_gate_case()` 按运行目录搜索命令后缀
250
+ (`mock_server.py --find-gate-case 'git push origin main'` 可复现)。
251
+ 测试输出保存于 `tests/smoke_output.txt`。
252
+
253
+ ## 目录结构
254
+
255
+ ```
256
+ phocinae_cli/
257
+ ├── pyproject.toml # phocinae-cli 0.1.0;console script: phocinae
258
+ ├── README.md
259
+ ├── LICENSE # MIT
260
+ ├── phocinae.py # 单文件零依赖版(decide/ping/gate)
261
+ ├── src/phocinae_cli/
262
+ │ ├── cli.py # typer 主程序 + 全局选项 + ping
263
+ │ ├── client.py # httpx 客户端:重试/超时/错误分类/应答解包
264
+ │ ├── questions.py # 题目 DSL 解析 + 协议前置校验(422 口径)
265
+ │ ├── decide.py # decide(管道/批量/perm)
266
+ │ ├── classify_route.py # classify + route(τ=0.6 escalate)
267
+ │ ├── score_gate_cli.py # score + gate 命令
268
+ │ ├── gate.py # gate 编排:L0 → L1 → fail-closed
269
+ │ ├── l0.py # L0 离线表(移植自 phocinae-guard 内置默认表)
270
+ │ ├── router_const.py # 工具路由冻结口径(τ/菜单上限/perm K)
271
+ │ └── output.py # rich 表格/JSON + 退出码
272
+ └── tests/
273
+ ├── mock_server.py # 冒烟 mock(确定性,含 find_gate_case)
274
+ ├── run_smoke.sh # 冒烟驱动脚本
275
+ └── smoke_output.txt # 测试输出证据
276
+ ```
@@ -0,0 +1,238 @@
1
+ # phocinae CLI
2
+
3
+ 斑海豹(Phocinae)生态的命令行工具:**一行命令本地决策**。
4
+ 对接本机 [phocinae-server](https://github.com/Phocinae/phocinae-server)
5
+ (默认 `http://127.0.0.1:8155`)的 TypeSafe System One 决策协议
6
+ (`POST /v1/systemone`),面向 144.3M 本地 typed decision 模型
7
+ `Phocinae-Largha-150M-v1`。所有推理都在本机完成,不上云。
8
+
9
+ - **子命令**:`decide` / `classify` / `route` / `score` / `gate` / `ping`
10
+ - **技术栈**:Python ≥ 3.8 + [typer](https://typer.tiangolo.com/)(CLI)+
11
+ [rich](https://rich.readthedocs.io/)(表格/着色)+
12
+ [httpx](https://www.python-httpx.org/)(重试/超时/错误分类)
13
+ - **单文件零依赖版**:`phocinae.py`(argparse + urllib,
14
+ 纯标准库,功能子集 decide / ping / gate)
15
+ - **退出码**:`0` 成功(gate: allow)· `1` 错误 · `2` gate deny · `3` gate ask
16
+
17
+ ## 安装
18
+
19
+ ```bash
20
+ pip install phocinae-cli # 从 PyPI 安装(提供 phocinae 命令)
21
+ phocinae --version # phocinae CLI 0.1.0
22
+ ```
23
+
24
+ 或从源码装(开发用):
25
+
26
+ ```bash
27
+ git clone https://github.com/Phocinae/phocinae-cli
28
+ cd phocinae-cli && pip install -e .
29
+ ```
30
+
31
+ 单文件版无需安装(纯标准库,Python ≥ 3.8 即可):
32
+
33
+ ```bash
34
+ python3 phocinae.py --help
35
+ ```
36
+
37
+ ### 前置:启动 phocinae-server
38
+
39
+ ```bash
40
+ # 官方包方式(默认端口 8155,仅监听 127.0.0.1)
41
+ pip install phocinae-server && bash <其 run_server.sh>
42
+ # 或源码方式
43
+ PHOC_MODEL_DIR=<hf_repo 路径> python -m phocinae.main --host 127.0.0.1 --port 8155
44
+ ```
45
+
46
+ ## 快速上手(三命令)
47
+
48
+ ```bash
49
+ # 1. 服务健康检查
50
+ phocinae ping
51
+
52
+ # 2. 一行命令本地决策:state + 三题型
53
+ phocinae decide --state "The agent restarted nginx after checking the logs." \
54
+ --noul ok:0.65 --choice act:allow,ask,deny --score risk
55
+
56
+ # 3. 命令审批门(shell hook / 包装器友好:退出码即判定)
57
+ phocinae gate --command "git status" # exit 0(L0 白名单)
58
+ phocinae gate --command "rm -rf /" # exit 2(L0 黑名单)
59
+ ```
60
+
61
+ ## 子命令说明
62
+
63
+ ### decide —— state + questions → answers
64
+
65
+ 题目 DSL(可重复、可混用;协议约束在客户端前置校验):
66
+
67
+ | 参数 | 语法 | 说明 |
68
+ |---|---|---|
69
+ | `--noul ID[:T]` | `ok` / `ok:0.65` | 是非题(threshold ∈ [0,1],默认 0.5) |
70
+ | `--choice ID:o1,o2` | `act:allow,ask,deny` | 单选题(选项逗号分隔,1–255 个) |
71
+ | `--score ID` | `risk` | 评分题(答案 2–10) |
72
+ | `--questions-json` | 内联 JSON 数组 / 文件路径 | 完整规格(可带 instructions/criteria 等扩展键) |
73
+
74
+ ```bash
75
+ phocinae decide --state "..." --noul ok --choice act:allow,ask,deny --score risk
76
+ phocinae --json decide --state "..." --noul ok # 原始 JSON(全局选项在子命令前)
77
+ phocinae decide --state "..." --choice act:a,b,c --perm # 4 排列平均(/permute)
78
+ phocinae decide --state "..." --verbose # 附每题完整选项概率
79
+ ```
80
+
81
+ **管道模式**:不带 `--state` 且 stdin 被管道时,从 stdin 读 state
82
+ (`--state -` 强制从 stdin 读)。
83
+
84
+ ```bash
85
+ echo "The service is down and users are reporting errors." \
86
+ | phocinae decide --noul ok --choice act:allow,ask,deny
87
+ ```
88
+
89
+ **批量模式**:`--batch` 读 stdin 每行一条 state(JSON 对象行取 `state` 键),
90
+ 经 `POST /v1/systemone/batch` 提交,自动按 64 条分片。
91
+
92
+ ```bash
93
+ printf 'state one\nstate two\n{"state": "state three"}\n' \
94
+ | phocinae decide --batch --noul ok --choice act:x,y
95
+ ```
96
+
97
+ ### classify —— state + labels → 单选标签
98
+
99
+ ```bash
100
+ phocinae classify --state "Customer says the account was hacked." \
101
+ --labels allow,ask,deny
102
+ ```
103
+
104
+ 输出:选中标签 + 标定置信度 + 各标签概率 + escalate 提示
105
+ (E1 升级门 τ=0.6:置信度低于 τ 建议升级外部模型)。
106
+
107
+ ### route —— state + 工具列表 → 工具选择
108
+
109
+ canonical 口径(与 phocinae-router 一致):`name` 或 `name:描述`(逗号分隔,
110
+ ≤10 个,JevBench tool_selection 域界),默认走 4 排列平均抑制顺序翻转。
111
+
112
+ ```bash
113
+ phocinae route --state "User asks for the current weather in Paris." \
114
+ --tools "web_search:搜索公开网络,read_file:读取本地文件"
115
+ ```
116
+
117
+ ### score —— state + criteria → 2–10 分
118
+
119
+ ```bash
120
+ phocinae score --state "The agent will delete production tables." \
121
+ --criteria "评估该操作的破坏性风险"
122
+ ```
123
+
124
+ 输出:分值(2–10)+ 各档标定概率 + 置信度。criteria 随题面发送
125
+ (question 的 instructions 扩展键,服务端渲染进提示)。
126
+
127
+ ### gate —— 命令审批门(allow / deny / ask + fail-closed)
128
+
129
+ 与 [phocinae-guard](https://github.com/Phocinae/phocinae-guard) 同口径的
130
+ 三层判定,面向 shell hook / 包装器集成:
131
+
132
+ ```
133
+ L0 纯离线确定性表(白名单精确 + 前缀 + 黑名单正则)→ allow / deny
134
+ L1(--l1) L0 不能定夺时 POST /v1/systemone 两问(noul 放行 + score 风险
135
+ 2–10)→ 阈值映射(noul≥0.65 放行;score≥7 deny,≥4 ask)
136
+ fail-closed 服务不可用 → 除白名单外一律 --fail-closed(默认 deny)
137
+ ```
138
+
139
+ ```bash
140
+ phocinae gate --command "git status" # exit 0
141
+ echo "sudo rm -rf /etc" | phocinae gate --json # 管道 + JSON,exit 2
142
+ phocinae gate --l1 --command "pip install requests" # 灰区交模型(exit 0/2/3)
143
+ phocinae gate --l1 --confirm --command "..." # 人工确认:ask → allow
144
+ phocinae gate --fail-closed ask ... # 服务不可用兜底 ask(exit 3)
145
+ phocinae gate --table my_l0.json ... # 自定义 L0 表(覆盖内置各节)
146
+ ```
147
+
148
+ > ⚠ **P0 口径**(与 guard 一致):150M 权重未做过命令审批域校准,L1 信号 ≈ 噪声,
149
+ > 故默认只走 L0 + fail-closed;`--l1` 显式启用才把灰区交给模型。
150
+
151
+ ### ping —— 健康检查
152
+
153
+ ```bash
154
+ phocinae ping # GET /health + /v1/models,表格展示,exit 0
155
+ phocinae ping --json # JSON
156
+ ```
157
+
158
+ ## 全局选项与环境变量
159
+
160
+ ```
161
+ --server URL 服务基地址(env PHOC_SERVER;默认 http://127.0.0.1:8155)
162
+ --timeout N 总请求超时秒数(默认 30;gate 的 L1 固定 2s,fail-closed 要快)
163
+ --retries N 连接错误/5xx 重试次数(默认 3,指数退避;4xx 不重试)
164
+ --model NAME 模型名(默认 Phocinae-Largha-150M-v1)
165
+ --json 原始 JSON 输出(默认富表格)
166
+ --verbose 显示重试与完整选项概率
167
+ ```
168
+
169
+ 环境变量:`PHOC_SERVER`(服务地址)、`PHOC_BEARER_TOKEN`(服务设了
170
+ Bearer 鉴权时自动携带)。全局选项放子命令之前:`phocinae --json decide ...`。
171
+
172
+ **错误分类**(httpx 客户端):连接拒绝 → 提示启动服务;超时 → 提示加
173
+ `--timeout`;422 → 原样展示服务端校验 detail;响应缺 answers/结构异常 → 明确报错。
174
+ 服务未启动给可行动提示(含启动命令)。
175
+
176
+ ## 退出码约定
177
+
178
+ | 码 | 含义 | 适用 |
179
+ |---|---|---|
180
+ | 0 | 成功 / gate allow | 全部命令 |
181
+ | 1 | 错误(用法/网络/协议/服务端 4xx-5xx) | 全部命令 |
182
+ | 2 | gate deny(含 fail-closed deny) | gate |
183
+ | 3 | gate ask(需人工确认;`--confirm` 可升级 allow) | gate |
184
+
185
+ > 与 phocinae-guard(deny=1 / ask=2)的差异是**有意为之**:本任务口径规定
186
+ > deny=2。集成 shell hook 时请按本表判读。
187
+
188
+ ## 单文件零依赖版 phocinae.py
189
+
190
+ ```bash
191
+ python3 phocinae.py ping --server http://127.0.0.1:8155
192
+ python3 phocinae.py decide --state "..." --noul ok --choice act:a,b --score risk
193
+ echo "text" | python3 phocinae.py decide --noul ok # 管道
194
+ python3 phocinae.py gate --command "rm -rf /" # exit 2
195
+ python3 phocinae.py gate --command "pip install x" --l1 --fail-closed ask
196
+ ```
197
+
198
+ 功能子集:decide / ping / gate。协议、退出码与包版一致;`--json` / `--perm`
199
+ (decide)可用;无批量与 classify/route/score。全局选项(--server/--timeout/
200
+ --retries/--model/--json)放子命令之前。
201
+
202
+ ## 测试
203
+
204
+ ```bash
205
+ bash tests/run_smoke.sh > tests/smoke_output.txt 2>&1 # 全量冒烟
206
+ ```
207
+
208
+ 冒烟测试自起 `tests/mock_server.py`(纯标准库 mock,响应形状与真实服务逐键
209
+ 对齐,md5 播种确定性答案,含 422 校验与 /permute 排列平均),覆盖 6 个子命令、
210
+ 管道/批量/JSON/perm、错误分类与可行动提示、gate L0/L1/fail-closed 全部退出码、
211
+ 单文件版;gate L1 的确定性用例用 `find_gate_case()` 按运行目录搜索命令后缀
212
+ (`mock_server.py --find-gate-case 'git push origin main'` 可复现)。
213
+ 测试输出保存于 `tests/smoke_output.txt`。
214
+
215
+ ## 目录结构
216
+
217
+ ```
218
+ phocinae_cli/
219
+ ├── pyproject.toml # phocinae-cli 0.1.0;console script: phocinae
220
+ ├── README.md
221
+ ├── LICENSE # MIT
222
+ ├── phocinae.py # 单文件零依赖版(decide/ping/gate)
223
+ ├── src/phocinae_cli/
224
+ │ ├── cli.py # typer 主程序 + 全局选项 + ping
225
+ │ ├── client.py # httpx 客户端:重试/超时/错误分类/应答解包
226
+ │ ├── questions.py # 题目 DSL 解析 + 协议前置校验(422 口径)
227
+ │ ├── decide.py # decide(管道/批量/perm)
228
+ │ ├── classify_route.py # classify + route(τ=0.6 escalate)
229
+ │ ├── score_gate_cli.py # score + gate 命令
230
+ │ ├── gate.py # gate 编排:L0 → L1 → fail-closed
231
+ │ ├── l0.py # L0 离线表(移植自 phocinae-guard 内置默认表)
232
+ │ ├── router_const.py # 工具路由冻结口径(τ/菜单上限/perm K)
233
+ │ └── output.py # rich 表格/JSON + 退出码
234
+ └── tests/
235
+ ├── mock_server.py # 冒烟 mock(确定性,含 find_gate_case)
236
+ ├── run_smoke.sh # 冒烟驱动脚本
237
+ └── smoke_output.txt # 测试输出证据
238
+ ```
@@ -0,0 +1,52 @@
1
+ [build-system]
2
+ requires = ["setuptools>=77"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "phocinae-cli"
7
+ version = "0.1.0"
8
+ description = "斑海豹 Phocinae CLI — 一行命令本地决策(phocinae-server /v1/systemone 客户端,含 fail-closed 命令审批门)"
9
+ readme = "README.md"
10
+ requires-python = ">=3.9"
11
+ license = "MIT"
12
+ license-files = ["LICENSE"]
13
+ authors = [{ name = "Phocinae" }]
14
+ keywords = ["decision-model", "system-one", "phocinae", "typed-decisions", "local-inference", "cli"]
15
+ dependencies = [
16
+ "typer>=0.9",
17
+ "rich>=13",
18
+ "httpx>=0.24",
19
+ ]
20
+ classifiers = [
21
+ "Development Status :: 4 - Beta",
22
+ "Environment :: Console",
23
+ "Intended Audience :: Developers",
24
+ "Natural Language :: Chinese (Simplified)",
25
+ "Natural Language :: English",
26
+ "Operating System :: OS Independent",
27
+ "Programming Language :: Python :: 3",
28
+ "Programming Language :: Python :: 3.9",
29
+ "Programming Language :: Python :: 3.10",
30
+ "Programming Language :: Python :: 3.11",
31
+ "Programming Language :: Python :: 3.12",
32
+ "Programming Language :: Python :: 3.13",
33
+ "Topic :: Software Development :: Libraries :: Python Modules",
34
+ "Topic :: Utilities",
35
+ ]
36
+
37
+ [project.urls]
38
+ Homepage = "https://github.com/Phocinae/phocinae-cli"
39
+ Repository = "https://github.com/Phocinae/phocinae-cli"
40
+ "Bug Tracker" = "https://github.com/Phocinae/phocinae-cli/issues"
41
+ "Model card" = "https://huggingface.co/Phocinae/Phocinae-Largha-150M-v1"
42
+ Server = "https://github.com/Phocinae/phocinae-server"
43
+ Guard = "https://github.com/Phocinae/phocinae-guard"
44
+
45
+ [project.scripts]
46
+ phocinae = "phocinae_cli.__main__:main"
47
+
48
+ [project.optional-dependencies]
49
+ dev = ["build>=1.2", "twine>=5"]
50
+
51
+ [tool.setuptools.packages.find]
52
+ where = ["src"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,10 @@
1
+ """phocinae CLI —— 斑海豹 /v1/systemone 命令行客户端。
2
+
3
+ 一行命令本地决策:decide / classify / route / score / gate / ping。
4
+ 协议:TypeSafe System One API(POST /v1/systemone)。
5
+ """
6
+
7
+ __version__ = "0.1.0"
8
+
9
+ DEFAULT_SERVER = "http://127.0.0.1:8155"
10
+ DEFAULT_MODEL = "Phocinae-Largha-150M-v1"
@@ -0,0 +1,6 @@
1
+ """python -m phocinae_cli 入口。"""
2
+
3
+ from .cli import main
4
+
5
+ if __name__ == "__main__":
6
+ main()