Skip to content

fix: stop setup from deleting vaults and fix agent config generation - #16

Merged
zxfccmm4 merged 1 commit into
mainfrom
fix/safe-setup-and-agent-configs
Sep 26, 2026
Merged

zxfccmm4 merged 1 commit into
mainfrom
fix/safe-setup-and-agent-configs

Conversation

@zxfccmm4

Copy link
Copy Markdown
Owner

📝 变更描述 / Change Description

修复 setup.sh 会删除用户已有知识库的问题,以及各 agent 配置生成中的几处错误;新增端到端冒烟测试,CI 覆盖 macOS 自带的 /bin/bash 3.2。

最严重的问题:重跑 setup 会删掉笔记

目录已存在时选「覆盖」,脚本会 rm -rf 整个知识库,而且是在第 1 步——检查 Node.js、安装依赖之前。后面任何一步失败,用户就什么都不剩了。README 和 GUIDE_FOR_AI.md 推荐给 AI 代部署用的 --overwrite-existing 也走这条路,而 docs/agents.md 写的是「切换 agent 不会删除笔记」。

现在目录已存在时三选一:

  1. 保留笔记,只更新规则和技能(新增 --keep-existing,复用 upgrade.sh)
  2. 旧目录改名为 <目录>.backup-时间戳,再新建(--overwrite-existing 现在是这个行为)
  3. 取消

所有文件操作挪到第 5 步,依赖装好之后才执行。

配置生成的错误

  • --provider skip 会让 setup 中途退出:write_agent_config 跳过时返回 1,在 set -e 下直接终止,Obsidian 插件配置和最后的说明都不会生成。README 里的 dry-run 示例就会触发。

  • Claude Code 连不上第三方:智谱 / DeepSeek / OpenRouter 写的是 OpenAI 兼容地址。改为各自的 Anthropic 兼容端点:

    服务商 ANTHROPIC_BASE_URL
    智谱 GLM https://open.bigmodel.cn/api/anthropic
    DeepSeek https://api.deepseek.com/anthropic
    OpenRouter https://openrouter.ai/api

    OpenAI / Google 没有这种端点,之前会生成 ANTHROPIC_BASE_URL: "" 的配置,现在开始前直接拒绝。

  • ~/.claude/settings.json 被整个覆盖:用户的权限、hooks 等只剩在备份里。OpenCode / Claude Code / Pi 的 JSON 配置现在用 node 合并写入,只改模型和 Key;也解决了 Key 里有引号、反斜杠会写坏 JSON 的问题。含 Key 的文件和备份权限改为 600。

  • Codex:model 写成了 provider/model;Anthropic / Google 的 base_url 为空;有一段被立即覆盖的死代码;配置完成后在终端明文打印 API Key(README 让用户截图终端报错发 Issue)。

  • 用户级技能目录:~/.codex/skills 已存在时,cp -R 会把技能嵌套复制到 skills/skill/;upgrade.sh 的 rsync --delete 会清掉用户自己装的其他技能。改为按技能名逐个同步。

其他

  • upgrade.sh 每次都用模板覆盖 AI_CONFIG.md(头部注释写的是「逐字段保留」)。现在用户改过就原样保留,新模板另存为 AI_CONFIG.md.new;与模板历史版本完全一致(从没改过)的直接更新。
  • upgrade.sh / uninstall.sh 不传 --agent 时默认 opencode,Claude Code 用户会升级或卸载错对象。改为按 vault 自动识别,识别不了就要求显式指定。
  • uninstall.sh --remove-vault 没有路径保护。现在只删含 AGENTS.md 和 wiki/ 的目录,并拒绝主目录、桌面等。
  • OpenCLI 安装失败不再中止整个部署。
  • npm 全局目录不可写时才用 sudo,失败时提示切换 npmmirror。
  • opencode-obsidian-doctor.sh 在 bash 3.2 下崩溃(mapfile 不存在;空数组在 set -u 下报错)。
  • 交互选择 provider 时校验输入;路径输入去掉首尾空格和引号,兼容把文件夹拖进终端。
  • claudian 用户的结束提示改为推荐 verify.sh(doctor 只适用于 opencode-obsidian)。

🏷️ 变更类型 / Type of Change

  • 🐛 Bug 修复 / Bug fix
  • ✨ 新功能 / New feature(--keep-existing)
  • 📝 文档更新 / Documentation
  • 🎨 代码风格 / Code style
  • ♻️ 代码重构 / Refactoring
  • ⚡ 性能优化 / Performance
  • ✅ 测试相关 / Tests
  • 🔧 构建/工具 / Build/Tools(CI 新增 macOS job)

🧪 测试清单 / Testing Checklist

  • 本地测试通过 / Local testing passed
  • 相关文档已更新 / Related documentation updated
  • 代码符合项目规范 / Code follows project guidelines(shellcheck 通过)
  • 提交信息符合规范 / Commit messages follow conventions

测试详情 / Testing Details

新增 tests/smoke-test.sh:在临时 HOME 里运行真实脚本,用桩命令替代 npm、各 agent CLI 和 sudo,不联网、不碰真实配置。共 13 组场景:

  • OpenCode / Claude Code / Codex 配不同 provider 的配置生成(含 Key 带引号/反斜杠、合并已有 settings.json、Key 不出现在输出里);Pi 没有单独的配置用例
  • Claude Code + OpenAI 在动任何文件前被拒绝
  • --provider skip 能跑完
  • --overwrite-existing 改名备份、--keep-existing 保留笔记并切换 agent、不带参数时拒绝处理已有目录
  • 拒绝 HOME、桌面、桌面/..
  • --dry-run 不写任何文件
  • upgrade.sh 自动识别 agent、刷新技能、保留用户技能、补回缺失文件
  • uninstall.sh --remove-vault 拒绝非知识库目录、正常删除真知识库
  • doctor 在空日志目录下不崩溃
bash tests/smoke-test.sh
BASH_BIN=/bin/bash /bin/bash tests/smoke-test.sh   # macOS 自带的 bash 3.2
shellcheck setup.sh scripts/*.sh tests/smoke-test.sh

在 macOS /bin/bash 3.2.57 下全部通过。测试过程中还发现一个 bash 3.2 特有的问题:$VAR 后面紧跟全角标点(如 $AGENT_CHOICE()时,全角字符的第一个字节会被当成变量名的一部分,报 unbound variable。已改成 ${VAR},并确认脚本里没有其他同类写法。

CI 新增 macos-system-bash job,专门用 /bin/bash 3.2 跑冒烟测试——普通用户在 Mac 上实际用的就是它,而原有的 Ubuntu job 用的是 bash 5,覆盖不到。

⚠️ 破坏性变更 / Breaking Changes

  • 否 / No
  • 是 / Yes

如果是,请说明 / If yes, please explain:

  • --overwrite-existing:从「删除旧目录」改为「旧目录改名备份」。旧目录会留在 <目录>.backup-时间戳,需要时手动删除。
  • upgrade.sh / uninstall.sh 不传 --agent 时不再默认 opencode:按 vault 自动识别,识别不了(codex / pi)会报错要求指定。README 示例本来就带 --agent,不受影响。
  • --agent claude-code 配 --provider openai|google 现在直接报错(之前生成的配置本来就用不了)。
  • upgrade.sh 不再覆盖用户改过的 AI_CONFIG.md,新模板写到 AI_CONFIG.md.new。
  • Claude Code 选 Anthropic 时 model 改为别名 opus(始终指向最新的 Opus),不再固定版本号。

📝 补充说明 / Additional Notes

没有真机验证的部分:冒烟测试只检查生成的配置内容,没有真的连接各服务商。上面三个 Anthropic 兼容端点建议用真实 Key 各试一次。

这个 PR 没有改的(发现了但无法核实,留给维护者判断):

  • 各家模型清单(setup.sh 顶部注释写的是 2026-06 核对)
  • Pi 的 ~/.pi/config.json 和 ~/.pi/skills 路径可能与 Pi 实际的目录结构不一致
  • claudian 插件 data.json 的字段名(cliPathsByHost 等)没有对照插件源码核实
  • Codex 从环境变量读 Key;从 Obsidian 图形界面启动时读不到 ~/.zshrc 里的变量,插件内可能无法认证

✅ 提交前检查 / Pre-Submission Checklist

  • 我的 PR 只解决一个问题 / My PR addresses only one issue
  • 我已经阅读了贡献指南 / I have read the Contributing Guide
  • 我的代码遵循项目规范 / My code follows the project guidelines
  • 我添加了适当的注释(如果需要)/ I have added appropriate comments

这个 PR 包含多个修复。它们大多集中在 setup.sh 的同一段流程里(目录处理、配置写入),并共用同一套冒烟测试,拆开会互相依赖。如果更希望分开审,可以按「知识库安全」「配置生成」「upgrade/uninstall」「测试与 CI」拆成几个 PR。

👥 审核者注意 / For Reviewers

建议重点看:

  • setup.sh 第 1 步和第 5 步:目录处理从「立即删除」改为「先决定、后执行」
  • update_json_file():所有 JSON 配置都经过它,用 node 读取-合并-写回
  • scripts/upgrade.sh 的 is_unmodified_template_copy():用 git 历史判断用户是否改过 AI_CONFIG.md;仓库不是 git clone(ZIP 下载)时一律按「改过」处理

Data safety
- setup.sh no longer runs `rm -rf` on an existing vault. It used to do
  so at step 1, before Node.js and npm were checked, so any later
  failure left the user with nothing. An existing directory now offers
  "keep notes, refresh rules/skills" (new --keep-existing, reuses
  upgrade.sh) or "rename old dir as backup, then create" (what
  --overwrite-existing now does). All file changes happen in step 5.
- Dangerous-path check resolves `..` and symlinks and also blocks
  Desktop, Documents, Downloads and friends.
- uninstall.sh --remove-vault only deletes a directory that contains
  AGENTS.md and wiki/, and refuses HOME / Desktop.
- upgrade.sh keeps a user-edited AI_CONFIG.md and writes the new
  template to AI_CONFIG.md.new; skills and helper scripts are synced
  one by one instead of `rsync --delete`, so user-added files survive.

Config correctness
- `--provider skip` aborted setup: write_agent_config returned 1 under
  `set -e`, so the plugin config and final instructions never ran.
- Claude Code now uses the Anthropic-compatible endpoints of Zhipu,
  DeepSeek and OpenRouter (it was given OpenAI-compatible URLs).
  OpenAI / Google are rejected up front instead of writing a config
  with an empty base URL.
- OpenCode / Claude Code / Pi JSON configs are merged via node instead
  of overwritten, so existing settings (permissions, hooks, other
  providers) survive, and keys with quotes or backslashes cannot break
  the JSON. Files holding API keys and their backups are chmod 600.
- Codex: `model` holds only the model name (was `provider/model`),
  Anthropic / Google get their OpenAI-compatible base URLs, dead code
  removed, and the API key is no longer echoed to the terminal.
- User-level skills (~/.codex/skills, ~/.pi/skills) are no longer
  nested under skills/skill when the directory already exists.

Robustness
- An OpenCLI install failure no longer aborts the whole setup.
- sudo is used only when the npm global directory is not writable;
  failures suggest the npmmirror registry.
- Interactive provider input is validated.
- upgrade.sh / uninstall.sh detect the agent from the vault when
  --agent is omitted instead of silently assuming opencode.
- opencode-obsidian-doctor.sh no longer crashes on macOS /bin/bash 3.2
  (mapfile, empty array under set -u).
- Braced variables that are followed by full-width punctuation, which
  bash 3.2 otherwise reads as part of the variable name.

Tests and docs
- Add tests/smoke-test.sh: runs setup / upgrade / uninstall / doctor in
  a throwaway HOME with stubbed npm, agent CLIs and sudo (13 scenarios).
- CI runs it on Linux and with macOS /bin/bash 3.2.
- Update CHANGELOG, README (zh/en), GUIDE_FOR_AI.md and the
  troubleshooting docs to match.
@zxfccmm4
zxfccmm4 merged commit 375f3ef into main Sep 26, 2026
4 checks passed
@zxfccmm4
zxfccmm4 deleted the fix/safe-setup-and-agent-configs branch September 26, 2026 23:06
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.

1 participant