From 366ca40095ce41044bad76a7205991497cb5d686 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 24 Sep 2026 11:56:56 +0000 Subject: [PATCH] =?UTF-8?q?=E5=85=AD=E5=AE=B6=E9=87=8C=E4=B8=89=E5=AE=B6?= =?UTF-8?q?=E7=9A=84=E9=BB=98=E8=AE=A4=E6=A8=A1=E5=9E=8B=E5=B7=B2=E7=BB=8F?= =?UTF-8?q?=E8=B0=83=E4=B8=8D=E9=80=9A=E4=BA=86=20=E2=80=94=E2=80=94=20?= =?UTF-8?q?=E4=BB=A5=E5=8F=8A=20README=20=E9=82=A3=E5=BC=A0=E8=A1=A8?= =?UTF-8?q?=E4=BB=8E=E6=AD=A4=E8=B7=9F=E4=BB=A3=E7=A0=81=E7=BB=91=E7=9D=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 2026-09 核对各家默认模型(官方文档经搜索核对,本机没有 key,没有真调用): kimi moonshot-v1-8k → kimi-k2.6 v1 整个系列 8/31 下线;K2.6 是 256K、面向 agent deepseek deepseek-chat → deepseek-flash 旧名 7/24 停用;deepseek-flash 是现在推荐的 V4.1 Flash gemini gemini-2.0-flash → gemini-3.5-flash 6/1 关停;agent.py 的 --model 注释里用的就是它 claude / openai / glm 三家的默认仍在服务,没动。 kimi-k2.6 默认开思考。Talos 回放历史时不带 reasoning_content —— Kimi 文档说 工具调用里不回传不会报错,只是推理连贯性可能差一点;Talos 也不设 tool_choice, 不撞「开思考时 tool_choice 只能 auto/none」那条。 新判据 test_the_provider_table_in_the_readme_is_what_the_code_does: README 的 provider 表(哪几家、读哪个 key、默认哪个模型)== agent.PROVIDERS。 这次两边一起改的;它管的是下一次只改一边。先只改代码,它当场点名三行,再改 README 才绿。 顺带:tests/test_memory.py 一段 docstring 里的 `\w` `\.` 是要原样显示的正则, 加 r 前缀 —— 3.12+ 的 SyntaxWarning / 3.11 的 DeprecationWarning 没了,值不变。 DEVELOPMENT.md 里 judge_live 的示例命令也从 deepseek-chat 换成 deepseek-flash。 337 判据:335 过、5 skip、1 xfail(原有),警告 0 条。 Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_014gdkHx6rLSMVsUmQiErVSn --- DEVELOPMENT.md | 6 +++--- README.md | 14 +++++++------- agent.py | 8 +++++--- tests/test_docs.py | 30 ++++++++++++++++++++++++++++++ tests/test_memory.py | 2 +- 5 files changed, 46 insertions(+), 14 deletions(-) diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md index 0838a40..9934d6e 100644 --- a/DEVELOPMENT.md +++ b/DEVELOPMENT.md @@ -150,7 +150,7 @@ def check_permission(state, cls, name, args): # 决策 + ```bash python agent.py --selfcheck # 零依赖、零网络、零 key。改完先跑这个 -python -m pytest tests/ -q # 336 条。CI 跑 ubuntu/windows × 3.10/3.13 +python -m pytest tests/ -q # 337 条。CI 跑 ubuntu/windows × 3.10/3.13 ``` `--selfcheck` 覆盖 4 个工具的读/写/改、`edit_file` 的"找不到 / 不唯一"两种报错、 @@ -190,14 +190,14 @@ set TALOS_MAX_STEPS=12 | **行为类** | **模型读到守卫那条消息之后干什么** | ❌ 必须用你真在用的那个 | 「拒绝之后会不会改用 `python -c` 绕路」是那个具体模型的性格,换了模型不算数。 -而**行为类正是 live 测试唯一还值钱的部分** —— 管道通不通,336 条判据已经免费覆盖了。 +而**行为类正是 live 测试唯一还值钱的部分** —— 管道通不通,337 条判据已经免费覆盖了。 按这条界,**目标闸的 live 判据是行为类的**:离线判据已经证明判断器拿得到 `read_file`、 越界会被驳回、判不出来时不假装成功;它们证明不了的是**这个具体模型拿到只读工具之后 会不会真的去用**,还是照样信对话里那句「验证通过」。这一条不成立的话,只读工具就是装饰。 ```bash -$env:TALOS_PROVIDER="deepseek"; $env:TALOS_MODEL="deepseek-chat" +$env:TALOS_PROVIDER="deepseek"; $env:TALOS_MODEL="deepseek-flash" .venv\Scripts\python.exe benchmarks\goal\judge_live.py --n 3 ``` diff --git a/README.md b/README.md index 377c16b..8274bb1 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [![tests](https://github.com/Jerry-TZ/Talos/actions/workflows/test.yml/badge.svg)](https://github.com/Jerry-TZ/Talos/actions/workflows/test.yml) -**一个你能完整读完的编程 agent。** 5309 行 Python,336 条离线判据,一份不糊弄人的安全说明。 +**一个你能完整读完的编程 agent。** 5311 行 Python,337 条离线判据,一份不糊弄人的安全说明。 Talos 终端界面:动盘之前先弹确认框 @@ -19,7 +19,7 @@ | 文件 | 行数 | 职责 | |---|---|---| -| `agent.py` | 4207 | 循环 + 工具 + 权限门 + 自学习 | +| `agent.py` | 4209 | 循环 + 工具 + 权限门 + 自学习 | | `console_ui.py` | 214 | 终端界面(可整体替换) | | `recall.py` | 582 | 联想记忆:扩散激活检索 | | `session.py` | 306 | 会话持久化(想换 SQLite 只改这个) | @@ -33,7 +33,7 @@ 极简 agent 赛道很挤,有人用 Zig 做到 678KB 二进制。**Talos 不比谁小,它比谁都好读。** - **能读完** — 四个文件,注释解释的是*为什么*,不是*是什么*。几乎每条防御旁边都写着它挡的那次真实翻车。 -- **能验证** — 336 个测试,**离线、免 API key、几秒跑完**,CI 在 Linux/Windows × Python 3.10/3.13 上都跑。clone 下来立刻知道它没坏。 +- **能验证** — 337 个测试,**离线、免 API key、几秒跑完**,CI 在 Linux/Windows × Python 3.10/3.13 上都跑。clone 下来立刻知道它没坏。 - **不吹牛** — [`SECURITY.md`](SECURITY.md) 明写 `create_tool` 就是进程内 RCE、正则黑名单只是减速带。**没有沙箱就是没有沙箱** —— 真要隔离,[三条现成方案](SECURITY.md#真要隔离怎么办)按代价从低到高列在那儿。 - **有考卷** — [`EXAM.md`](EXAM.md) / [`EXAM2.md`](EXAM2.md) 是两份可复现的能力测试,带标准答案和作弊检测(比如逐个核验 arXiv ID 真伪,防止编造引用)。记录的是"我怎么验证它真的有用",不是功能列表。 - **有实测** — [`FINDINGS.md`](FINDINGS.md) 记了二十二个真实任务量出来的东西:哪条提示词生效、哪条从头到尾没生效、六次翻车、检索改动的前后数字,以及**两个被数据否掉的自己的方案**。样本小,局限写在最前面。 @@ -81,10 +81,10 @@ python agent.py --selfcheck |---|---|---| | `claude`(默认) | `ANTHROPIC_API_KEY` | claude-haiku-4-5 | | `openai` | `OPENAI_API_KEY` | gpt-4o-mini | -| `gemini` | `GEMINI_API_KEY` | gemini-2.0-flash | -| `deepseek` | `DEEPSEEK_API_KEY` | deepseek-chat | +| `gemini` | `GEMINI_API_KEY` | gemini-3.5-flash | +| `deepseek` | `DEEPSEEK_API_KEY` | deepseek-flash | | `glm` | `ZHIPUAI_API_KEY` | glm-4.7-flash | -| `kimi` | `MOONSHOT_API_KEY` | moonshot-v1-8k | +| `kimi` | `MOONSHOT_API_KEY` | kimi-k2.6 | --- @@ -200,7 +200,7 @@ Ctrl+C 停下当前这轮 —— 做过的都留着,可以直接说 ```bash .venv\Scripts\python.exe -m pip install -r requirements-dev.txt -.venv\Scripts\python.exe -m pytest tests/ -q # 336 条,约 8 秒,不联网、不需要 key +.venv\Scripts\python.exe -m pytest tests/ -q # 337 条,约 8 秒,不联网、不需要 key python agent.py --selfcheck # 免依赖的冒烟检查 ``` diff --git a/agent.py b/agent.py index 375b69f..28aff48 100644 --- a/agent.py +++ b/agent.py @@ -91,14 +91,16 @@ def _load_dotenv(path: str = ".env") -> None: # ── providers: 大家都讲 OpenAI 兼容 API,只有 base_url + 模型名不同 ──────────────── # base_url 稳定;模型名常变 —— 用 TALOS_MODEL 环境变量覆盖成你有权限的那个。 +# 默认模型 2026-09 核对过:moonshot-v1 整个系列(8/31)、deepseek-chat(7/24)、 +# gemini-2.0-flash(6/1)都已下线,换成了各家当前的对应档。README 那张表跟这里由判据绑着。 PROVIDERS = { # name key 环境变量 base_url (None = OpenAI 官方) 默认模型 "claude": ("ANTHROPIC_API_KEY", "https://api.anthropic.com/v1/", "claude-haiku-4-5-20251001"), "openai": ("OPENAI_API_KEY", None, "gpt-4o-mini"), - "gemini": ("GEMINI_API_KEY", "https://generativelanguage.googleapis.com/v1beta/openai/", "gemini-2.0-flash"), - "deepseek": ("DEEPSEEK_API_KEY", "https://api.deepseek.com/v1", "deepseek-chat"), + "gemini": ("GEMINI_API_KEY", "https://generativelanguage.googleapis.com/v1beta/openai/", "gemini-3.5-flash"), + "deepseek": ("DEEPSEEK_API_KEY", "https://api.deepseek.com/v1", "deepseek-flash"), "glm": ("ZHIPUAI_API_KEY", "https://open.bigmodel.cn/api/paas/v4", "glm-4.7-flash"), - "kimi": ("MOONSHOT_API_KEY", "https://api.moonshot.cn/v1", "moonshot-v1-8k"), + "kimi": ("MOONSHOT_API_KEY", "https://api.moonshot.cn/v1", "kimi-k2.6"), } PROVIDER = os.environ.get("TALOS_PROVIDER", "claude").lower() diff --git a/tests/test_docs.py b/tests/test_docs.py index ad1cce8..eec8ded 100644 --- a/tests/test_docs.py +++ b/tests/test_docs.py @@ -118,3 +118,33 @@ def test_the_test_count_the_docs_advertise_is_the_real_one(): assert not wrong, ( f"文档宣传的测试数跟 tests/ 里真实的 {real} 条对不上:\n " + "\n ".join(wrong) + "\n加判据是这个项目每天在干的事,所以这个数**每天都会陈** —— 这条就是为它存在的。") + + +# `| `claude`(默认) | `ANTHROPIC_API_KEY` | claude-haiku-4-5 |` +_PROVIDER_ROW = re.compile(r"^\|\s*`(\w+)`[^|]*\|\s*`(\w+)`\s*\|\s*([\w.\-]+)\s*\|", re.M) + + +def test_the_provider_table_in_the_readme_is_what_the_code_does(): + """README 那张 provider 表 == `agent.PROVIDERS`:哪几家、读哪个 key、默认哪个模型。 + + **默认模型会被供应商下线,而且下得很快。** 2026-09 核对时,六家里有三家的默认值 + 已经调不通了:`moonshot-v1-8k`(整个 v1 系列 8 月 31 日下线)、`deepseek-chat` + (7 月 24 日停用)、`gemini-2.0-flash`(6 月 1 日关停)。那次是两边一起改的 —— + 这条判据管的是**下一次只改了一边**:读者照着 README 设了 provider,跑起来却是另一个模型。 + + README 可以写去掉日期后缀的名字(`claude-haiku-4-5` 对 `claude-haiku-4-5-20251001`), + 那是同一个模型的别名;别的一律要逐字相同。""" + import agent + readme = io.open(os.path.join(HOME, "README.md"), encoding="utf-8").read() + rows = {p: (key, model) for p, key, model in _PROVIDER_ROW.findall(readme)} + assert set(rows) == set(agent.PROVIDERS), ( + f"README 表里的 provider 跟代码对不上:多了 {sorted(set(rows) - set(agent.PROVIDERS))}、" + f"少了 {sorted(set(agent.PROVIDERS) - set(rows))}") + wrong = [] + for p, (key, model) in sorted(rows.items()): + want_key, _url, want_model = agent.PROVIDERS[p] + if key != want_key: + wrong.append(f"{p}:README 写 key {key},代码读 {want_key}") + if not (model == want_model or want_model.startswith(model + "-")): + wrong.append(f"{p}:README 写默认 {model},代码默认 {want_model}") + assert not wrong, "README 的 provider 表跟代码对不上:\n " + "\n ".join(wrong) diff --git a/tests/test_memory.py b/tests/test_memory.py index 356b9b9..4c23a6b 100644 --- a/tests/test_memory.py +++ b/tests/test_memory.py @@ -1959,7 +1959,7 @@ def test_a_refusal_says_what_was_refused_instead_of_something_that_never_happene def test_a_file_that_merely_starts_with_check_is_not_a_verification_script(ws): - """`checksum.py` / `checkpoint.py` / `checklist.py` / `checkout.py` 不是验证脚本。 + r"""`checksum.py` / `checkpoint.py` / `checklist.py` / `checkout.py` 不是验证脚本。 正则原来是 `^(verify|validate|check)[\w-]*\.py$` —— 它认「以 check 开头」, 而这几个名字在真实仓库里到处都是。命中之后 `write_file` / `edit_file` 一律拒绝: