Skip to content

fix: 修复在启用 set -u 时由于未绑定变量导致的 store_session_get_latest_dir 和 validate_config 崩溃#67

Merged
lloydzhou merged 4 commits into
lloydzhou:mainfrom
engigu:fix/deepseek-env-set-error
Jul 14, 2026
Merged

fix: 修复在启用 set -u 时由于未绑定变量导致的 store_session_get_latest_dir 和 validate_config 崩溃#67
lloydzhou merged 4 commits into
lloydzhou:mainfrom
engigu:fix/deepseek-env-set-error

Conversation

@engigu

@engigu engigu commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

描述

本 PR 修复了在启用 set -u(未定义变量视为错误)时导致 bash-agent 崩溃的两处未绑定变量问题。

问题现象

安装bash的版本

curl -fsSL https://github.com/lloydzhou/bash-agent/releases/latest/download/agent.sh \
  -o ~/.local/bin/bash-agent && chmod +x ~/.local/bin/bash-agent

然后设置deepseek

export DEEPSEEK_API_KEY="sk-..."
bash-agent "hello"   # 自动检测,使用 deepseek-v4-flash

出现报错

root@armbian:~/workspace# env | grep EE
DEEPSEEK_API_KEY=sk-xxxxxxxxxxxxx
root@armbian:~/workspace# bash-agent --continue  'ls'
/root/.local/bin/bash-agent: line 2120: File: unbound variable
/root/.local/bin/bash-agent: line 3326: ANTHROPIC_API_KEY: unbound variable

修复详情

1. 修复 store_session_get_latest_dir 中出现的 File: unbound variable 错误

  • 根本原因
    在 Linux 系统上,stat -f 用于查询文件系统状态(与 BSD/macOS 格式化输出不同)。在 Linux 执行 stat -f "%m" 虽然找不到名为 %m 的文件,但依然会为第二个参数输出文件系统信息,其标准输出(stdout)包含 File: ... 字样。
    此输出被捕获存入变量 ts 中,随后在数学计算表达式 (( ts > latest_ts )) 中被评估。Bash 遇到 File 单词时会将其视作变量去解析。在 set -u 启用下,这会引发未绑定变量 File 的崩溃。
  • 修复方案
    在进入循环前先检测 stat 命令是支持 -c(GNU)还是 -f(BSD),动态构建命令,并在赋值时通过正则确保 ts 是合法数字,避免非法字符串干扰。

2. 修复 validate_config 中出现的 ANTHROPIC_API_KEY: unbound variable 错误

  • 根本原因
    默认的 claude 提供商分支会先执行 : "${API_KEY:=$ANTHROPIC_API_KEY}"。如果用户使用的是 DeepSeek,仅配置了 DEEPSEEK_API_KEY 而未定义 ANTHROPIC_API_KEY,脚本在走到 DeepSeek 自动检测逻辑前就会因未定义变量崩溃。
  • 修复方案
    • 将 DeepSeek 的自动检测逻辑移动到了 validate_config 函数的最顶部。
    • 使用安全默认值格式 ${ANTHROPIC_API_KEY:-}${OPENAI_API_KEY:-},以防在未配置这些变量时触发 set -u 崩溃。

@engigu
engigu marked this pull request as ready for review July 14, 2026 06:19
@engigu
engigu force-pushed the fix/deepseek-env-set-error branch 2 times, most recently from cde9565 to c3abebc Compare July 14, 2026 07:06
@lloydzhou

Copy link
Copy Markdown
Owner

感谢修复未设置密钥时触发未绑定变量的问题。

我保留了对 Anthropic/OpenAI 环境变量的安全展开修复,但恢复了两处原有逻辑:

  1. stat:原实现会针对每个候选路径依次尝试 BSD 与 GNU 两种 stat 参数,并在 events.jsonl 不存在时回退到会话目录本身。这样可同时兼容 macOS 和 Linux,也能处理不完整的会话目录。PR 中先探测一次并固定命令的写法会弱化这层逐路径回退,因此恢复为原实现。
  2. DeepSeek 自动检测:需要在当前 provider 的默认密钥、地址和模型解析之后执行。若提前执行,同时配置多个密钥或显式选择 OpenAI 时,DeepSeek 配置可能错误覆盖用户明确选择的 provider。

因此最终仅保留安全变量展开的改动:未设置 ANTHROPIC_API_KEYOPENAI_API_KEY 时会正常返回“缺少 API 密钥”的业务错误,不再因未绑定变量退出。

@lloydzhou
lloydzhou force-pushed the fix/deepseek-env-set-error branch from e2bd232 to d859bf8 Compare July 14, 2026 11:43
@lloydzhou

Copy link
Copy Markdown
Owner

更正我上一条评论中关于 stat 的判断:PR 描述的问题确实存在,已在 GNU coreutils stat 环境实际复现。

GNU stat 接收 -f "%m" 时会将 %m 视为文件系统参数,而非 BSD 格式串;它会向标准输出写入文件系统信息(其中包含 File:),即使命令以非零状态退出。原来的命令替换会捕获这段标准输出;由于 || 链只会根据退出状态继续执行,最终会把该文本与后续 GNU -c "%Y" 的数字输出拼接到 ts。随后 (( ts > latest_ts ))set -u 下把 File 当变量解析,因此会触发未绑定变量错误。

我已撤销对 stat 部分的恢复,保留 PR 的平台探测与数字校验;先前恢复的提交已通过强制更新改写。DeepSeek 检测顺序与环境变量安全展开的调整保持不变。

@lloydzhou

Copy link
Copy Markdown
Owner

已补充配置解析顺序的修复。核心原则是优先使用用户已设置的配置,只有缺失时才使用自动检测或默认值:

  1. 命令行传入的 --api-key--base-url-m/--model 优先级最高。
  2. 未传命令行配置时,读取当前选中 provider 的环境变量(例如 OPENAI_API_KEYOPENAI_BASE_URL)。
  3. 仅当当前 provider 的密钥和地址均未配置时,才回退检测 DEEPSEEK_API_KEY,并切换到 DeepSeek 的 Anthropic 兼容端点。
  4. 模型同样遵循这一顺序:保留用户通过 -m 指定的模型;DeepSeek 自动检测且模型未设置时使用 deepseek-v4-flash;其余情况下最后才设置 Claude 或 OpenAI 的默认模型。
  5. 地址、认证头和请求转换在最终 provider 确定后再构造,避免 DeepSeek 回退后仍使用旧 provider 的请求配置。

因此,显式 OpenAI/Anthropic 的密钥或地址不会被 DeepSeek 自动检测覆盖。

@lloydzhou

Copy link
Copy Markdown
Owner

已完成跨运行时配置优先级修复与复核。

本次补充提交:f925bce fix: align port provider fallback

验证结果:

  • make test-c-e2e:182 通过,0 失败
  • make test-go-e2e:182 通过,0 失败
  • make test-rust-e2e:182 通过,0 失败
  • git diff --check:通过

修复确保 C、Go、Rust 与 Bash 一致:显式配置优先,其次为当前 provider 的环境配置,再执行 DeepSeek 回退并切换至 Claude 兼容传输。

@engigu

engigu commented Jul 14, 2026

Copy link
Copy Markdown
Contributor Author

已完成跨运行时配置优先级修复与复核。

本次补充提交:f925bce fix: align port provider fallback

验证结果:

  • make test-c-e2e:182 通过,0 失败
  • make test-go-e2e:182 通过,0 失败
  • make test-rust-e2e:182 通过,0 失败
  • git diff --check:通过

修复确保 C、Go、Rust 与 Bash 一致:显式配置优先,其次为当前 provider 的环境配置,再执行 DeepSeek 回退并切换至 Claude 兼容传输。

速度太快了

@lloydzhou
lloydzhou merged commit 8570891 into lloydzhou:main Jul 14, 2026
45 checks passed
@lloydzhou

Copy link
Copy Markdown
Owner

最近自己用C版本比较多,Bash版本疏于测试了

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants