Skip to content
This repository was archived by the owner on Oct 8, 2026. It is now read-only.

Commit 3d9c447

Browse files
rootclaude
andcommitted
release: v1.9.90 Claude Code tool parse fix + package layout
- Fix Claude Code "tool call could not be parsed" on empty/malformed tool schemas - Align stop_reason=tool_use only when tool_use content blocks are emitted - Move business code into grok2api/{admin,pool,protocol,upstream,store} - Keep root + store/* compatibility shims for existing imports/entrypoints - Update README/UPGRADE/Dockerfile/docker-publish for package layout and v1.9.90 Co-Authored-By: Claude <noreply@anthropic.com>
1 parent e6e365f commit 3d9c447

109 files changed

Lines changed: 50443 additions & 49724 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.github/workflows/docker-publish.yml‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ jobs:
4141
id: ver
4242
run: |
4343
set -euo pipefail
44-
V=$(python3 -c 'import re,pathlib; t=pathlib.Path("app.py").read_text(encoding="utf-8"); m=re.search(r"APP_VERSION\s*=\s*\"([^\"]+)\"", t); assert m, "APP_VERSION not found"; print(m.group(1))')
44+
V=$(python3 -c 'import re,pathlib; t=pathlib.Path("grok2api/app.py").read_text(encoding="utf-8"); m=re.search(r"APP_VERSION\s*=\s*\"([^\"]+)\"", t); assert m, "APP_VERSION not found"; print(m.group(1))')
4545
echo "app_version=$V" >> "$GITHUB_OUTPUT"
4646
echo "APP_VERSION=$V"
4747
@@ -53,7 +53,7 @@ jobs:
5353
APP="${{ steps.ver.outputs.app_version }}"
5454
echo "tag=$TAG app=$APP"
5555
if [[ "$TAG" != "$APP" ]]; then
56-
echo "ERROR: git tag v$TAG must equal APP_VERSION $APP in app.py" >&2
56+
echo "ERROR: git tag v$TAG must equal APP_VERSION $APP in grok2api/app.py" >&2
5757
exit 1
5858
fi
5959

‎Dockerfile‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,9 +80,11 @@ COPY . /app
8080
RUN chmod +x /app/entrypoint.sh \
8181
&& mkdir -p /app/turnstile-solver/logs /app/turnstile-solver/keys \
8282
&& test -f /app/grok-build-auth/xconsole_client/client.py \
83-
&& test -f /app/grok_build_adapter.py \
83+
&& test -f /app/grok2api/app.py \
84+
&& test -f /app/grok2api/upstream/grok_build_adapter.py \
85+
&& test -f /app/app.py \
8486
&& test -f /app/turnstile-solver/api_solver.py \
85-
&& python -c "import grok_build_adapter, app; print('build-check', app.APP_VERSION, grok_build_adapter.ADAPTER_BUILD)"
87+
&& python -c "import app; import grok2api.app as pkg_app; from grok2api.upstream import grok_build_adapter; print('build-check', pkg_app.APP_VERSION, grok_build_adapter.ADAPTER_BUILD, app.APP_VERSION)"
8688

8789
EXPOSE 3000 5072
8890

‎README.md‎

Lines changed: 61 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,14 @@
22

33
把 **Grok OIDC 登录态** 转成 **OpenAI / Anthropic 兼容 API**,并附带 Web 管理台:多 API Key、多账号轮询、设备码 / SSO / JSON 导入导出、协议注册。
44

5-
**当前版本:v1.9.89** · 使用明细展示思考强度 · Token 过期移出轮询 · SSO 续期自愈
5+
**当前版本:v1.9.90** · 修复 Claude Code tool call could not be parsed · 空 schema 工具补 `{}` · stop_reason 对齐
66

77
[![GHCR](https://img.shields.io/badge/ghcr.io-hm2899%2Fgrokcli--2api-blue)](https://github.com/users/HM2899/packages/container/package/grokcli-2api)
88
[![Release](https://img.shields.io/github/v/release/HM2899/grokcli-2api?display_name=tag)](https://github.com/HM2899/grokcli-2api/releases)
99

1010
| 镜像(全小写) | 说明 |
1111
|----------------|------|
12-
| `ghcr.io/hm2899/grokcli-2api:1.9.89` | 当前版本 |
12+
| `ghcr.io/hm2899/grokcli-2api:1.9.90` | 当前版本 |
1313
| `ghcr.io/hm2899/grokcli-2api:latest` | 最近 `v*` tag |
1414
| `ghcr.io/hm2899/grokcli-2api:edge` | `main` 最新 |
1515

@@ -68,17 +68,18 @@
6868

6969
---
7070

71-
## 本版本重点(v1.9.89)
71+
## 本版本重点(v1.9.90)
7272

7373
| 能力 | 行为 |
7474
|------|------|
75-
| **使用明细 · 思考强度** | 管理台「使用明细」新增「思考强度」列:`low` / `medium` / `high` / `xhigh` |
76-
| **协议覆盖** | OpenAI `reasoning_effort` · Anthropic `thinking` / `budget_tokens` · Responses `reasoning.effort` |
77-
| **落库** | 写入 usage event `detail.reasoning_effort`(兼容 `thinking_intensity`);列表接口透出 |
78-
| **预算映射** | Anthropic `budget_tokens` 与上游一致:≤4k low · ≤16k medium · ≤48k high · 更大 xhigh |
79-
| **详情** | 点击行可在完整明细中看到 `reasoning_effort` / `thinking_intensity` |
75+
| **Claude Code tool 解析** | 修复 `The model's tool call could not be parsed (retry also failed)` |
76+
| **stop_reason 对齐** | 仅在实际发出 `tool_use` 内容块时返回 `stop_reason=tool_use` |
77+
| **空 schema 工具** | EnterPlanMode / TaskList / ExitPlanMode 等无参数工具补 `input: {}` |
78+
| **不完整参数** | 丢弃残缺 tool arguments,不再下发 `{"_raw":...}` 触发 malformed |
79+
| **流式/非流式一致** | `AnthropicStreamAssembler.finish` 与 `openai_completion_to_anthropic` 同一规则 |
80+
| **包结构重构** | 业务代码迁入 `grok2api/{admin,pool,protocol,upstream,store}`;根目录 / `store/*` 保留兼容 shim |
8081

81-
继承 v1.9.87:Token 过期移出轮询 · 连续续期失败 SSO 自愈 · 首页按账号状态统计。
82+
继承 v1.9.89:使用明细思考强度英文标签 · Token 过期移出轮询 · SSO 续期自愈。
8283

8384
---
8485

@@ -128,7 +129,7 @@ TURNSTILE_THREAD=3 GROK2API_REG_CONCURRENCY=3 docker compose up -d --build
128129

129130
> 2 核小机器建议 `TURNSTILE_THREAD=1~2`;`3` 已较重,`5` 容易把 CPU/内存打满。
130131
131-
**默认只映射应用端口 `3000`(内联部署)。**
132+
**默认只映射应用端口 `3000`(内联部署)。**
132133
栈内 **PostgreSQL / Redis / 本地过盾** 都不绑定宿主机端口:
133134

134135
| 服务 | 容器内地址 | 是否映射到宿主机 |
@@ -145,7 +146,7 @@ REDIS_URL=redis://redis:6379/0
145146
DATABASE_URL=postgresql://grok2api:grok2api@postgres:5432/grok2api
146147
```
147148

148-
> `.env.example` 中的 `127.0.0.1` 仅适用于「本机直接跑 Python、自己起 DB」的场景。
149+
> `.env.example` 中的 `127.0.0.1` 仅适用于「本机直接跑 Python、自己起 DB」的场景。
149150
> `docker compose` 启动时会用 `docker-compose.yml` 中的服务名覆盖,无需改成宿主机端口。
150151
151152
若你**确实**需要从宿主机连库调试,可在本地 `docker-compose.override.yml` 临时加 `ports`(该文件已 gitignore,勿提交)。
@@ -158,11 +159,11 @@ Docker / GHCR **镜像名必须全小写**。仓库 owner 可能是 `HM2899`,
158159
ghcr.io/hm2899/grokcli-2api
159160
```
160161

161-
**错误示例(会拉失败):** `ghcr.io/HM2899/grokcli-2api`
162+
**错误示例(会拉失败):** `ghcr.io/HM2899/grokcli-2api`
162163
**正确示例:**
163164

164165
```bash
165-
docker pull ghcr.io/hm2899/grokcli-2api:1.9.89
166+
docker pull ghcr.io/hm2899/grokcli-2api:1.9.90
166167
# 或
167168
docker pull ghcr.io/hm2899/grokcli-2api:latest
168169
```
@@ -201,7 +202,7 @@ services:
201202
retries: 10
202203

203204
grokcli-2api:
204-
image: ghcr.io/hm2899/grokcli-2api:1.9.89
205+
image: ghcr.io/hm2899/grokcli-2api:1.9.90
205206
ports:
206207
# 只映射应用;不要给 postgres/redis 加 ports
207208
- "3000:3000"
@@ -290,7 +291,7 @@ echo "$GITHUB_TOKEN" | docker login ghcr.io -u YOUR_GITHUB_USERNAME --password-s
290291
管理台 **用量** 页会汇总:
291292

292293
- **token 命中率** = `Σ cache_read_tokens / Σ prompt_tokens`
293-
- **请求命中率** = 成功且 `cache_read_tokens > 0` 的请求占比
294+
- **请求命中率** = 成功且 `cache_read_tokens > 0` 的请求占比
294295
数据来自 `usage_events`(不是日汇总表),今日 / 近 N 天 / 累计三档。
295296

296297
历史压缩(`GROK2API_HISTORY_COMPACT=1`)开启时,默认 `GROK2API_HISTORY_PREFIX_STABLE=1`:旧 tool 结果用 **确定性 placeholder**(含内容 hash),后续轮次不再反复改写已压缩前缀,避免打断 prefix cache。
@@ -338,13 +339,13 @@ docker compose up -d redis postgres
338339
docker compose run --rm \
339340
-e DATABASE_URL=postgresql://grok2api:grok2api@postgres:5432/grok2api \
340341
grokcli-2api \
341-
python migrate_json_to_pg.py --data-dir /app/data --merge-pool
342+
python scripts/migrate_json_to_pg.py --data-dir /app/data --merge-pool
342343
```
343344

344-
迁移内容:`auth.json` / `keys.json` / `settings.json`(含账号池状态)→ PostgreSQL。
345+
迁移内容:`auth.json` / `keys.json` / `settings.json`(含账号池状态)→ PostgreSQL。
345346
不迁移:Redis 热状态、管理台登录会话。
346347

347-
已是 hybrid 时,拉新镜像即可;表结构由 `store/pg.py` 启动时幂等升级。
348+
已是 hybrid 时,拉新镜像即可;表结构由 `grok2api/store/pg.py` 启动时幂等升级。
348349

349350
---
350351

@@ -418,12 +419,12 @@ API:
418419

419420
### 协议注册
420421

421-
依赖 **临时邮箱** + **过盾**(环境变量或管理台配置,存 PG):
422-
- 邮箱:`MoeMail` / **YYDS Mail**([vip.215.im](https://vip.215.im/docs))/ **GPTMail**([mail.chatgpt.org.uk](https://mail.chatgpt.org.uk/zh/api/))
423-
- 过盾:本地内联 Turnstile Solver 或 YesCaptcha
422+
依赖 **临时邮箱** + **过盾**(环境变量或管理台配置,存 PG):
423+
- 邮箱:`MoeMail` / **YYDS Mail**([vip.215.im](https://vip.215.im/docs))/ **GPTMail**([mail.chatgpt.org.uk](https://mail.chatgpt.org.uk/zh/api/))
424+
- 过盾:本地内联 Turnstile Solver 或 YesCaptcha
424425

425-
本地过盾默认与主容器同进程(`127.0.0.1:5072`),**无需填写 URL**;选 YesCaptcha 时仅用云端 Key。
426-
邮箱有效期:MoeMail 支持 1 小时 / 1 天 / 3 天 / 永久;YYDS / GPTMail 临时邮箱约 24 小时。
426+
本地过盾默认与主容器同进程(`127.0.0.1:5072`),**无需填写 URL**;选 YesCaptcha 时仅用云端 Key。
427+
邮箱有效期:MoeMail 支持 1 小时 / 1 天 / 3 天 / 永久;YYDS / GPTMail 临时邮箱约 24 小时。
427428
新注册账号入池后默认 **延迟 30s** 再自动测活;可在管理台「测活等待秒」调整,或用环境变量 `GROK2API_REG_PROBE_DELAY_SEC`(`0`=立即测活)。
428429

429430
---
@@ -448,17 +449,17 @@ docker exec grokcli-2api sh -c 'echo TZ=$TZ; date'
448449
### 发布镜像(GHCR)
449450

450451
```bash
451-
# 1) app.py 中 APP_VERSION 必须与 git tag 一致(镜像路径全小写)
452+
# 1) grok2api/app.py 中 APP_VERSION 必须与 git tag 一致(镜像路径全小写)
452453
# 2) 推 main → edge + 版本号;推 v* tag → 额外 latest + GitHub Release
453-
git add -A && git commit -m "release: v1.9.89"
454+
git add -A && git commit -m "release: v1.9.90"
454455
git push origin main
455-
git tag -a v1.9.89 -m "v1.9.89"
456-
git push origin v1.9.89
457-
gh release create v1.9.89 --title "v1.9.89 usage detail effort English labels" --notes-file - <<'EOF'
456+
git tag -a v1.9.90 -m "v1.9.90"
457+
git push origin v1.9.90
458+
gh release create v1.9.90 --title "v1.9.90 Claude Code tool parse + package layout" --notes-file - <<'EOF'
458459
## Highlights
459-
- 使用明细新增思考强度列(low / medium / high / xhigh)
460-
- 记录 OpenAI / Anthropic / Responses 请求的 reasoning_effort
461-
- 兼容 budget_tokens → effort 映射
460+
- 修复 Claude Code `tool call could not be parsed`(空 schema 补 `{}`、stop_reason 对齐、丢弃残缺 tool args)
461+
- 业务代码迁入 `grok2api/` 包;根目录与 `store/*` 保留兼容 shim
462+
- 继承 v1.9.89:使用明细思考强度英文标签
462463
EOF
463464
# 监视构建
464465
gh run list --workflow=docker-publish.yml --limit 3
@@ -467,40 +468,42 @@ gh run list --workflow=docker-publish.yml --limit 3
467468
成功后拉取(**必须小写**):
468469

469470
```bash
470-
docker pull ghcr.io/hm2899/grokcli-2api:1.9.89
471+
docker pull ghcr.io/hm2899/grokcli-2api:1.9.90
471472
docker pull ghcr.io/hm2899/grokcli-2api:latest
472473
```
473474

474-
CI 会把 `github.repository` 强制转成小写后再推送,避免 `HM2899` 大小写导致 `docker pull` 失败。
475+
CI 会把 `github.repository` 强制转成小写后再推送,避免 `HM2899` 大小写导致 `docker pull` 失败。
475476
`docker-publish.yml` 在 tag 推送时还会校验 `v*` 与 `APP_VERSION` 一致。
476477

478+
**不要提交**:`.env`、`data/`、`docker-compose.override.yml`、`docker-rebuild.local.sh`、密钥与本地 SSO 备份。
479+
477480
---
478481

479482
## 目录提示
480483

481484
```
482485
# 运行时入口
483-
app.py / admin_routes.py # API 与管理路由
484-
anthropic_compat.py / openai_responses.py# Claude / Responses 流与终态帧
485-
account_pool.py # 账号轮询 / 冷却踢出 / inflight 负载分散
486-
conversation_affinity.py # 会话粘性 / prompt_cache_key / response 链
487-
model_health.py # 模型探测 / free-usage 识别
488-
settings_store.py # 系统设置热更新
489-
sub2api_client.py # sub2api 登录 / 推送 / 账号容量
490-
history_compact.py # 大上下文压缩 / 出站工具 gap
491-
proxy_pool.py / quota.py # 出站代理池 / 硬配额踢出
492-
task_log.py # 任务日志入口
493-
494-
# 存储
495-
store/ # Redis + PostgreSQL 适配
496-
store/pool_redis.py # RR 游标 / cooldown / inflight
497-
store/affinity_redis.py # 会话粘性 Redis
498-
migrate_json_to_pg.py # JSON → PG
486+
app.py # 兼容启动包装(真实应用在 grok2api/app.py)
487+
grok2api/app.py # FastAPI 应用、OpenAI/Anthropic 路由入口
488+
489+
# 业务包(新代码请从这里 import)
490+
grok2api/admin/ # 管理台路由、API Key、设置、任务日志、用量统计
491+
grok2api/pool/ # 账号池、认证、配额、模型健康、token 维护、会话粘性
492+
grok2api/protocol/ # Claude / Responses / OpenAI 协议兼容与历史压缩
493+
grok2api/upstream/ # Grok 上游、OIDC、sub2api、代理、模型目录
494+
grok2api/store/ # Redis + PostgreSQL 适配(PG 表、Redis 热状态、锁、指标)
495+
496+
# 兼容层(旧导入仍可用)
497+
account_pool.py / admin_routes.py / ... # root shim → grok2api.*
498+
store/ # root store wrapper → grok2api/store
499+
migrate_json_to_pg.py # 兼容包装;推荐 scripts/migrate_json_to_pg.py
500+
sso_to_auth_json.py # 兼容包装;推荐 scripts/sso_to_auth_json.py
499501
500502
# 脚本(见 scripts/README.md)
501503
scripts/build_admin_assets.py # 管理台静态资源打包
502504
scripts/upgrade_from_file_backend.sh # file → hybrid 升级
503-
scripts/_test_*.py # 本地回归(粘性 / 冷却 / 踢出 / 终态帧)
505+
scripts/migrate_json_to_pg.py # JSON → PG 迁移
506+
scripts/_test_*.py # 本地回归(粘性 / 冷却 / 踢出 / tool parse / 终态帧)
504507
505508
# 前端 / 部署
506509
static/ # 管理台前端
@@ -525,7 +528,13 @@ turnstile-solver/ # 本地过盾(内联)
525528

526529
## 版本
527530

528-
- **v1.9.89**(当前)
531+
- **v1.9.90**(当前)
532+
- 修复 Claude Code 报错 `The model's tool call could not be parsed (retry also failed)`
533+
- `stop_reason=tool_use` 仅在实际发出 tool_use 内容块时设置(不再仅因 `finish_reason=tool_calls`)
534+
- 无 required 参数的工具(EnterPlanMode / TaskList / ExitPlanMode 等)空参数补 `input: {}`
535+
- 不完整 tool arguments 不再以 `{"_raw":...}` 下发,避免 Claude Code 判为 malformed
536+
- **包结构**:业务代码迁入 `grok2api/{admin,pool,protocol,upstream,store}`;根目录与 `store/*` 保留兼容 shim
537+
- **v1.9.89**
529538
- **使用明细 · 思考强度**:管理台「使用明细」直接展示英文标签 low / medium / high / xhigh
530539
- 从 OpenAI `reasoning_effort`、Anthropic `thinking`/`budget_tokens`、Responses `reasoning.effort` 提取并写入 usage detail
531540
- 列表接口透出 `reasoning_effort`;点击行可看完整字段
@@ -689,7 +698,7 @@ turnstile-solver/ # 本地过盾(内联)
689698
- **v1.9.45–1.9.38**:YYDS 域名、任务日志、JSON/SSO 进度、内联 hybrid 等
690699
- 更早变更见 [GitHub Releases](https://github.com/HM2899/grokcli-2api/releases)
691700

692-
> 镜像 tag 与 `app.py` 中 `APP_VERSION` 一致(当前 **1.9.82**)。
701+
> 镜像 tag 与 `grok2api/app.py` 中 `APP_VERSION` 一致(当前 **1.9.90**)。
693702
> 拉取路径固定 **`ghcr.io/hm2899/grokcli-2api`**(全小写)。
694703
695704
## License

0 commit comments

Comments
 (0)