minimalcode 1.5.2__py3-none-any.whl

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.
Files changed (58) hide show
  1. minimalcode/__init__.py +3 -0
  2. minimalcode/__main__.py +3 -0
  3. minimalcode/agent.py +1084 -0
  4. minimalcode/cli.py +1520 -0
  5. minimalcode/clipboard.py +212 -0
  6. minimalcode/config.py +1065 -0
  7. minimalcode/defaults.json +491 -0
  8. minimalcode/errors.py +31 -0
  9. minimalcode/highlight/__init__.py +47 -0
  10. minimalcode/highlight/code.py +261 -0
  11. minimalcode/highlight/color.py +58 -0
  12. minimalcode/highlight/markdown.py +710 -0
  13. minimalcode/highlight/palette.py +73 -0
  14. minimalcode/highlight/sanitize.py +175 -0
  15. minimalcode/highlight/thinking.py +71 -0
  16. minimalcode/httpclient.py +278 -0
  17. minimalcode/importer.py +253 -0
  18. minimalcode/prompt.py +195 -0
  19. minimalcode/provider/__init__.py +28 -0
  20. minimalcode/provider/anthropic.py +805 -0
  21. minimalcode/provider/anthropic_env.py +161 -0
  22. minimalcode/provider/chat.py +394 -0
  23. minimalcode/provider/client.py +243 -0
  24. minimalcode/provider/common.py +176 -0
  25. minimalcode/provider/deepseek_web.py +1158 -0
  26. minimalcode/provider/factory.py +63 -0
  27. minimalcode/provider/responses.py +692 -0
  28. minimalcode/provider/sha3_wasm_bg.wasm +0 -0
  29. minimalcode/provider/transport.py +241 -0
  30. minimalcode/provider/types.py +54 -0
  31. minimalcode/sandbox/__init__.py +64 -0
  32. minimalcode/sandbox/audit.py +120 -0
  33. minimalcode/sandbox/backends.py +343 -0
  34. minimalcode/sandbox/execution.py +435 -0
  35. minimalcode/sandbox/network.py +793 -0
  36. minimalcode/sandbox/policy.py +253 -0
  37. minimalcode/sandbox/runner.py +347 -0
  38. minimalcode/sandbox/sensitive.py +286 -0
  39. minimalcode/session.py +465 -0
  40. minimalcode/shell.py +333 -0
  41. minimalcode/subagent.py +120 -0
  42. minimalcode/tools/__init__.py +46 -0
  43. minimalcode/tools/files.py +1139 -0
  44. minimalcode/tools/process.py +164 -0
  45. minimalcode/tools/remote.py +74 -0
  46. minimalcode/tools/runtime.py +219 -0
  47. minimalcode/tools/schemas.py +418 -0
  48. minimalcode/tools/search.py +521 -0
  49. minimalcode/tools/search_tools.py +583 -0
  50. minimalcode/tools/validation.py +99 -0
  51. minimalcode/vision.py +231 -0
  52. minimalcode/web.py +238 -0
  53. minimalcode-1.5.2.dist-info/METADATA +646 -0
  54. minimalcode-1.5.2.dist-info/RECORD +58 -0
  55. minimalcode-1.5.2.dist-info/WHEEL +5 -0
  56. minimalcode-1.5.2.dist-info/entry_points.txt +2 -0
  57. minimalcode-1.5.2.dist-info/licenses/LICENSE +201 -0
  58. minimalcode-1.5.2.dist-info/top_level.txt +1 -0
@@ -0,0 +1,646 @@
1
+ Metadata-Version: 2.4
2
+ Name: minimalcode
3
+ Version: 1.5.2
4
+ Summary: A configurable coding agent with provider web tools and Responses/Chat/Anthropic support
5
+ License-Expression: Apache-2.0
6
+ Project-URL: Repository, https://github.com/jiaheng0815/MinimalCode
7
+ Project-URL: Issues, https://github.com/jiaheng0815/MinimalCode/issues
8
+ Project-URL: Changelog, https://github.com/jiaheng0815/MinimalCode/blob/main/CHANGELOG.md
9
+ Keywords: coding-agent,cli,terminal,openai,anthropic,deepseek,openai-compatible,multi-provider
10
+ Classifier: Development Status :: 5 - Production/Stable
11
+ Classifier: Environment :: Console
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Operating System :: OS Independent
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3 :: Only
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Programming Language :: Python :: 3.13
19
+ Requires-Python: <3.14,>=3.11
20
+ Description-Content-Type: text/markdown
21
+ License-File: LICENSE
22
+ Requires-Dist: httpx2<3,>=2.0
23
+ Provides-Extra: dev
24
+ Requires-Dist: ruff==0.17.3; extra == "dev"
25
+ Provides-Extra: deepseek-web
26
+ Requires-Dist: wasmtime>=20; extra == "deepseek-web"
27
+ Dynamic: license-file
28
+
29
+ # MinimalCode
30
+
31
+ [![CI](https://github.com/jiaheng0815/MinimalCode/actions/workflows/tests.yml/badge.svg)](https://github.com/jiaheng0815/MinimalCode/actions/workflows/tests.yml)
32
+
33
+ MinimalCode 是一个面向终端编码任务的轻量 Agent。它优先减少启动开销、交互层级和上下文浪费,不提供炫技式 TUI。
34
+
35
+ 当前版本:`1.5.2`。运行时依赖只有 `httpx2`(`deepseek_web` 协议额外需要可选的 `wasmtime`),Python 3.11–3.13。
36
+
37
+ ## 特性
38
+
39
+ - **Shell 优先使用 pwsh**:Windows 上按 `pwsh` → `powershell.exe` → Git Bash(`bash`)选择,其他平台按 `pwsh` → `bash` → `zsh` → `sh` 选择;每个候选都会先探测能否启动,启动时解析一次,可在配置中固定路径。Windows 上会跳过 `C:\Windows\System32\bash.exe`(WSL 启动器),它看起来像 bash,但会把命令送进 Linux 命名空间。
40
+ - **聚焦工具集**:`read`、`read_range`、`write`、`append_file`、`edit`、`shell`、`grep`、`find`、`subagent` 九个基础工具,外加可选的 `read_image`、`web_search`、`web_fetch`。`edit` 默认按行号替换区间,`append_file` 负责在 EOF 追加,写入 Python 时会校验并回滚坏改动。`read_image` 不绑定供应商,任何配置了 `vision` 的供应商都能使用。
41
+ - **工具白名单与只读模式**:`tools.allow` 列出允许的工具名,`--read-only` 只保留 `read`、`read_range`、`grep`、`find`、`read_image`、`web_search`、`web_fetch`;两者取交集。被禁用的工具既不发给模型,直接在 `dispatch` 里调用也会被拒绝,因此恢复的旧会话或忽略 schema 的供应商都绕不过去。
42
+ - **搜索不依赖 shell**:`grep` / `find` 直接用 `rg` 子进程或内置 Python 遍历实现,不经过 pwsh,因此没有引号、通配符和对象管道语义的偏差。同一轮里相邻的只读工具会并发执行(上限 `tools.max_parallel`,默认 4),结果仍按请求顺序写回;只读调用旁边出现 `write` / `shell` / `subagent` 时保持严格顺序。
43
+ - **纯文本输出**:流式打印,在交互终端中增量渲染 Markdown 高亮,不使用 Rich、Textual 或其他 UI 框架。
44
+ - **会话**:追加式 JSONL 自动保存,支持继续最近会话、按 ID 恢复、按工作区隔离。`--session` 只接受 `.jsonl` 文件;文件里记录的 workspace 只有在文件位于配置目录 `sessions/` 之下时才会被信任。压缩后如果文件比保留的状态大一倍以上(且超过 64 KiB),会原子重写成「meta + 压缩状态」,避免把同一段历史存两遍;小会话保持纯追加。
45
+ - **上下文管理**:接近上限时自动压缩较早消息,也可手动 `/compact`。
46
+ - **编码可见**:`read` 用严格 UTF-8 先扫一遍请求范围,遇到非 UTF-8 字节时改用替换解码返回内容,并在 `warnings` 里说明 `edit` 会拒绝该文件;UTF-8 BOM 会被去掉,不再出现在第一行。
47
+ - **会话总结**:`/summary` 让模型把当前会话总结成仓库笔记写入工作区 `AGENTS.md`,已存在时只更新标记块,其余内容不动。
48
+ - **规则文件**:读取全局和项目级 `AGENTS.md` / `CLAUDE.md`,每次运行开始前重新读取(文件不存在则跳过);可用 `SYSTEM.md` 替换默认系统提示词。
49
+ - **协议**:OpenAI Chat Completions、OpenAI Responses、Anthropic Messages 与 DeepSeek 网页版(`deepseek_web`),其他兼容供应商只需配置。Anthropic 供应商可加 `"prompt_cache": true`,把 system 提示与工具定义标记为一个缓存前缀,工具循环里每轮重发的大段静态内容按缓存读取计费;默认关闭,因为并非所有 Messages 兼容端点都接受 `cache_control`。
50
+ - **多供应商切换**:内置 37 个供应商预设(34 家托管服务 + `ollama` / `lmstudio` / `vllm`),各自的 API key 走对应厂商的环境变量;交互中用 `/model 供应商/模型` 随时切换,会话历史保留。
51
+ - **多供应商切换**:内置 36 个供应商预设(33 家托管服务 + `ollama` / `lmstudio` / `vllm`),各自的 API key 走对应厂商的环境变量;交互中用 `/model 供应商/模型` 随时切换,会话历史保留。
52
+ - **脚本友好**:`--json` 输出机器可读结果,stdout 与工具活动分离。
53
+ - **用量可见**:每次任务结束在 stderr 打印本轮 token 用量(prompt、completion、total,以及非零的 cached/reasoning)。供应商没有返回 usage 时按字符宽度估算并标注 `(estimated)`,不会把猜出来的数字当成计费结果。
54
+
55
+ ## 安装
56
+
57
+ ```powershell
58
+ python -m pip install -e .
59
+ minimalcode init
60
+ ```
61
+
62
+ 也可以用 pipx:
63
+
64
+ ```powershell
65
+ pipx install .
66
+ minimalcode init
67
+ ```
68
+
69
+ `init` 会在配置目录写入 `settings.json` 并创建 `sessions/`。首次正常运行如果发现配置缺失,也会自动生成,因此这一步是可选的。
70
+
71
+ 要求 Python 3.11–3.13。安装 `ripgrep`(`rg`)是可选的,但会让 `grep` / `find` 更快,并获得更完整的 ripgrep 语义。`deepseek_web` 协议需要可选的 wasm 运行时:`python -m pip install "minimalcode[deepseek-web]"`。
72
+
73
+ ## 升级指南
74
+
75
+ ### 从 1.5.1 升级到 1.5.2
76
+
77
+ 1.5.2 新增 `deepseek_web` 协议和 `deepseek-web` 预设,没有删除任何公开名字、CLI 参数、配置键、JSON 字段、会话格式或工具 schema,已有配置无需改动。要使用网页版协议才需要额外安装 `minimalcode[deepseek-web]`(wasmtime),并把浏览器 localStorage 里的 `userToken` 放进 `DEEPSEEK_WEB_TOKEN`。
78
+
79
+ - 新增 `protocol: "deepseek_web"`:直连 chat.deepseek.com 的网页接口,用本机的 wasmtime 解 `x-ds-pow-response` 工作量证明(挑战前缀为 `<salt>_<expire_at>_`,模块的 `status` 非零表示成功);工具以文本块形式发给模型再解析回来,因此这条链路不需要函数调用支持。
80
+ - 认证用 `Authorization: Bearer <userToken>`;`DEEPSEEK_WEB_COOKIE` / `cookie` 只是可选的 WAF 兼容项,缺失不会报错。`-m` / `/model deepseek-web/<mode>` 选的 `model_type` 不再被预设的 `default` 覆盖,`Authorization` 里重复的 `Bearer` 前缀会被去掉。
81
+ - 会话 id 从 `biz_data.id` 读取(旧结构 `biz_data.chat_session.id` 仍兼容),补全请求带上 `stream: true` 和 `client_stream_id`,否则服务端只回一整段非 SSE JSON。
82
+ - 网页版流式回复按片段增量去重,思维链与答案分别投递,`response/content` 补丁同样计入正文;无标记的裸 JSON 只有带参数键时才当作工具调用,普通 JSON 回答原样显示,解析失败的参数会让模型自我纠正而不是把原文塞进工具参数。
83
+ - `tool_mode`、`cookie`、`cookie_env`、`model_type`、`web_search`、`pow_wasm_path`、`tool_parse_retries` 是新增的供应商键;`web_search` 与其它布尔键一样参与占位符展开和类型校验,`config show` 会脱敏内联的 `cookie`。
84
+ - `transport` 的响应读取现在把裸 `OSError`/TLS 错误也归入 `ProviderError`,握手请求(会话创建、挑战获取)沿用连接重试,但重试仍不覆盖已开始生成的补全。
85
+
86
+ 详见 [CHANGELOG.md](CHANGELOG.md)。
87
+
88
+ ### 从 1.5.0 升级到 1.5.1
89
+
90
+ 1.5.1 没有删除任何公开名字、CLI 参数、配置键、JSON 字段、会话格式或工具 schema,升级不需要改代码;`minimalcode.shell.MAX_TIMEOUT_SECONDS` 是新增常量。这一版修的是 1.5.0 里仍然存在的口径不一致,其中几条会改变日常命令的结果:
91
+
92
+ - 引号不再能绕过敏感文件检查:`type ".env"`、`Get-Content '.ssh/id_rsa'` 与不加引号时一样被拒绝;`minimalcode --home <目录>` 这类“长选项 + 目录名”不算读凭据,子代理不会再被自己的配置目录挡住。
93
+ - 网络门禁补上四种写法:`curl -xhost:port`(粘连代理)、`\\?\UNC\host\share`(扩展长度 UNC)、直接把 `(New-Object Net.WebClient).DownloadString(...)` 输入 shell、以及 `py -3 -c` / `python3.12 -c` 的内联脚本。`allowlist` 下这些目标同样参与主机比对。
94
+ - 审计记录里带引号的 `-b` / `-H` / `--header` 值现在也被脱敏,`/status` 的 `recent_denials` 不再是凭证明文副本。
95
+ - Chat 工具调用的分片不再截断或串包:`id` 只随首片发送时的续片归入同一调用,服务端复用 `index` 时的续片跟随新调用。每次连接尝试也受 `timeout_seconds` 剩余预算约束。
96
+ - `edit` 越界提示只显示前 40 行,`write` 覆盖超过 `tools.max_file_bytes` 的既有文件会明确报错,`grep(path=<单个文件>, glob=…)` 在有无 `rg` 时结果一致,`subagent` 回报的超时不再超过实际的 3600 秒上限。
97
+ - 管道与子代理的文本固定走 UTF-8(子进程设 `PYTHONUTF8=1`),`settings.json` 里 `thinking` 大小写不敏感,交互模式以 `/` 开头的多行粘贴会发给模型而不是被当成未知命令丢弃。
98
+
99
+ 详见 [CHANGELOG.md](CHANGELOG.md)。
100
+
101
+ ### 从 1.4.3 升级到 1.5.0
102
+
103
+ 1.5.0 没有删除任何公开名字、CLI 参数、配置键、JSON 字段、会话格式或工具 schema,升级不需要改代码;`SandboxPolicy` 多了一个只读属性 `isolates_network`。这一版把此前几处“工具拦截、shell 放行”的口子堵上,其中一些会改变日常命令的结果:
104
+
105
+ - `shell` 命令现在也受敏感文件策略约束。未加引号的 `.env`、`~/.ssh/id_rsa`、`.git/config` 等路径会被拒绝并记入审计,`cmd /c "type .env"` 这类引号内的内联命令同样会被扫描。这条规则在沙箱关闭(包括默认配置)时仍然生效,因为 `read` / `write` 本来就拒绝这些路径;需要放行时设 `sandbox.allow_sensitive_files: true`。`git commit -m "document .env"` 这种引号内的文字不会被误判。
106
+ - 敏感名单新增 `.envrc`、`secrets.yaml` / `.yml` / `.toml`、`credentials.yaml` / `.yml` / `.toml` 与 `.git/config`,`grep` / `find` 也不再返回它们。`secrets.py`、`credentials.py` 仍可读写。
107
+ - 使用 `bwrap` / `firejail` / `sandbox-exec` / `docker` 后端时,`allowlist` 现在与 `deny` 一样隔离网络:容器无法执行主机白名单,此前它把后端进程整个放行,只剩字符串门禁。需要在容器里联网就改用 `allow`。
108
+ - 解析器会先按空行组装多行 `data:` 事件再解析,跨行长 JSON 不再被丢弃;省略 `index` 的并行工具调用按 `id` 归位,不再串包;`arguments` 以对象形式到达时覆盖已收到的片段。
109
+ - 非 UTF-8 的 Windows 控制台输出按当前控制台/OEM 代码页解码,不再整段变成 `�`。
110
+
111
+ 详见 [CHANGELOG.md](CHANGELOG.md)。
112
+
113
+ ### 从 1.4.2 升级到 1.4.3
114
+
115
+ 1.4.3 是缺陷修复版本,没有新增或删除任何公开名字、CLI 参数、配置键、JSON 字段、会话格式或工具 schema,升级不需要改代码。修复集中在安全闸门与搜索,其中几处会改变出错场景下的结果,需要留意:
116
+
117
+ - 沙箱网络策略补上四种此前完全看不见的写法:`env -S 'curl …'` / `--split-string`(该选项的值本身就是命令,旧版把它当普通选项值跳过)、`py -3 -m pip install …` / `python -mpip install …` / `python -m pip3 install …`(Windows 的 `py` 启动器与紧贴拼写)、PowerShell 内联的 `(New-Object Net.WebClient).DownloadString/DownloadFile`,以及 `\\host\share` 形式的 UNC 路径(SMB,不出现任何客户端名或 URL)。`deny` 下这些命令现在会被拒绝;`allowlist` 下 UNC 主机也会参与比对。
118
+ - 审计脱敏覆盖紧贴标志的凭据:`curl -uadmin:pw`、`--user=admin:pw`、`mysql -phunter2` 此前以明文写入拒绝记录,现在被标记为 `<redacted>`。`docker run -p 8080:80` 这类普通端口映射不受影响。
119
+ - `write` 保留文件原有的 UTF-8 BOM(此前只有 `edit` 保留,重写会静默改变整个文件的编码)。
120
+ - 校验器自身跑不起来(ruff 配置损坏、超时、工具缺失)时不再算作“内容有错”,新建的 Python 文件不会被回滚删除,改为在 `warnings` 里报告。
121
+ - `grep` / `find` 的 `glob` 现在按搜索根锚定:`find("deep/*.py", path="sub")`、`grep(..., glob="src/*.py")` 此前在装有 `rg` 时返回空结果(无 `rg` 的 Python 回退却能找到),模型会把“没找到”当成事实。含多次 `{a,b}` 的花括号展开也加了上限,不再指数级挂死。
122
+ - `grep` 结果不再被行内换页符、U+2028 或孤立 CR 切断并丢弃尾部文本。
123
+ - 供应商重试受 `timeout_seconds` 约束:此前连接退避会跑完整轮(1 秒超时实际可耗约 55 秒)。
124
+ - 兼容 Anthropic 的网关用 `data: [DONE]` 收尾时按正常结束处理,完整回答与工具调用不再被判为 `incomplete` 丢弃。
125
+
126
+ 详见 [CHANGELOG.md](CHANGELOG.md)。
127
+
128
+ ### 从 1.4.1 升级到 1.4.2
129
+
130
+ 1.4.2 是缺陷修复版本,没有新增或删除任何公开名字、CLI 参数、配置键、JSON 字段、会话格式或工具 schema,升级不需要改代码。修复覆盖安全闸门、工具循环、文件编辑、渲染与协议解析,其中几处会改变出错场景下的结果,需要留意:
131
+
132
+ - 沙箱网络策略更准也更严。内联命令现在按词边界切片,`sh -c "curl …" arg0`、`pwsh -Command "iwr …" x` 这类带尾随参数的写法不再漏检;PowerShell 的 `-ec` / `-e` / `-en` 等 `-EncodedCommand` 缩写会解码检查;`npx` / `bunx` 与 `curl.cmd` / `wget.ps1` 计入联网命令;嵌套层数超出预算按 fail-closed 处理。反方向的误报也修掉了:`bash -c "rm -f ./curl"` 这类引号内提到命令名的普通命令不再被拒绝。用 `allowlist` 时可能发现此前被放行的命令现在被拒,那正是修复的目标。
133
+ - `tools.max_parallel` 或 `subagent.max_parallel` 设为 1 时,一组相邻工具调用现在会逐个全部执行;此前只执行第一个,其余既没执行也没有工具结果,下一轮请求会把未配对的 `tool_call` 发给供应商。
134
+ - 文件工具:`edit` 保留 UTF-8 BOM、拒绝 NUL 字节,替换没有尾随换行的末行时按文件主导换行补丁。
135
+ - 会话:`--session` 指向用户自己的目录时不再改动该目录权限;末行缺少换行的会话文件会先补换行再追加;含孤立代理对的内容转义写入而不是让追加失败。
136
+ - 显式把 `shell.path` 配成 `cmd.exe` 现在直接报错;docker 后端拒绝 PowerShell 命令,而不是把它交给 `/bin/sh` 静默误执行。
137
+ - `/summary` 走工具策略写 `AGENTS.md`,在 `--read-only` 或 `tools.allow` 未放行 `write` 时会被拒绝。
138
+
139
+ 详见 [CHANGELOG.md](CHANGELOG.md)。
140
+
141
+ ### 从 1.4.0 升级到 1.4.1
142
+
143
+ 1.4.1 是缺陷修复版本,同时补了两个工具,没有删除任何公开名字、CLI 参数、配置键、JSON 字段或工具 schema,升级不需要改代码。新增 `read_range`(按行号读取窗口)与 `append_file`(EOF 追加,保留既有换行风格),`edit` 增加行号参数:`path` + `new_text` 是必填项,`old_text` 作为精确文本兜底保留,两者不能混用。`write` / `edit` / `append_file` 写入 Python 文件后会运行 `py_compile`,装有时再跑 `ruff`,出现新诊断就回滚。可观察的行为变化都是修正错误行为:`read` 结果多出 `line_ending` 字段;`settings.json` 只保存用户改过的键,升级后新增的默认值不再被旧文件里的全量副本掩盖;`--read-only` 的只读集合包含 `read_range`。其余修复(沙箱网络策略识别、搜索窗口、渲染状态、流式工具调用、配置脱敏)只改变出错场景下的结果。详见 [CHANGELOG.md](CHANGELOG.md)。
144
+
145
+ ### 从 1.3.2 升级到 1.4.0
146
+
147
+ 1.4.0 没有删除任何公开名字、CLI 参数、配置键、JSON 字段或工具 schema,升级不需要改代码。新增的是五个可选项:`--read-only`、`tools.allow`、`tools.max_parallel`(相邻只读工具并发数)、供应商的 `prompt_cache`,以及压缩后重写会话文件。可观察的行为变化只有三处,且都是修正错误行为:`read` 遇到非 UTF-8 内容时会在结果里带 `warnings` 字段(此前只返回 U+FFFD 且没有任何提示),UTF-8 BOM 不再显示为第一行的 `\ufeff`;被 `tools.allow` / `--read-only` 禁用的工具既不出现在工具定义里,直接调用也会返回错误;压缩后的大会话文件会被原子重写为「meta + 压缩状态」,此前同一段历史在文件里保存两份并整段重放。`read` 的常规结果多出一个只在出错时出现的 `warnings` 键,`/status` 多出 `read_only` 与 `tools` 两个字段。详见 [CHANGELOG.md](CHANGELOG.md)。
148
+
149
+ ### 从 1.3.1 升级到 1.3.2
150
+
151
+ 1.3.2 是缺陷修复版本,没有删除任何公开名字、CLI 参数、配置键、JSON 字段、会话格式或工具 schema,升级不需要改代码。可观察的行为变化都是修正错误行为:`grep` / `find` 现在隐藏全部敏感路径(此前开启 ripgrep 时 `.env-prod`、`KEY.PEM`、`Secrets` 会漏出),并且不再读取 `RIPGREP_CONFIG_PATH`;两条搜索路径的 glob 统一按 ripgrep 语义匹配,`*` 不再跨目录、Windows 上不再忽略大小写;`write` 拒绝含 NUL 的内容;恢复会话时若记录的 provider 不在配置里会报错,而不是把历史发给另一个协议;Windows 不再自动选用 `C:\Windows\System32\bash.exe` 这个 WSL 启动器;压缩与 `/summary` 的 token 用量计入统计。其余修复(流式与非流式协议解析、超时预算、搜索截断、渲染状态、并发 subagent)只改变出错场景下的结果。详见 [CHANGELOG.md](CHANGELOG.md)。
152
+
153
+ ### 从 1.3.0 升级到 1.3.1
154
+
155
+ 1.3.1 是缺陷修复版本,没有删除任何公开名字、CLI 参数、配置键、JSON 字段、会话格式或工具 schema,升级不需要改代码。可观察的行为变化只有两处,且都是修正错误行为:stdout 读取端提前关闭(`minimalcode ... | head`)现在按 `0` 退出,不再在 Windows 上打印 `error: [Errno 22] Invalid argument` 并以 `2` 退出;`--home` 写在管理命令前面时(`minimalcode --home DIR sessions`)按管理命令执行,不再把命令词当成提示词发给模型。其余修复(协议解析、压缩边界、搜索回退语义、沙箱网络识别、`trust_env` 布尔转换)都只改变出错场景下的结果。详见 [CHANGELOG.md](CHANGELOG.md)。
156
+
157
+ ### 从 1.2 升级到 1.3
158
+
159
+ 1.3.0 没有删除任何公开名字、CLI 参数、配置键、JSON 字段或会话格式,升级不需要改代码。新增的是交互式剪贴板图片粘贴:空回车读取系统剪贴板里的图片,经供应商 `vision` 配置转成文字描述后随消息发送。可观察的行为变化有四处:JSON API 请求遇到 3xx 现在直接报错而不是跟随跳转(跳转会重发请求体与 `x-api-key` 等认证头);新建文件按进程 umask 创建,不再固定 `0600`;`config set-model` 同时更新当前供应商的 `model`;恢复会话时沿用会话记录的供应商与模型,显式 `--provider` / `--model` 仍然优先。`requires-python` 收窄为 `>=3.11,<3.14`。详见 [CHANGELOG.md](CHANGELOG.md)。
160
+
161
+ ### 从 1.1 升级到 1.2
162
+
163
+ 1.2.0 没有删除任何公开名字、CLI 参数、配置键或 JSON 字段,升级不需要改代码。新增的是:`anthropic_messages` 协议、`--anthropic-env`(与 `--provider` 互斥)、交互命令 `/model [供应商/模型]`,以及 `defaults.json` 里的 33 家托管供应商加 `ollama`、`lmstudio`、`vllm` 三个本地预设。预设走常规的默认值合并,已有 `settings.json` 里同名的供应商保留自己设置的键;因此对未改动配置的用户,唯一可见的差异是 `config show`、`minimalcode sessions` 和 `/model` 列表里多出了 `deepseek-anthropic` 与这些供应商。`/model` 只切换当前会话,不写回配置。详见 [CHANGELOG.md](CHANGELOG.md)。
164
+
165
+ ### 从 1.0 升级到 1.1
166
+
167
+ 1.1.0 没有删除任何公开名字、CLI 参数、配置键或 JSON 字段,升级不需要改代码。可观察的变化只有两处:系统提示会在每次运行开始时重新读取 `AGENTS.md` / `CLAUDE.md`(此前在进程启动时缓存一次),以及新增的交互命令 `/summary`(只在交互模式下可用,`-p` 一次性运行不受影响)。详见 [CHANGELOG.md](CHANGELOG.md)。
168
+
169
+ ### 从 0.8 升级到 1.0
170
+
171
+ 1.0.0 是首个稳定版本。从 1.0 起,CLI 参数、配置键、JSON 输出字段、会话格式,以及 `tools`、`sandbox`、`provider`、`highlight` 四个包的 `__all__` 公开面在 1.x 内保持兼容。0.8 → 1.0 没有删除公开名字或 CLI 参数,但修复项里有两处可观察行为变化:`--json` 的 `usage` 改为本次运行(累计值在 `session_usage`),`import-pi` 默认不再复制 API key。详见 [CHANGELOG.md](CHANGELOG.md)。
172
+
173
+ ### 从 0.6 升级到 0.7
174
+
175
+ 0.7.0 把 `tools`、`sandbox`、`provider`、`highlight` 四个大模块拆成了包,并在发布前移除了拆包过程中临时保留的旧名字回退。CLI、配置和工具行为没有变化;只有直接导入内部名字或 patch 内部函数的代码需要迁移:
176
+
177
+ - `minimalcode.tools`、`minimalcode.sandbox`、`minimalcode.provider`、`minimalcode.highlight` 现在只导出各自 `__all__` 中的公开名称,未知名字直接抛 `AttributeError`。
178
+ - 私有 helper 改为从实现模块导入,例如 `minimalcode.tools.search.run_python_grep`、`minimalcode.sandbox.execution._posix_limits`、`minimalcode.highlight.palette._PALETTES`。
179
+ - patch 目标要指向实际查找该名字的模块,例如 `minimalcode.tools.search_tools.shutil.which`、`minimalcode.provider.transport.time.sleep`、`minimalcode.highlight.color._supports_color`。
180
+
181
+ 完整对照表见 [docs/compatibility.md](docs/compatibility.md)。
182
+
183
+ 0.7 → 0.8 只补充文档与注释、补全供应商重试策略的测试,公开面与 0.7.0 一致,升级无需改代码。
184
+
185
+ ## 快速开始
186
+
187
+ 推荐 API:[<img src="https://www.deepseek.com/favicon.ico" width="16" height="16" alt="DeepSeek 图标"> DeepSeek 开放平台](https://platform.deepseek.com)
188
+
189
+ ```powershell
190
+ $env:DEEPSEEK_API_KEY = "your-key"
191
+ minimalcode
192
+ ```
193
+
194
+ 交互模式启动后会显示供应商/模型、当前工作区、shell 和会话文件路径。
195
+
196
+ 输入支持多行:行尾写 `\` 回车继续下一行(`... ` 提示符),行尾 `\\` 表示字面反斜杠;也可以直接粘贴整段长文本,粘贴块里的换行不会被当作多次提交,整段内容作为一条消息发送。`-p` 或管道输入时不做改写。
197
+
198
+ 如果剪贴板里是图片,先按终端的粘贴快捷键(Windows 为 `Ctrl+V`,macOS 为 `Cmd+V`,多数 Linux 终端为 `Ctrl+Shift+V`)再回车即可发送:终端本身无法把图片粘进输入行,所以 MinimalCode 把空回车当作读取剪贴板的信号。随后可以输入要一起发送的问题再回车;直接回车则让视觉模型完整描述图片。图片不需要事先保存成文件,由供应商 `vision` 配置的视觉模型转成文字描述后随消息一起发给主模型;未配置 `vision` 时该功能不可用。
199
+
200
+ 单次任务:
201
+
202
+ ```powershell
203
+ minimalcode "找出这个项目测试失败的原因并修好"
204
+ minimalcode -p "运行测试并总结" --json
205
+ ```
206
+
207
+ `-p/--print` 表示非交互执行,必须同时给出提示词或通过标准输入管道传入;`--json` 隐含该模式。
208
+
209
+ ## CLI 参考
210
+
211
+ ```text
212
+ minimalcode [prompt ...] [options]
213
+ ```
214
+
215
+ | 选项 | 说明 |
216
+ |---|---|
217
+ | `prompt ...` | 初始消息。给出后执行一轮任务并退出 |
218
+ | `-p`, `--print` | 非交互模式;缺少提示词时报错 |
219
+ | `--json` | 输出 JSON 并隐含 `--print`,同时隐藏工具活动 |
220
+ | `-c`, `--continue` | 继续当前目录最近一次会话 |
221
+ | `--session <id>` | 指定会话:完整 ID、前缀或 `.jsonl` 路径 |
222
+ | `--no-session` | 本次运行不读写会话 |
223
+ | `--provider <name>` | 覆盖配置中的供应商 |
224
+ | `--anthropic-env` | 用 Claude Code 风格的 `ANTHROPIC_*` / `CLAUDE_CODE_*` 环境变量直接启动 Anthropic Messages 协议,不修改配置文件;不能与 `--provider` 同用 |
225
+ | `-m`, `--model <id>` | 覆盖模型 |
226
+ | `--thinking <effort>` | 覆盖推理强度:`none`(关闭)、`minimal`、`low`、`medium`、`high`、`xhigh`、`ultra`、`max` |
227
+ | `--max-turns <n>` | 覆盖最大工具轮次(1–10000) |
228
+ | `--read-only` | 只保留 `read`、`grep`、`find`、`read_image`、`web_search`、`web_fetch`,拒绝任何可能改动工作区的工具 |
229
+ | `--cwd <dir>` | 指定工作区 |
230
+ | `--home <dir>` | 指定配置目录,默认 `~/.MinimalCode` |
231
+ | `--sandbox`, `--no-sandbox` | 开启/关闭沙箱执行层(默认关闭,等价于默认 `--no-sandbox`)。无论开关,文件工具的工作区与敏感文件边界都生效 |
232
+ | `--sandbox-backend <name>` | `auto`、`local`、`bwrap`、`firejail`、`sandbox-exec`、`docker` |
233
+ | `--sandbox-root <path>` | 额外允许的读写根,可重复 |
234
+ | `--sandbox-network <policy>` | `deny`(默认)、`allowlist`、`allow` |
235
+ | `--sandbox-allow-host <host>` | `allowlist` 允许的主机,可重复 |
236
+ | `--sandbox-timeout <sec>` | 单条命令的硬超时 |
237
+ | `--sandbox-max-output <chars>` | 单条命令返回的 stdout/stderr 上限 |
238
+ | `--sandbox-allow-sensitive` | 允许访问 `.env`、私钥等敏感文件 |
239
+ | `--quiet` | 隐藏工具活动和 token 用量摘要 |
240
+ | `--no-highlight` | 关闭 Markdown 高亮 |
241
+ | `--version` | 打印版本 |
242
+
243
+ 管理命令按第一个词识别,`--home` 可以写在命令前面(`minimalcode --home DIR sessions` 等价于 `minimalcode sessions --home DIR`);其他选项写在前面时会被当成普通提示词。以命令词开头的提示词需要用 `--` 分隔:`minimalcode -- init config show` 发送的是提示词而不是执行子命令。
244
+
245
+ 管理命令:
246
+
247
+ | 命令 | 说明 |
248
+ |---|---|
249
+ | `minimalcode init [--force]` | 创建配置目录与 `settings.json` |
250
+ | `minimalcode config [show]` | 打印合并后的配置,敏感字段显示为 `<redacted>` |
251
+ | `minimalcode config path` | 打印配置文件路径 |
252
+ | `minimalcode config set-model <id>` | 写入默认模型 |
253
+ | `minimalcode config set-provider <name>` | 写入默认供应商 |
254
+ | `minimalcode sessions` | 列出已保存会话(时间、ID、模型、工作区) |
255
+ | `minimalcode shell` | 显示探测到的 shell |
256
+ | `minimalcode sandbox` | 打印当前沙箱策略与各后端可用性 |
257
+ | `minimalcode import-pi` | 从 Pi 配置迁移供应商、模型和上下文窗口 |
258
+
259
+ `import-pi` 默认**不**复制 API key,而是写入指向环境变量的 `api_key_env`;确实要把密钥复制进权限受限的配置时加 `--secrets`(密钥不会在终端打印)。`--pi-home` 指定 Pi 目录,`--overwrite` 允许覆盖已有供应商。
260
+
261
+ 退出码:`0` 任务完成,`1` 未在轮次上限内完成,`2` 配置或运行错误,`130` 被 Ctrl+C 中断。stdout 的读取端提前关闭(例如 `minimalcode ... | head`)按 `0` 退出,不会打印错误或 `Exception ignored`。
262
+
263
+ JSON 输出字段:
264
+
265
+ ```json
266
+ {"text":"...","completed":true,"turns":3,"usage":{},"session_usage":{},"usage_estimated":false,"session":"...jsonl"}
267
+ ```
268
+
269
+ `usage` 是本次运行新增的用量,`session_usage` 是整个会话的累计值(`-c` 继续会话时两者不同);`usage_estimated` 为 `true` 表示至少有一轮没有供应商返回的 usage,数字来自本地估算。
270
+
271
+ ## 交互命令
272
+
273
+ | 命令 | 作用 |
274
+ |---|---|
275
+ | `/new`、`/clear` | 新建会话 |
276
+ | `/compact` | 立即压缩历史 |
277
+ | `/summary` | 让模型总结全部上下文并写入工作区 `AGENTS.md`;文件不存在则创建,已存在则只更新 `<!-- minimalcode:summary:start/end -->` 之间的块,其余内容原样保留 |
278
+ | `/session` | 显示会话文件路径 |
279
+ | `/effort [none\|minimal\|low\|medium\|high\|xhigh\|ultra\|max]` | 查看或修改本次运行的推理强度;`none` 关闭思考 |
280
+ | `/model [供应商/模型]` | 查看当前模型和可用供应商(只列出已检测到凭据的,含免密钥的本地预设);给出 `供应商/模型` 时切换本次会话,例如 `/model deepseek/deepseek-flash`。只切换当前会话,不写回 `settings.json` |
281
+ | `/status` | 显示模型、推理强度、shell、上下文和 token 统计(JSON) |
282
+ | `/help` | 显示命令 |
283
+ | `/exit`、`/quit` | 退出 |
284
+
285
+ 未知的 `/` 命令只报错,不会结束会话。多行消息的行间换行会原样保留在会话记录里。
286
+
287
+ ## 工具
288
+
289
+ | 工具 | 作用 | 主要参数 |
290
+ |---|---|---|
291
+ | `read` | 按行范围读取 UTF-8 文本,输出带行号并报告 `line_ending`;非 UTF-8 内容会带 `warnings` 提示 | `path`、`start_line`、`end_line` |
292
+ | `read_range` | 读取显式行区间(带行号),用于行号编辑前确认目标 | `path`、`start_line`、`end_line` |
293
+ | `write` | 创建或整体覆盖文件 | `path`、`content` |
294
+ | `append_file` | 在 EOF 追加文本,文件不存在时创建,保留既有换行风格 | `path`、`content` |
295
+ | `edit` | 按行号替换区间,`end_line = start_line - 1` 表示在该行前插入;`old_text` 是精确文本兜底,两者不能混用 | `path`、`start_line`、`end_line`、`new_text`、`old_text`、`replace_all` |
296
+ | `shell` | 在配置的 shell 中执行命令 | `command`、`timeout`、`cwd` |
297
+ | `grep` | 正则搜索文本,返回 `path:line:text` | `pattern`、`path`、`glob`、`max_results` |
298
+ | `find` | 按 glob 查找文件 | `pattern`、`path`、`max_results` |
299
+ | `subagent` | 在子 shell 中启动一个新的 `minimalcode`,只返回它的最终答复 | `task`、`cwd`、`timeout`、`max_turns` |
300
+ | `read_image` | 读取本地图片并交给配置的 OpenAI 兼容视觉端点,返回描述或对 `prompt` 的回答 | `path`、`prompt` |
301
+ | `web_search` | 通过供应商检索网页 | `query`、`count`、`need_content` |
302
+ | `web_fetch` | 通过供应商抓取 HTTP/HTTPS 页面 | `url` |
303
+
304
+ `web_search`、`web_fetch` 由供应商的 `web_tools` 配置启用;`read_image` 由供应商的 `vision` 配置启用。未启用的供应商既收不到对应的工具定义,直接调用也会被拒绝。
305
+
306
+ `tools.allow` 给出允许的工具名列表(例如 `["read", "grep", "find"]`),`--read-only` 是它的一种预设。两者取交集,且被禁用的工具不会出现在请求的 `tools` 里;即使模型仍然发起调用(恢复的旧会话、忽略 schema 的供应商),`dispatch` 也会返回形如 `tool 'write' is disabled by --read-only` 的错误。只读模式下列表以外的工具一律不可用,包括 `subagent`(它会启动一个能写文件的子进程)。
307
+
308
+ `subagent` 默认开启,但受 `subagent.enabled` 和 `subagent.max_depth` 约束;超过嵌套深度的子进程既收不到该工具定义,直接调用也会被拒绝。同一轮里相邻的多个 `subagent` 调用会并发执行(上限 `subagent.max_parallel`,默认 4),结果仍按请求顺序写回会话;它们不会与相邻的其他工具重叠,因为 `write` 后接 `shell` 这类顺序是有意义的。相邻的只读工具(`read`、`read_range`、`grep`、`find`、`read_image`、`web_search`、`web_fetch`)同样会并发执行,上限 `tools.max_parallel`。子进程就是一条命令,因此开启沙箱执行层时其超时还要再受 `sandbox.timeout_seconds` 约束:`subagent.timeout_seconds` 更大时会被压到该值,并在 `minimalcode sandbox` / `/status` 的 `notes` 中记录;执行层关闭时只受 `subagent.timeout_seconds` 约束。
309
+
310
+ `write`、`edit`、`append_file` 写入 Python 文件后会先跑 `py_compile`,装有时再跑 `ruff`;出现新诊断就原子回滚并返回文件、行号和源码预览。改动前已经存在的 lint 问题不会阻塞无关编辑。
311
+
312
+ ### 图像理解
313
+
314
+ `read_image` 是通用工具,不绑定某个供应商,也不受供应商自身 `protocol` 限制:只要在供应商配置里加一个 `vision` 块,指向任意 OpenAI 兼容的 `/chat/completions` 端点,该供应商就能获得这个工具。`base_url`、`model` 和密钥默认沿用供应商的同名字段,也可以单独覆盖:
315
+
316
+ ```json
317
+ "vision": {
318
+ "enabled": true,
319
+ "base_url": "https://api.example.com/v1",
320
+ "model": "vision-model",
321
+ "timeout_seconds": 120,
322
+ "max_image_bytes": 33554432,
323
+ "max_chars": 8000,
324
+ "detail": "auto",
325
+ "api_key_env": "EXAMPLE_API_KEY",
326
+ "headers": {}
327
+ }
328
+ ```
329
+
330
+ - 图片以 base64 data URL 内联发送,格式按文件内容判断,支持 JPEG、PNG、GIF 和 WebP,不依赖扩展名。
331
+ - 交互模式下也可以直接从剪贴板粘贴图片:按终端的粘贴快捷键后再回车(Windows `Ctrl+V`、macOS `Cmd+V`、多数 Linux 终端 `Ctrl+Shift+V`),不需要先保存文件。MinimalCode 调用同一个 `vision` 配置读取剪贴板图片并生成描述;图片超过 `max_image_bytes`、剪贴板里没有图片或读取失败时会报错并继续会话。
332
+ - `prompt` 可选;缺省时要求模型详细描述图片并逐字转写可见文字,结果超过 `max_chars` 时截断并标记 `<description truncated>`。
333
+ - `read_image` 和其他文件工具一样受工作区限制,读取工作区外的图片需要 `tools.allow_outside_workspace`。
334
+ - 内置默认配置只为 DeepSeek 打开了 `vision`(`deepseek-flash`),其他供应商默认关闭,需要时按上面的结构自行添加。
335
+
336
+ ### 实现要点
337
+
338
+ - **工作区约束**:所有接受路径的工具都经同一处校验。相对路径以工作区为基准,解析后必须位于工作区内;`tools.allow_outside_workspace: true` 可放行外部路径,但仍受敏感文件策略约束。`shell` 与 `subagent` 同样经过沙箱入口,命令的工作目录和解析后的符号链接都在允许根内。`--no-sandbox` 只关闭执行层(后端包装、网络策略、资源限制),工作区与敏感文件边界照旧生效。
339
+ - **沙箱执行层**:`sandbox.enabled` 默认关闭(等同默认 `--no-sandbox`),`--sandbox` 或任意 `--sandbox-*` 选项会开启它;开启后默认后端 `local`(跨平台策略与子进程限制基线),可选 `auto`(Linux 依次尝试 `bwrap`、`firejail`,macOS 尝试 `sandbox-exec`,否则 `local`)以及 `bwrap`、`firejail`、`sandbox-exec`、`docker`。默认网络策略 `deny`,默认拒绝 `.env`、私钥、`.ssh/`、`.aws/` 等敏感路径。开启时路径逃逸、符号链接逃逸、敏感文件、网络命令、后端缺失都会 fail-closed 拒绝并记录原因。命令统一受 `sandbox.timeout_seconds`、`sandbox.max_output_chars` 和子进程资源上限约束,临时目录用后删除。详见 `docs/configuration.md` 的 Sandbox 一节。
340
+ - **grep / find**:检测到 `rg` 时直接以参数数组调用子进程(`rg --no-config --line-number --no-heading --color never --smart-case ...` 和 `rg --files --glob ...`),不拼接命令行字符串;没有 `rg` 时退回 Python 的 `re` + `os.walk`,并用独立子进程执行正则,超时会终止。两条路径跳过相同的忽略目录(`.git`、`node_modules`、`build`、`dist`、缓存和虚拟环境),支持相同的 smart-case 语义和相同的 glob 语义(`*` 不跨目录、`**/` 可匹配零层、大小写敏感),都不解析 `.gitignore`,也都不受 `RIPGREP_CONFIG_PATH` 影响;显式把 `path` 指向 `build` 等目录时仍会搜索该目录。两条路径的输出都再经过一次敏感文件策略过滤,被沙箱截断产生的标记行不会作为匹配返回。单行结果按 300 字符截断,`rg`/`find` 输出达到上限即停止读取。
341
+ - **shell**:自动探测会先用一条 `exit 0` 验证候选 shell 能否真正启动,`pwsh` 因缺少 libicu、.NET 无法预留内存或架构不符而崩溃时会继续尝试 `bash` → `zsh` → `sh`(Windows 为 `powershell` → Git Bash);探测结果按可执行文件缓存,每个进程只付一次启动开销(pwsh 约 0.2 秒)。Windows 上 `System32\bash.exe` 与 `WindowsApps\bash.exe`(WSL 或应用商店启动器)不会作为原生 shell 候选,`pwsh-preview` / `powershell-preview` 按对应的 PowerShell 处理。显式配置的 `shell.path` 同样会验证,启动失败会直接报出原因而不是静默换 shell;`cmd.exe` 会被直接拒绝,因为它不接受 `-c`,用 `-c` 启动只会打印横幅、退出 0 而什么都不执行。`pwsh`/`powershell` 以 `-NoLogo -NoProfile -NonInteractive -Command` 启动,并在命令前注入 bootstrap:关闭进度条、`$ErrorActionPreference='Stop'`、控制台输出编码设为无 BOM 的 UTF-8。bash/zsh/sh 分别使用 `-c` 及各自的 no-profile 参数。stdout/stderr 由后台线程持续读取,只在内存中保留首尾有界片段,因此超长输出不会占满磁盘或内存,超时后仍能返回已产生的部分输出。超时会终止整个进程树(Windows 用 `taskkill /T`,POSIX 用进程组)。
342
+ - **误报网络命令**:`local` 基线的 `deny` 基于命令字符串识别,只读的 `python -m pip show/list`、`pip --version` 会被放行,`pip install/download` 等会触网子命令才会被拒绝。
343
+ - **资源限制**:POSIX 下对子进程设置 `RLIMIT_CORE` 和按超时推算的 `RLIMIT_CPU`;Linux 的 `RLIMIT_AS`(`sandbox.max_memory_mb`)和 `RLIMIT_NPROC`(`sandbox.max_processes`)默认关闭,因为 `RLIMIT_AS` 限制的是预留地址空间而非实际占用,2 GB 的默认值会让 .NET(pwsh)、JVM、Go 子进程在真正运行前就报 `Out of memory`。
344
+ - **subagent**:没有新的子协议,就是一条 shell 命令 `<python> -m minimalcode -p --no-session --quiet`,透传父进程的 `--provider` / `-m` / `--thinking` / `--home` / 工作区。任务正文通过 stdin 传入,因此提示词不会出现在命令行里,也没有引号转义问题;PowerShell 使用调用运算符 `&`,并在末尾用空值安全的 `exit` 保留子进程真实退出码(无法启动时返回 1)。子进程通过 `MINIMALCODE_SUBAGENT_DEPTH` 得知自己的层级,超过 `subagent.max_depth` 后不再获得 `subagent` 工具;`PYTHONPATH` 指向当前包所在目录,因此子进程跑的是同一份代码。
345
+ - **网络重试**:请求在拿到响应之前失败(`ConnectError`、`ConnectTimeout`,以及 `Server disconnected without sending a response.` 这类 `RemoteProtocolError`)会自动重试 10 次,退避从 0.5 秒翻倍到最多 8 秒;已经开始返回数据的流式中断不重试,避免重复输出或重复计费。HTTP 429/503 仍按 `Retry-After` 重试一次。
346
+ - **输出裁剪**:工具结果按首尾保留截断,超长输出中间以 `... <truncated N chars> ...` 标记,既保留开头上下文也保留结尾错误信息。
347
+ - **编码与并发**:`read` 先用 `errors="strict"` 扫描请求范围,只有真正遇到非 UTF-8 字节时才退回替换解码并写 `warnings`,因此正常文件不多读一遍、也不会把有损内容当成干净内容。同一轮的只读调用走同一个分组器:结果按调用顺序回填,`[read]` 等活动行仍在主线程打印;`write` / `edit` / `shell` / `subagent` 不参与并发,紧挨着它们的只读调用也留在主线程。
348
+
349
+ ## 配置
350
+
351
+ 默认目录:
352
+
353
+ ```text
354
+ ~/.MinimalCode/
355
+ ├── settings.json # 自动创建,与包内 defaults.json 深度合并
356
+ ├── SYSTEM.md # 可选,替换默认系统提示词
357
+ ├── AGENTS.md # 可选,全局规则
358
+ └── sessions/ # 按工作区分组的 JSONL 会话
359
+ ```
360
+
361
+ 配置目录可用 `MINIMALCODE_HOME` 或 `--home` 覆盖。
362
+
363
+ 默认供应商是 DeepSeek,使用 Responses 协议和环境变量中的密钥:
364
+
365
+ ```json
366
+ {
367
+ "provider": "deepseek",
368
+ "model": "deepseek-flash",
369
+ "thinking": "high",
370
+ "max_turns": 1000,
371
+ "providers": {
372
+ "deepseek": {
373
+ "protocol": "openai_responses",
374
+ "base_url": "https://api.deepseek.com/v1",
375
+ "api_key_env": "DEEPSEEK_API_KEY",
376
+ "context_window": 1000000,
377
+ "timeout_seconds": 120,
378
+ "stream": true,
379
+ "include_usage": false,
380
+ "send_reasoning_effort": true,
381
+ "headers": {},
382
+ "extra_body": {}
383
+ }
384
+ }
385
+ }
386
+ ```
387
+
388
+ - `protocol` 取 `openai_chat`、`openai_responses`、`anthropic_messages` 或 `deepseek_web`(网页版对话接口,见 [docs/configuration.md](docs/configuration.md#deepseek-web-chatdeepseekcom))。
389
+ - 密钥优先用 `api_key_env` 指向环境变量;直接写 `api_key` 也支持,但要注意文件权限。密钥不会由 `init` 写入配置。
390
+ - 任意字符串值支持 `${VAR}` 环境变量占位符,未解析时会明确报出变量名,而不是把占位符发给供应商。
391
+ - `include_usage` 仅在服务端接受 `stream_options` 时开启(仅 Chat 使用);`send_reasoning_effort` 仅在供应商支持时开启。Responses 模式下的 `thinking` 只有配合 `send_reasoning_effort: true` 才会作为 `reasoning.effort` 发送;`none` 会发送 `reasoning.effort: "none"`,Chat 模式则发送 `thinking: {"type": "disabled"}` 关闭思考。Anthropic 模式同样由 `send_reasoning_effort` 控制是否发送 `thinking`。
392
+ - `max_tokens` 仅 Anthropic Messages 使用,默认 `8192`。官方 Anthropic API 要求该字段;`thinking` 的 `budget_tokens` 会按 `thinking` 等级映射,并保证小于 `max_tokens`。
393
+ - `prompt_cache: true` 只对 Anthropic Messages 生效:给 system 提示与工具定义打一个 `cache_control` 缓存断点,长工具循环里这段静态前缀按缓存读取计费。默认关闭,因为部分兼容端点不接受该字段。
394
+ - 其他兼容供应商沿用同一结构,替换 `base_url`、模型和密钥环境变量即可。
395
+ - 代理:供应商、`web_tools`、`vision` 默认沿用环境变量与系统代理设置。`base_url` 指向环回地址(`127.0.0.1`、`::1`、`localhost`)时自动忽略代理,否则本机运行的 Ollama、vLLM 或测试服务器会被 Clash 之类的代理劫走;需要强制时可在对应配置块里写 `"trust_env": true|false`。显式传入自建 transport 时默认不读环境代理,避免代理映射覆盖注入的连接。
396
+
397
+ ### 内置供应商预设
398
+
399
+ `defaults.json` 已经为常用供应商准备好端点、协议和密钥环境变量。它们不会猜模型 ID:交互中用 `/model 供应商/模型` 时显式给出模型,例如:
400
+
401
+ ```text
402
+ /model deepseek/deepseek-flash
403
+ /model openai/<model-id>
404
+ /model anthropic/<model-id>
405
+ /model moonshot/<model-id>
406
+ ```
407
+
408
+ | 供应商 | API key 环境变量 | 端点 |
409
+ |---|---|---|
410
+ | `deepseek` | `DEEPSEEK_API_KEY` | `https://api.deepseek.com/v1`(Responses) |
411
+ | `deepseek-anthropic` | `DEEPSEEK_API_KEY` | `https://api.deepseek.com/anthropic`(Anthropic Messages) |
412
+ | `openai` | `OPENAI_API_KEY` | `https://api.openai.com/v1`(Responses) |
413
+ | `anthropic` | `ANTHROPIC_API_KEY` | `https://api.anthropic.com/v1`(Anthropic Messages) |
414
+ | `google` | `GEMINI_API_KEY` | `https://generativelanguage.googleapis.com/v1beta/openai` |
415
+ | `openrouter` | `OPENROUTER_API_KEY` | `https://openrouter.ai/api/v1` |
416
+ | `groq` | `GROQ_API_KEY` | `https://api.groq.com/openai/v1` |
417
+ | `mistral` | `MISTRAL_API_KEY` | `https://api.mistral.ai/v1` |
418
+ | `xai` | `XAI_API_KEY` | `https://api.x.ai/v1` |
419
+ | `moonshot` | `MOONSHOT_API_KEY` | `https://api.moonshot.cn/v1` |
420
+ | `zhipu` | `ZHIPUAI_API_KEY` | `https://open.bigmodel.cn/api/paas/v4` |
421
+ | `dashscope` | `DASHSCOPE_API_KEY` | `https://dashscope.aliyuncs.com/compatible-mode/v1` |
422
+ | `siliconflow` | `SILICONFLOW_API_KEY` | `https://api.siliconflow.cn/v1` |
423
+ | `together` | `TOGETHER_API_KEY` | `https://api.together.ai/v1` |
424
+ | `fireworks` | `FIREWORKS_API_KEY` | `https://api.fireworks.ai/inference/v1` |
425
+ | `perplexity` | `PERPLEXITY_API_KEY` | `https://api.perplexity.ai` |
426
+ | `cerebras` | `CEREBRAS_API_KEY` | `https://api.cerebras.ai/v1` |
427
+ | `sambanova` | `SAMBANOVA_API_KEY` | `https://api.sambanova.ai/v1` |
428
+ | `nebius` | `NEBIUS_API_KEY` | `https://api.studio.nebius.com/v1` |
429
+ | `deepinfra` | `DEEPINFRA_TOKEN` | `https://api.deepinfra.com/v1/openai` |
430
+ | `novita` | `NOVITA_API_KEY` | `https://api.novita.ai/openai/v1` |
431
+ | `cohere` | `COHERE_API_KEY` | `https://api.cohere.ai/compatibility/v1` |
432
+ | `github` | `GITHUB_TOKEN` | `https://models.github.ai/inference` |
433
+ | `volcengine` | `ARK_API_KEY` | `https://ark.cn-beijing.volces.com/api/v3` |
434
+ | `minimax` | `MINIMAX_API_KEY` | `https://api.minimax.io/v1` |
435
+ | `hunyuan` | `HUNYUAN_API_KEY` | `https://api.hunyuan.cloud.tencent.com/v1` |
436
+ | `qianfan` | `QIANFAN_API_KEY` | `https://qianfan.baidubce.com/v2` |
437
+ | `modelscope` | `MODELSCOPE_API_KEY` | `https://api-inference.modelscope.cn/v1` |
438
+ | `baichuan` | `BAICHUAN_API_KEY` | `https://api.baichuan-ai.com/v1` |
439
+ | `yi` | `YI_API_KEY` | `https://api.lingyiwanwu.com/v1` |
440
+ | `stepfun` | `STEP_API_KEY` | `https://api.stepfun.com/v1` |
441
+ | `spark` | `SPARK_API_PASSWORD` | `https://spark-api-open.xf-yun.com/v1` |
442
+ | `ppio` | `PPIO_API_KEY` | `https://api.ppio.com/openai/v1` |
443
+ | `ollama` | 无需密钥 | `http://localhost:11434/v1` |
444
+ | `lmstudio` | 无需密钥 | `http://localhost:1234/v1` |
445
+ | `vllm` | 无需密钥 | `http://localhost:8000/v1` |
446
+
447
+ 预设只固定端点和密钥变量名,`context_window` 保持一个保守值(本地三家为 `32768`,其余按各家公开的主推窗口填写),换到更大或更小的模型时按需在 `settings.json` 里调整。区域或套餐端点不同时(例如 MiniMax 国内站 `https://api.minimax.cn/v1`、StepFun 国际站 `https://api.stepfun.ai/v1`、火山方舟 `step_plan` 端点),覆盖 `base_url` 即可;Cohere 的兼容端点不接受 `stream_options`,所以预设里 `include_usage` 为 `false`。
448
+
449
+ `/model` 切换的是当前会话,不会修改 `settings.json`;要改默认值仍用 `minimalcode config set-provider` / `set-model`。切换后子代理也会继承新的供应商和模型。新供应商如果没有配置 `web_tools` / `vision`,对应的 `web_search`、`web_fetch`、`read_image` 工具会从工具列表中移除,切回带这些配置的供应商后恢复。
450
+
451
+ Anthropic Messages 模式可以直接接入 DeepSeek 的 Anthropic 兼容端点,内置预设 `deepseek-anthropic`:
452
+
453
+ ```json
454
+ "deepseek-anthropic": {
455
+ "protocol": "anthropic_messages",
456
+ "base_url": "https://api.deepseek.com/anthropic",
457
+ "api_key_env": "DEEPSEEK_API_KEY",
458
+ "model": "deepseek-flash",
459
+ "context_window": 1000000,
460
+ "timeout_seconds": 120,
461
+ "stream": true,
462
+ "send_reasoning_effort": true,
463
+ "max_tokens": 8192,
464
+ "headers": {},
465
+ "extra_body": {}
466
+ }
467
+ ```
468
+
469
+ ```powershell
470
+ $env:DEEPSEEK_API_KEY = "your-key"
471
+ minimalcode --provider deepseek-anthropic "运行测试并总结"
472
+ ```
473
+
474
+ 端点从 `base_url` 推导:`https://api.deepseek.com/anthropic` 会请求 `/anthropic/v1/messages`;`base_url` 已以 `/v1` 结尾时只补 `/messages`,已经是完整 `/messages` 地址时原样使用。鉴权发送 `x-api-key`,并附带 `anthropic-version: 2023-06-01`(自定义 `headers` 中的同名字段优先)。工具定义会转换为 Anthropic 的 `name` / `description` / `input_schema`,连续的工具结果会合并到同一条 user 消息,且 `tool_result` 块放在文本之前。思考模式下通过工具调用继续对话时,assistant 的 thinking 块(含 signature)会保存在会话中并原样回传,以保证 Anthropic 的多轮工具调用可以继续。需要复用系统提示与工具定义的缓存时,在该供应商里加上 `"prompt_cache": true`;内置预设默认不开,避免端点不支持 `cache_control` 时整轮请求失败。
475
+
476
+ ### 从 Claude Code 环境变量启动
477
+
478
+ 如果本机已经按 [DeepSeek 的 Claude Code 接入文档](https://api-docs.deepseek.com/zh-cn/quick_start/agent_integrations/claude_code)配好了环境变量,可以跳过配置文件直接用:
479
+
480
+ ```powershell
481
+ $env:ANTHROPIC_BASE_URL="https://api.deepseek.com/anthropic"
482
+ $env:ANTHROPIC_AUTH_TOKEN="<你的 DeepSeek API Key>"
483
+ $env:ANTHROPIC_MODEL="deepseek-flash[1m]"
484
+ $env:CLAUDE_CODE_EFFORT_LEVEL="max"
485
+ $env:CLAUDE_CODE_AUTO_COMPACT_WINDOW="786432"
486
+
487
+ minimalcode --anthropic-env
488
+ ```
489
+
490
+ `--anthropic-env` 只在本进程内合成一个名为 `anthropic-env` 的供应商,不读写 `settings.json`,因此普通启动(不带该参数)仍然使用文件配置;它也不能与 `--provider` 同时使用。
491
+
492
+ | 环境变量 | 作用 |
493
+ |---|---|
494
+ | `ANTHROPIC_BASE_URL` | 端点根,默认 `https://api.deepseek.com/anthropic` |
495
+ | `ANTHROPIC_AUTH_TOKEN` | Bearer 凭据,作为 `Authorization: Bearer` 发送;与 `ANTHROPIC_API_KEY` 同时存在时优先 |
496
+ | `ANTHROPIC_API_KEY` | 作为 `x-api-key` 发送(两者至少需要一个) |
497
+ | `ANTHROPIC_MODEL` | 模型名;缺省时回退到 `ANTHROPIC_DEFAULT_SONNET_MODEL`,再缺省则报错。`--model` 优先级最高 |
498
+ | `CLAUDE_CODE_EFFORT_LEVEL` | 推理强度,取值同 `--thinking`;`--thinking` 优先 |
499
+ | `CLAUDE_CODE_AUTO_COMPACT_WINDOW` | 自动压缩阈值(token),换算成 `context.compact_at`,只在本次运行生效 |
500
+ | `ANTHROPIC_CONTEXT_WINDOW` | 覆盖上下文窗口(MinimalCode 扩展项) |
501
+ | `ANTHROPIC_MAX_TOKENS` | 覆盖输出上限,默认 `8192`(MinimalCode 扩展项) |
502
+
503
+ 模型名里的 `[1m]` / `[200k]` 这类 Claude Code 后缀只用于选择上下文窗口,发送请求前会被去掉(`deepseek-flash[1m]` → `deepseek-flash`,窗口 1000000);不带后缀时默认按 Anthropic 标准的 200000。`--anthropic-env` 不读取配置文件里的 `web_tools` / `vision`,因此这次运行没有 `web_search`、`web_fetch` 和 `read_image` 工具;需要这些工具时仍用 `--provider deepseek-anthropic`。
504
+
505
+ 沙箱执行层默认关闭(默认 `--no-sandbox`),需要时用 `--sandbox` 或把 `enabled` 设为 `true` 开启;开启后默认只允许工作区、默认禁网:
506
+
507
+ ```json
508
+ "sandbox": {
509
+ "enabled": false,
510
+ "backend": "local",
511
+ "allowed_roots": [],
512
+ "network_policy": "deny",
513
+ "allowed_hosts": [],
514
+ "timeout_seconds": 120,
515
+ "max_output_chars": 60000,
516
+ "allow_sensitive_files": false,
517
+ "max_memory_mb": 0,
518
+ "max_processes": 0,
519
+ "docker_image": "alpine:3"
520
+ }
521
+ ```
522
+
523
+ `backend` 可选 `auto`、`local`、`bwrap`、`firejail`、`sandbox-exec`、`docker`;不可用的后端会拒绝执行而不是降级。命令行提供 `--sandbox/--no-sandbox`、`--sandbox-backend`、`--sandbox-root`、`--sandbox-network`、`--sandbox-allow-host`、`--sandbox-timeout`、`--sandbox-max-output` 和 `--sandbox-allow-sensitive`,`minimalcode sandbox` 可查看当前策略与后端可用性。
524
+
525
+ 完整字段、默认值、Web 工具和视觉配置见 [docs/configuration.md](docs/configuration.md);内置默认值以包内 `minimalcode/defaults.json` 为准。
526
+
527
+ ## 终端高亮
528
+
529
+ 当输出目标是支持 ANSI 的交互式终端时,模型输出中的标题、强调、行内代码、引用、列表、表格和围栏代码块会被着色,并按流式 delta 逐词显示,不等待整行或完整回复。未闭合的 Markdown 标记会立即按对应样式渲染且不打印语法字符;`#` 到 `######` 标题标记本身也不打印,`## 标题` 只输出着色的标题文字;链接显示为 `文本 (URL)`。正文不重排,会话中保存的仍是模型返回的原始 Markdown。模型输出、工具输出和错误信息在写到终端前会移除 ANSI/OSC 等控制序列,只保留换行和制表符,避免转义序列操纵终端。
530
+
531
+ 主题通过配置切换:
532
+
533
+ ```json
534
+ "output": {
535
+ "markdown_highlight": true,
536
+ "theme": "dark"
537
+ }
538
+ ```
539
+
540
+ `theme` 支持 `dark` 和 `light`。以下情况保持纯文本:`--json`、stdout 被重定向、设置 `NO_COLOR`、`--no-highlight`、或配置中关闭高亮。
541
+
542
+ 工具活动(`[shell]`、`[read]` 等标签)写入 stderr,助手正文写入 stdout;`--quiet` 和 `--json` 下不显示工具活动。长 shell 输出在终端只保留首尾各若干行(最多 12 行、4000 字符,省略部分标记 `… N lines omitted`),模型收到的完整输出不受影响。
543
+
544
+ ## 安全边界
545
+
546
+ - MinimalCode 会执行模型生成的 shell 命令,所有命令统一经过沙箱入口。文件工具始终拒绝工作区外路径、符号链接逃逸和常见敏感文件。沙箱执行层默认关闭(默认 `--no-sandbox`),此时不施加网络策略、命令超时/输出上限和子进程资源限制;用 `--sandbox` 或 `sandbox.enabled: true` 开启后,疑似联网命令会被拒绝,后端不可用时 fail-closed 拒绝执行。
547
+ - 默认关闭的执行层意味着 `shell` 直接以当前用户身份运行,没有禁网推断、命令超时和输出上限;需要这些约束时请加 `--sandbox`(或在配置中开启)。开启后的 `local` 基线是策略、超时、输出和子进程资源限制层,不是操作系统级文件系统或网络隔离。需要硬隔离时请选择 `bwrap`/`firejail`/`sandbox-exec`/`docker`(`docker` 仅在 POSIX 宿主上可用,并以当前 `uid:gid` 运行容器,避免工作区出现 root 属主文件),或把 MinimalCode 放进容器、虚拟机或受限账户中运行。
548
+ - 执行层关闭时 `local` 的网络 `deny` 不生效;开启后 `deny` 基于命令字符串识别,无法阻止任意程序自行发起网络连接;`allowlist` 同样依赖命令中的主机可被识别。真正的禁网依赖支持网络命名空间的后端。
549
+ - 文件工具默认限制在工作区内;这不能替代操作系统级隔离,路径检查与真正打开文件之间存在 TOCTOU 窗口。
550
+ - `sandbox` 不清理子进程环境变量,`shell` 仍能看到当前用户的凭据环境变量;不要在不信任的仓库中运行不可信命令。
551
+ - 网络策略 `deny` / `allowlist` 只检查命令位置上的可执行文件名与少量已知联网子命令(`pip install`、`git clone`、`npm install` 等)。因此 `rg curl`、`git log --grep=curl` 这类把网络命令名当参数或搜索词的命令会被放行,引号内的 `|` / `;` 也不会被拆成多条命令(`rg 'nc|netcat'` 同样放行);而 `echo x | curl ...`、`pwsh -Command "iwr ..."`、`sudo wget ...`、`busybox wget ...`、`sh -c "sudo curl ..."` 仍会被拒绝。它不是网络防火墙。
552
+ - `AGENTS.md` / `CLAUDE.md` / `SYSTEM.md` 会进入系统提示词,并在每次运行开始前重新读取(文件不存在则跳过)。解析后的文件必须仍位于声明它的目录中,指向目录外的符号链接会被忽略,避免把工作区外文件带进模型上下文。`/summary` 写入 `AGENTS.md` 的路径同样经过这层校验。
553
+ - `web_fetch` 的目标 URL 由配置的 provider 服务端抓取,而不是由 MinimalCode 直接访问。`web_tools.base_url` 及其凭据属于可信配置,不要指向不可信或能访问敏感内网的服务。
554
+ - `read_image` 同样受工作区限制,图片以 base64 data URL 内联发送,受 `max_image_bytes` 约束。请求由 MinimalCode 直接发往 `vision.base_url`(未设置时回退到供应商的 `base_url`),与主协议无关,因此该端点及其凭据属于可信配置。
555
+
556
+ ## 开发
557
+
558
+ ```powershell
559
+ python -m pip install -e ".[dev]"
560
+ python -m unittest discover -s tests -v
561
+ python -m compileall -q minimalcode tests main.py
562
+ python -m ruff check minimalcode tests benchmarks main.py
563
+ python -m ruff format --check minimalcode tests benchmarks main.py
564
+ python benchmarks/deepseek_responses.py --runs 3
565
+ ```
566
+
567
+ `benchmarks/coding_suite.py --validate-only` 用于在无网络、无密钥的情况下校验基准任务定义。结果报告只列出实际运行过的 agent:只跑了 MinimalCode 时不会输出与 Pi 的对比列。
568
+
569
+ 旧入口仍然可用:
570
+
571
+ ```powershell
572
+ python main.py -p "inspect this repository"
573
+ ```
574
+
575
+ ## 项目结构
576
+
577
+ ```text
578
+ minimalcode/
579
+ ├── cli.py # 参数解析、管理命令、交互循环
580
+ ├── agent.py # 工具循环、用量统计、上下文压缩
581
+ ├── provider/ # OpenAI Chat / Responses 与 Anthropic Messages 客户端
582
+ │ ├── client.py # 共享客户端与协议分派
583
+ │ ├── chat.py # Chat Completions 载荷、流与解析
584
+ │ ├── responses.py # Responses 载荷、事件流与解析
585
+ │ ├── anthropic.py # Anthropic Messages 载荷、流与解析
586
+ │ ├── transport.py # HTTP 请求建立与连接重试
587
+ │ ├── common.py # usage / 内容 / 参数归一化
588
+ │ ├── types.py # ToolCall、ProviderReply
589
+ │ └── factory.py # create_provider
590
+ ├── tools/ # 工作区工具
591
+ │ ├── runtime.py # 共享状态与工具分派
592
+ │ ├── schemas.py # 工具定义
593
+ │ ├── files.py # read / read_range / write / append_file / edit
594
+ │ ├── search.py # 子进程搜索与输出解析
595
+ │ ├── search_tools.py # grep / find
596
+ │ ├── process.py # shell / subagent
597
+ │ ├── remote.py # vision / web 工具
598
+ │ └── validation.py # 模型参数校验
599
+ ├── sandbox/ # 沙箱策略、后端与有界执行
600
+ │ ├── runner.py # 统一入口
601
+ │ ├── policy.py # 路径与网络策略
602
+ │ ├── sensitive.py # 敏感文件规则
603
+ │ ├── network.py # 联网命令识别与主机白名单
604
+ │ ├── backends.py # bwrap / firejail / sandbox-exec / docker
605
+ │ ├── execution.py # 子进程捕获、超时与资源限制
606
+ │ └── audit.py # 拒绝与运行记录
607
+ ├── highlight/ # 流式 Markdown 渲染
608
+ │ ├── markdown.py # 增量渲染状态机
609
+ │ ├── code.py # 围栏代码着色
610
+ │ ├── sanitize.py # 终端控制序列清理
611
+ │ ├── color.py # ANSI 能力探测
612
+ │ └── palette.py # 深色/浅色调色板
613
+ ├── shell.py # shell 探测与子进程执行
614
+ ├── httpclient.py # HTTP 客户端构造、代理策略与连接重试
615
+ ├── prompt.py # 系统提示词与 AGENTS.md 发现
616
+ ├── session.py # JSONL 会话存储与检索
617
+ ├── config.py # 配置合并、校验、脱敏、原子写入
618
+ ├── web.py # 供应商 web_search / web_fetch 客户端
619
+ ├── vision.py # 供应商视觉客户端
620
+ ├── clipboard.py # 系统剪贴板图片读取
621
+ ├── subagent.py # 子进程命令构建与深度传递
622
+ ├── importer.py # Pi 配置迁移
623
+ ├── errors.py # 统一异常类型
624
+ └── defaults.json # 内置默认配置
625
+ ```
626
+
627
+ 四个包的 `__all__` 是唯一公开接口。0.7.0 起不再为拆分前的模块级名字提供回退;私有 helper 从定义它的子模块导入,详见 [docs/compatibility.md](docs/compatibility.md)。
628
+
629
+ 请求链路:CLI → 配置与 shell 探测 → 会话加载/创建 → 供应商流式请求 → 工具调用与执行 → 结果追加到 JSONL → 下一轮模型请求 → 最终文本或 JSON。每次运行只有一个常驻主进程和一个复用的 HTTP 连接池,没有守护进程、嵌入式数据库或后台服务(`shell` 工具会按需启动子进程)。更多细节见 [docs/architecture.md](docs/architecture.md)。
630
+
631
+ ## 文档
632
+
633
+ - [docs/architecture.md](docs/architecture.md):请求链路、模块职责与性能取舍。
634
+ - [docs/configuration.md](docs/configuration.md):全部配置字段、默认值与安全边界。
635
+ - [docs/compatibility.md](docs/compatibility.md):1.0 兼容承诺、公开面定义,以及 0.6 → 0.7 的导入与 patch 迁移对照表。
636
+
637
+ ## 后续工作
638
+
639
+ - 原生 Gemini 协议适配。
640
+ - RPC/SDK 集成。
641
+ - 扩展、Skills 和主题系统。
642
+ - 按路径/按命令的更细粒度工具权限(当前只有按工具名的白名单)。
643
+
644
+ ## 许可证
645
+
646
+ [Apache License 2.0](LICENSE),Copyright 2026 jiaheng0815。