Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# shell 脚本强制 LF —— core.autocrlf=true 下防止 checkout 成 CRLF,
# 否则在 Linux/Alpine/WSL 里会 `bad interpreter: /bin/sh^M` 跑不了。
*.sh text eol=lf
*.bash text eol=lf

# Windows 脚本用 CRLF
*.ps1 text eol=crlf
*.bat text eol=crlf
*.cmd text eol=crlf
111 changes: 111 additions & 0 deletions docs/bug_fix/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
# 确定性修复记录(fork 专用)

> 本目录是 **HyperGroups fork 自有记录**,只存在于 fork 仓库的镜像分支(`KongFangXun`,原名 `upstream`,
> 已改名以消除与 remote `upstream` 的歧义),**不向上游提 PR**。向上游贡献时从 `upstream/main`
> 另切干净的 `fix/xxx` 主题分支,只带代码改动,不带本目录。
>
> 与 `issues/`(gitignored,本地审计草稿)的分工:
> - `issues/` —— 原始发现台账,本地保留,不进版本库。
> - `docs/bug_fix/` —— 已确认的**确定性** bug + 复现 + 修复,提交到 fork,按拟提的主题分支分组。

「确定性」= 100% 可复现、与模型能力无关的脚本 bug(区别于 `docs/anti-cases/` 记录的模型行为问题)。

## 工作流

1. 在镜像分支(`KongFangXun`)按自己的方式修问题、记录到本目录、打 tag 标记。
2. 真要回贡上游时,从最新 `upstream/main` 切 `fix/xxx` 主题分支,把对应那一组修复做成**原子提交**。
3. 按作者规矩(CONTRIBUTING.md + PR 模板)走:`verify.sh` 全过 → 部署循环 → 非 OpenClaw 平台测试。
4. 先推到自己 fork(`origin`)的主题分支,再从该分支开 PR 到上游 `KongFangXun:main`。

> **PR 创建方式(实测)**:本机终端到 GitHub 的 HTTPS 被墙、只有 SSH 通;`gh` 用 PAT
> 建 PR 一律被拒(`Resource not accessible by personal access token`,三种 token 都试过,
> 疑账号级限制/邮箱未验证)。**改用浏览器会话开 PR 成功**——`git push`(SSH)推分支,
> 再去上游 Pull requests 页点 "recently pushed branches" 黄条的 *Compare & pull request*。

## 提交状态

| 主题分支 | 覆盖的 bug | 状态 |
|---------|-----------|------|
| `fix/cross-platform-portability` | shasum 回退、stat GNU/BSD | ✅ **已提 [PR #1](https://github.com/KongFangXun/sofagent/pull/1)**(OPEN,待作者 review) |
| `fix/set-e-premature-exit` | set -e 提前退出(3 处) | ⏳ 待提(等 #1 反馈后) |
| `fix/arg-parsing-shift` | verify/uninstall 参数解析 | ⏳ 待提 |
| `fix/numeric-and-unbound-guards` | 除零 / grep -c 双 0 / set -u | ⏳ 待提 |

> 策略:单人维护者,不一次性砸多个 PR。先用 #1(作者点名最缺的跨平台兼容)走通流程、摸清接受口味,再逐个发。

## 拟分组(= 拟提的主题分支)

相对最新 `upstream/main`(含 v0.82)的净改动,按主题归为 4 个主题分支:

### 1. `fix/set-e-premature-exit` — `set -e` 下裸命令提前退出(高)

`task-orchestrate.sh` 在 `set -euo pipefail`(line 69)下,3 处裸 `ao run` 失败即退出,
后续失败处理/重试逻辑全成死代码。

| 位置 | 修复 |
|------|------|
| L3 模板分支 | `EXIT_CODE=0; ao run ... \|\| EXIT_CODE=$?` |
| L4 直接执行 | 同上 |
| 重试循环(上游 v0.73 新增) | 把 `\|\| EXIT_CODE=$?` 并入上游循环,否则重试永不触发 |

**复现**:`ao` 返回非 0 → 脚本立即终止,看不到"重试 N/M"和失败汇总。

### 2. `fix/arg-parsing-shift` — `for arg in "$@"` + `shift` 失效(中)

`for arg` 循环里 `shift` 无效、取 `$2` 拿到的是脚本位置参数而非"下一个 arg",
导致 `--quiet --platform X` 把 PLATFORM 误设为字面量 `--platform`。改用 `while [[ $# -gt 0 ]]` + `shift`。

| 文件 | 备注 |
|------|------|
| `verify.sh` | 同时保留上游新增的 `--quick` |
| `uninstall.sh` | 同类修复 |

**复现**:`bash verify.sh --quiet --platform claude` → 平台探测错误。

### 3. `fix/cross-platform-portability` — BSD/GNU 工具差异(中)✅ 已提 PR #1

作者在 CONTRIBUTING「最需要的技能」里点名的 bash BSD/macOS 兼容性。
> 已作为 [PR #1](https://github.com/KongFangXun/sofagent/pull/1) 提交(+4/-2,2 文件,OPEN)。
> 验证:`bash -n` 通过 + 功能验证(sha256sum 回退出哈希、`stat -c %Y` 取到真实 mtime);
> 部署循环/非 OpenClaw 实测因无安装环境未跑,已在 PR 正文如实标注。

| 位置 | 修复 |
|------|------|
| `task-orchestrate.sh` TASK_SLUG | `shasum` 缺失时回退 `sha256sum`(Alpine/精简 Linux 无 shasum) |
| `verify.sh` think.md 时间 | `stat -c %Y`(GNU)优先 + `stat -f %m`(BSD)回退。原 BSD-only 写法在 GNU/Linux 上 `-f`=`--file-system`、`%m` 被当文件名,**取不到 mtime**,反思频率检查失真 |

**复现**:精简 Linux 容器跑 `task-orchestrate.sh` → TASK_SLUG 恒为 unknown;Linux 跑 `verify.sh` → think.md 反思频率计算错误(实测旧写法在 GNU 上会输出文件系统信息、破坏算术)。

### 4. `fix/numeric-and-unbound-guards` — 数值/未绑定健壮性(低-中)

| 文件 | 修复 |
|------|------|
| `task-record.sh` 预算 | `--limit 0`/非数字在 `$(( ))` 前拦截,防除零崩溃 |
| `task-record.sh` 闭环计数 | 修 `grep -c ... \|\| echo 0` 在 0 匹配时输出 `"0\n0"` |
| `task-orchestrate.sh` 清理 | guard 空 `$SOFAGENT_CONSTRAINT_FILE`,避免 set -u 下 `rm ""` |
| `install.sh` 数据目录 | `SOFAGENT_DATA="${SOFAGENT_DATA:-...}"` 保留外部环境变量覆盖 |

**复现**:`task-record.sh --budget --steps 5 --limit 0` → 除零,set -e 崩脚本。

## 跨平台自检脚本(`tests/`)

把验证固化成可移植脚本,各环境**独立执行**、方便复现与排查:

- **`tests/check-portability.sh`** —— 纯 POSIX sh,可在 Alpine(busybox) / Ubuntu / macOS / MSYS2 直接 `sh` 跑,
验证 PR #1 两处修复在当前平台成立(stat 取 mtime、shasum 缺失回退),退出码 0/1。
- **`tests/run-envs.sh`** —— 本机驱动,把上面的自检丢进 **本机 MSYS2 + WSL Ubuntu + Docker Alpine** 各自独立跑、汇总;
缺哪个环境就跳过哪个,互不影响。

已实测(2026-06):本机 MSYS2(GNU 8.32) 与 WSL Ubuntu 24.04(GNU 9.4) 均 **4/0 通过**,slug 跨平台一致;
旧 `stat -f %m` 在两处 GNU 平台均复现 bug。Docker Alpine(真·无 shasum)待引擎启动后补跑。

## 回归测试

`dev` 分支已有针对前 5 个确定性 bug 的回归用例(A–E,commit `44a0778`)。
提主题分支时一并带上对应用例,满足作者 PR 模板的「verify.sh 全过」要求。

## 不在本目录的改动

- `install.ps1` + `install.sh` 环境检测 —— **功能新增**,不是确定性 bug 修复,不归此处。
按 fork 原则(见 `issues/FORK.md` §1.3)走独立 feature 分支评估。
- `load-chain.sh` 哈希缓存修复 —— 上游 v0.64 已删该文件(hook 替代,无缓存层),修复已无对象。
103 changes: 103 additions & 0 deletions docs/bug_fix/tests/ENVIRONMENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
# 测试环境与编码记录

> 本机实测过的环境、版本,以及踩过的编码/换行坑。供跨平台脚本(install.ps1 / uninstall.ps1 /
> verify.sh / 自检脚本)开发与排查参考。记录时间:2026-06(fork 维护)。

## 一、已测试环境矩阵

宿主:**Windows 11**(build 10.0-26200,中文版)。

| 环境 | 版本 | 解释器 | 关键工具 | 已实测 |
|------|------|--------|---------|--------|
| MSYS2 / Git Bash | MINGW64 | bash 5.3.9 | GNU coreutils **8.32**(stat 8.32 / sha256sum / shasum=perl) | ✅ 自检 4/0 |
| WSL Ubuntu | 24.04.1 LTS | bash | GNU coreutils **9.4**(shasum + sha256sum 均有) | ✅ 自检 4/0 |
| Windows PowerShell | **5.1**(`powershell.exe`) | — | — | ✅ install/uninstall 部署循环 PASS |
| Docker(rancher-desktop) | 29.1.4-rd | — | Alpine(busybox,真·无 shasum) | ⏳ 引擎未启动,待补 |

辅助工具版本:git 2.54.0.windows.1、curl 8.19.0(**Schannel** TLS 后端)、python 3.12.10、
node v24.15.0 / npm 11.12.1、gh 2.95.0。jq **未装**(脚本里用 python 替代解析 JSON)。

### 实测结论
- `check-portability.sh`(PR#1 两修复):MSYS2(GNU 8.32) + WSL Ubuntu 24.04(GNU 9.4) 均 **4/0**,slug 跨平台一致。
- `install.ps1` / `uninstall.ps1`:沙箱(临时 USERPROFILE)部署循环 install→uninstall→reinstall **PASS**,卸载正确保留 `.sofagent/` 数据。
- 缺口:Alpine(真·无 shasum)需启动 docker 引擎后用 `run-envs.sh` 补跑。

## 二、编码与换行坑(重要,已踩过)

### 1. PowerShell `.ps1` 必须 UTF-8 **带 BOM**
- **现象**:Windows PowerShell 5.1 读**无 BOM** 的 UTF-8 脚本时,按系统 ANSI 代码页(中文 Windows = **GBK**)解析 → 中文乱码、字符串提前截断、`解析报错`(Unexpected token / Missing closing quote)。
- **规则**:含中文的 `.ps1` 一律存 **UTF-8 with BOM**(前 3 字节 `EF BB BF`)。
- **正确加 BOM 写法**:
```powershell
[System.IO.File]::WriteAllText($p, $c, (New-Object System.Text.UTF8Encoding $true))
```

### 2. 转 BOM 时,读取**必须显式 `-Encoding UTF8`**
- **本次踩坑**:用 `Get-Content -Raw`(不带 `-Encoding`)读一个**无 BOM** 的 UTF-8 文件,5.1 默认按 GBK 误读 → 中文变 `鍗歌浇`/`涓枃` 这类 mojibake,再写回直接把文件读坏。
- **正确**:`Get-Content -Raw -Encoding UTF8 $p`。
- **例外**:原文件是 **UTF-16 BOM** 时,`Get-Content -Raw`(不带 `-Encoding`)能靠 BOM 自动识别、正确读入(install.ps1 第一次从 UTF-16 转 UTF-8 即此情形,所以那次没坏)。

### 3. `.gitattributes` 锁换行(已落地)
```
*.sh *.bash text eol=lf # Linux/Alpine/WSL 跑 shell 必须 LF
*.ps1 *.bat *.cmd text eol=crlf # Windows 脚本
```
- **背景**:仓库 `core.autocrlf=true` 且原本无 `.gitattributes` → checkout 会把 `*.sh` 变 CRLF → 在 Linux/Alpine/WSL 里 `bad interpreter: /bin/sh^M` 直接跑不了。

### 4. `wsl.exe` 输出是 UTF-16LE
- **现象**:`wsl.exe ... cmd` 的 stdout 是 UTF-16LE,Git Bash 里直接管道/`grep` 会乱码、或被当成 “Binary file matches”。
- **解法**:让重定向**在 WSL 内部**完成,输出文件即 UTF-8:
```bash
wsl.exe -d Ubuntu sh -c "sh /mnt/c/.../check.sh > /mnt/c/.../out.txt 2>&1"
cat /c/.../out.txt # UTF-8,干净
```

### 5. MSYS 路径转换(调 `wsl.exe` / native exe 时)
- **现象**:Git Bash 调 `wsl.exe` 时会把 `/tmp/x` 这类 `/unix/路径` 误转成 Windows 路径,导致 WSL 里 `No such file`。
- **解法**:`export MSYS2_ARG_CONV_EXCL='*'`(或 `MSYS_NO_PATHCONV=1`)禁用转换。

## 三、Windows 安装器实测发现的 bug(`feat/windows-installer`)

| # | bug | 影响 | 修复 |
|---|-----|------|------|
| 1 | install.ps1/install.sh 用 **`WSLENV`** 判 WSL | `WSLENV`(如 `WT_SESSION:`)在装了 WSL 的 Windows 主机上**本就有** → 脚本在 Windows 上误判为 WSL **直接拒跑** | 只认 `WSL_DISTRO_NAME` |
| 2 | install.ps1 rules.md 用旧路径 `constitution\rules.md` | v0.73 已扁平化到 `sofagent\rules.md` → **宪法部署失败** | 新路径优先 + 旧路径 fallback |

两者均由**沙箱实测**逐轮跑出来,修复后部署循环全过。

## 四、Shell→PowerShell 全面移植(`feat/windows-installer`)

把运行时 shell 脚本全量移植为原生 Windows PowerShell(纯 PowerShell + 非 WSL 可跑)。

### 已移植(**16 个 .ps1,100% 覆盖**,均实测对照 .sh)
`install` `uninstall` `task-record`(反思闭环)`audit` `lib/config` `task-orchestrate`(ao 包装)
`verify` `cleanup` `compress-memory` `verify-evidence` `benchmark`(A/B 题库 + audit-log 客观判定)
`daemon` `daemon-install` `daemon-status` `daemon-uninstall` `lib/daemon-lib`。
**全部 .sh(14)+ 2 lib 均有对应 .ps1,无遗漏。**

> daemon 系列特别说明:bash 版**明确拒绝在非 Unix 运行**;PS 版**反过来支持 Windows**——
> Get-Process 替 pgrep、Start-Process 替 nohup、Register-ScheduledTask 替 launchd/systemd、
> 原生 ConvertFrom/To-Json 替 grep/sed。实测主循环检测到真实 workbuddy/claude 进程。
> 计划任务注册需管理员权限(否则 try/catch 降级 + 直接启动)。

### Skill dispatch
SKILL.md(第 1 层永远注入)加「跨平台脚本调用约定」:`bash X.sh --flag` 在纯 Windows PowerShell
改 `powershell -File X.ps1 -Flag`(kebab→Pascal)。install.ps1 部署 .ps1 到 `$TARGET\scripts\`。
E2E 实测:install→部署7脚本→用部署后的 task-record.ps1 跑闭环→uninstall,纯 PowerShell 全过。

### PowerShell 移植踩坑全集(写 .ps1 必看)
1. **脚本编码**:含中文 .ps1 必须 **UTF-8 BOM**(PS 5.1 读无 BOM 按 GBK 解析、乱码/解析错)。
2. **加 BOM 时读取**须 `Get-Content -Raw -Encoding UTF8`(不指定→GBK 误读、直接读坏文件)。
3. **控制台输出**:脚本顶部加 `[Console]::OutputEncoding = New-Object System.Text.UTF8Encoding $false`,
否则输出按 OEM/GBK 编码,被 UTF-8 消费方(Agent/Git Bash)读到乱码。机器可读前缀(ASCII)不受影响。
4. **`if` 表达式不能直接作函数参数**:`f (if(){}else{})` 运行时崩 → 先 `$x = if...` 再传。
5. **`switch` 无 `break` 执行所有匹配 case**:兜底 `^-` 会误伤每个 flag → 用 if/elseif 链。
6. **函数前向引用**:PS 顺序解释,函数定义须在调用之前(Write-Summary 被前置段调用就得提前定义)。
7. **单元素嵌套数组 `@(@(...))` 被摊平**成一维 → `foreach` 遍历到字符、`$x[0]` 取首字符。多元素不摊平。
8. **日志/数据文件写 UTF-8 无 BOM**:用 `[IO.File]::WriteAllText/AppendAllText($p,$s,(New-Object Text.UTF8Encoding $false))`,对齐 .sh,且 BOM 会污染追加。
9. **`.gitattributes`** 锁 `*.ps1=CRLF` / `*.sh=LF`。

### 移植中顺带发现的 .sh bug(候选独立 PR)
- `task-record.sh` 的 `sanitize()` 用 BSD 专属词边界 `[[:<:]]`,**GNU sed 4.9 报 `Invalid character class`** →
AWS密钥/凭证/手机/IP 4 条脱敏在 Linux 上失效。ps1 用 `\b` 修对。
- `stat -f %m`(BSD)在 GNU 上是 `--file-system`、取不到 mtime(已在 PR #1 修)。
57 changes: 57 additions & 0 deletions docs/bug_fix/tests/check-portability.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
#!/bin/sh
# ============================================================
# sofagent 跨平台修复自检(对应上游 PR #1)
# ============================================================
# 目标:在「任意」环境独立执行,验证两处确定性修复在当前平台成立。
# 修复1 task-orchestrate.sh TASK_SLUG —— shasum 缺失时回退 sha256sum
# 修复2 verify.sh think.md mtime —— GNU `stat -c %Y` / BSD `stat -f %m` 回退
#
# 纯 POSIX sh,无 bashism,可在 Alpine(busybox) / Ubuntu / macOS / MSYS2 直接跑:
# sh check-portability.sh
# 退出码:0=全过,1=有失败(方便 CI / 排查)
# ============================================================
set -u
pass=0; fail=0
ok() { echo " [PASS] $1"; pass=$((pass + 1)); }
ng() { echo " [FAIL] $1"; fail=$((fail + 1)); }
is_hex8() { case "$1" in [0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]) return 0 ;; *) return 1 ;; esac; }

echo "== 环境 =="
echo " uname : $(uname -s) $(uname -m)"
echo " stat : $(stat --version 2>/dev/null | head -1 || echo '非GNU(BSD/busybox)')"
echo " shasum : $(command -v shasum 2>/dev/null || echo 无)"
echo " sha256sum: $(command -v sha256sum 2>/dev/null || echo 无)"
echo

echo "== 修复1:TASK_SLUG(缺 shasum 回退 sha256sum)=="
slug=$(printf '%s' "sofagent-task" | { shasum -a 256 2>/dev/null || sha256sum 2>/dev/null; } | cut -c1-8)
if is_hex8 "$slug"; then ok "正常环境 slug=$slug(8 位十六进制)"; else ng "正常环境 slug 非法:'$slug'"; fi
# 模拟 shasum 缺失:临时目录放一个必失败的 shasum stub,前插 PATH
d=$(mktemp -d 2>/dev/null || { d=/tmp/nob.$$; mkdir -p "$d"; echo "$d"; })
printf '#!/bin/sh\nexit 127\n' > "$d/shasum"; chmod +x "$d/shasum"
slug2=$(PATH="$d:$PATH" sh -c 'printf "%s" sofagent-task | { shasum -a 256 2>/dev/null || sha256sum 2>/dev/null; } | cut -c1-8')
rm -rf "$d"
if is_hex8 "$slug2"; then ok "缺 shasum 回退 slug=$slug2"; else ng "缺 shasum 回退失败:'$slug2'(这正是上游 bug)"; fi
if [ "$slug" = "$slug2" ]; then ok "回退透明(两次哈希一致)"; else ng "回退哈希不一致:$slug vs $slug2"; fi
echo

echo "== 修复2:stat 取 mtime(GNU -c%Y / BSD -f%m 回退)=="
f=$(mktemp 2>/dev/null || { f=/tmp/t.$$; echo "$f"; }); : > "$f"
now=$(date +%s)
mt=$(stat -c %Y "$f" 2>/dev/null || stat -f %m "$f" 2>/dev/null || echo "")
# 对照:上游旧写法只有 BSD 语法(只取首行,避免 GNU 上 -f 吐出整块文件系统信息)
old=$(stat -f %m "$f" 2>/dev/null | head -1)
rm -f "$f"
case "$mt" in
'' | *[!0-9]*) ng "新写法未取到数字 mtime:'$mt'" ;;
*) age=$((now - mt)); if [ "$age" -ge 0 ] && [ "$age" -le 5 ]; then ok "新写法 mtime=$mt 年龄=${age}s(正确)"; else ng "mtime 异常 age=${age}s"; fi ;;
esac
case "$old" in
'') echo " (参考)旧写法 stat -f %m:失败/无输出(本平台不支持该 BSD 语法)" ;;
*[!0-9]*) echo " (参考)旧写法 stat -f %m:取不到 mtime(GNU 上 -f=--file-system)← bug 本体" ;;
*) echo " (参考)旧写法 stat -f %m = $old(本平台为 BSD/macOS 风格,恰好可用)" ;;
esac
echo

echo "== 结果:$pass 通过 / $fail 失败 =="
[ "$fail" -eq 0 ]
39 changes: 39 additions & 0 deletions docs/bug_fix/tests/run-envs.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#!/usr/bin/env bash
# ============================================================
# 在本机把 check-portability.sh 丢进多个真实环境独立执行并汇总
# ============================================================
# 用法(Git Bash / Windows): bash docs/bug_fix/tests/run-envs.sh
# 设计:各环境互不依赖,单独成段,方便排查;某环境缺失则跳过、不影响其他。
# ============================================================
set -u
HERE="$(cd "$(dirname "$0")" && pwd)"
CHECK="$HERE/check-portability.sh"
sep() { echo; echo "######################## $1 ########################"; }

# 1) 本机 MSYS2 / Git Bash(Windows + GNU coreutils)
sep "本机 MSYS2 (Windows/GNU)"
sh "$CHECK"; echo "[exit $?]"

# 2) WSL Ubuntu(真 Linux/GNU)—— 输出走文件,避开 wsl.exe 的 UTF-16 管道乱码
if command -v wsl.exe >/dev/null 2>&1; then
sep "WSL Ubuntu (真 Linux/GNU)"
WIN_TMP="${HOME}/.cpcheck.sh"; WIN_OUT="${HOME}/.cpout.txt"
cp "$CHECK" "$WIN_TMP"
# 重定向在 WSL 内部完成 → 输出文件是 UTF-8(直接 cat wsl.exe 的 stdout 会是 UTF-16 乱码)
MSYS2_ARG_CONV_EXCL='*' wsl.exe -d Ubuntu sh -c "sh '/mnt${WIN_TMP}' > '/mnt${WIN_OUT}' 2>&1"
cat "$WIN_OUT"
rm -f "$WIN_TMP" "$WIN_OUT"
else
sep "WSL Ubuntu"; echo "(无 wsl,跳过)"
fi

# 3) Docker Alpine(真·无 shasum 的 busybox 环境)—— 仅当 docker 引擎在跑
if command -v docker >/dev/null 2>&1 && docker info >/dev/null 2>&1; then
sep "Docker Alpine (真·无 shasum / busybox)"
WINPATH="$(cygpath -w "$HERE" 2>/dev/null || echo "$HERE")"
docker run --rm -v "${WINPATH}:/t" alpine sh /t/check-portability.sh; echo "[exit $?]"
else
sep "Docker Alpine"; echo "(docker 引擎未启动,跳过;启动 rancher-desktop 后重跑即可补这一档)"
fi

echo; echo "######################## 汇总完毕 ########################"
2 changes: 1 addition & 1 deletion sofagent/scripts/benchmark.sh
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ while [[ $# -gt 0 ]]; do
SUMMARY_ONLY=true; shift ;;
--api)
API_MODE=true; shift ;;
*) shift ;;
*) echo "未知参数: $1(--help 查看用法)"; exit 1 ;;
esac
done

Expand Down
Loading
Loading