Skip to content

Latest commit

 

History

History
554 lines (435 loc) · 25.7 KB

File metadata and controls

554 lines (435 loc) · 25.7 KB

Task Finished

已实现并通过测试的工作项。每次推进时把 ToDo.md 里完成的条目搬到这里。 关联文档:Plan.md(策略路线图) · ToDo.md(待办与已知问题)


2026-04-28 — Phase 0:Hello Loop ✅

目标:CLI → DeepSeek → 文本回复(无工具)。对应 Plan.md "Phase 0 — Hello Loop"。

工程骨架

  • pyproject.toml — 依赖(openai, pydantic, typer, rich, python-dotenv),entry point my-agent
  • .env.example / .gitignore
  • README.md — Setup / Run / Test 三段式
  • 目录结构(含 Phase 1+ 的 tools/ui/ 占位空目录)

内部消息协议(src/my_agent/types.py

  • ContentBlock discriminated union:TextBlock | ToolUseBlock | ToolResultBlock
  • Message(role, content: list[ContentBlock]) + text() helper
  • ToolSpec 数据模型(Phase 1 用得上,Phase 0 先就位)
  • JSON round-trip 测试通过(验证 discriminator 正确还原子类型)

LLM 抽象(src/my_agent/llm/

  • LLMClient ABC:chat(messages, system, tools) -> Message
  • OpenAIStyleClientbase_url=https://api.deepseek.com/v1model=deepseek-chat
  • 内部 Message ↔ OpenAI wire format 翻译(Phase 0 仅 text,工具翻译留给 Phase 1

Agent loop(src/my_agent/agent.py

  • 单轮 Agent.run(user_input) -> str
  • 自动记录 user / assistant 消息到 self.messages

CLI(src/my_agent/cli.py + __main__.py

  • typer 入口,支持 my-agent "msg" 与 stdin 两种输入
  • 选项:--model / --base-url / --api-key-env / --system
  • 缺 API key 时优雅退出(exit 1)+ 提示 cp .env.example .env
  • API 异常时退出 code 2

测试(tests/

  • MockLLMClient 测试夹具(无网络,可注入 canned responses)
  • 7 个 pytest 用例全过 — pytest -v 0.52s:
    • test_single_turn_returns_assistant_text
    • test_messages_record_user_and_assistant_turn
    • test_system_prompt_is_forwarded_to_client
    • test_default_reply_when_mock_runs_out
    • test_text_helper_concatenates_text_blocks
    • test_message_round_trips_through_json
    • test_tool_result_block_defaults

代码量

  • 源码 ~250 行(types 58 / agent 25 / cli 74 / openai_style 58 / base 28 / 入口若干)
  • 测试 ~120 行
  • 合计 369 行(与 Plan.md 估算一致)

验证记录

检查 结果
pytest -v ✅ 7 passed
my-agent --help ✅ 选项与帮助正常
my-agent "hi"(无 key) ✅ exit 1 + 友好提示
真实 DeepSeek 端到端调用 ✅ 已验证

2026-04-28 — Phase 0.5 重构:Anthropic 兼容端点 ✅

目标:把 LLM 客户端从 OpenAI 兼容路径切到 DeepSeek Anthropic 兼容端点,对齐内部 ContentBlock 协议。

依赖与环境

  • pyproject.tomlanthropic>=0.40 加为主依赖,openai 移到 [project.optional-dependencies].openai
  • .env.example:字段切到 ANTHROPIC_AUTH_TOKEN / ANTHROPIC_BASE_URL / ANTHROPIC_MODEL / ANTHROPIC_EFFORT
  • .gitignore 已正确排除 .env

LLM 客户端替换(src/my_agent/llm/anthropic_style.py

  • AnthropicStyleClient(LLMClient):封装 anthropic.Anthropic(auth_token, base_url)
  • chat():调 client.messages.create(model, system, messages, tools, max_tokens)
  • _to_anthropic():内部 Message → SDK MessageParam(TextBlock / ToolUseBlock / ToolResultBlock 三向翻译)
  • _from_anthropic():SDK 响应 .content → 内部 [TextBlock | ToolUseBlock],thinking blocks 丢弃
  • --effort 参数 + EFFORT_BUDGETS 映射(low/medium/high/max/off)
  • thinking 禁用时显式传 {"type": "disabled"}(DeepSeek v4-pro 默认 thinking ON)
  • openai_style.py 保留并标记 # Deferred to Phase 3 fallback provider
  • llm/__init__.py 导出 AnthropicStyleClient(不导出 OpenAIStyleClient)

CLI 默认值更新

  • --api-key-env 默认 ANTHROPIC_AUTH_TOKEN
  • --base-url 默认 https://api.deepseek.com/anthropic
  • --model 默认 deepseek-v4-pro[1m]

测试

  • 老 7 个用例全部保留且通过
  • 新增 tests/test_anthropic_style.py(14 个用例):_to_anthropic / _from_anthropic / tool forwarding / thinking budget / effort disabled
  • 全部 21 个用例通过,无网络依赖

验证记录

检查 结果
pytest -v ✅ 21 passed
my-agent "用一句话介绍你自己" ✅ DeepSeek 正确响应

2026-04-28 — Phase 1:Tool Loop ✅

目标:agent 能用 4 个核心工具自主完成"读这个目录、找包含 X 的文件、写一个总结到 out.md"这种任务。

工具基础设施(src/my_agent/tools/base.py

  • Tool 抽象基类:name / description / input_model(Pydantic BaseModel) / run(input) -> str
  • input_schema property:自动调 model_json_schema() 生成 JSON Schema
  • ToolRegistryregister() / get_specs() -> list[ToolSpec] / execute(name, tool_use_id, input) -> ToolResultBlock
  • 三层错误保护:未知工具 → Invalid input → Runtime error,全部返回 is_error=True

4 个核心工具

  • tools/read.py — 路径 → 文件内容(行号前缀 cat -n 风格,2000 行限制,offset/limit 分页)
  • tools/write.pypath + content(父目录自动 mkdir,UTF-8)
  • tools/bash.pycommand + timeoutsubprocess.run,捕获 stdout/stderr/exit code,默认 120s)
  • tools/glob.pypattern + pathpathlib.Path().glob(),** 递归,最多 500 结果)

Agent loop 升级(src/my_agent/agent.py

  • Agent.run() 改为 while 循环:直到 assistant 不再产出 tool_use
  • max_iterations=20 防死循环(达上限抛 IterationLimitError
  • 多个 tool_use 的结果统一打包成一条 user message(Anthropic 协议要求)
  • tool_use_id 正确串接:assistant.id → tool_result.tool_use_id
  • 工具执行失败 → ToolResultBlock(is_error=True),喂回 LLM 自行恢复

System prompt(src/my_agent/prompt.py

  • 基础 system prompt:身份、可用工具说明、CWD、当前日期
  • 支持用户 --system 覆盖

Anthropic 客户端补齐工具协议

  • chat()tools=[ToolSpec...] 转为 Anthropic SDK tools=[{name, description, input_schema}](Phase 0.5 已就位)
  • _from_anthropic() 解析 tool_use blocks(Phase 0.5 已就位)
  • DeepSeek 工具字段稳定性验证:name 字段正常,未触发 fallback

测试

  • 工具单测:tests/test_tools.py(19 个用例)— Read/Write/Bash/Glob 全覆盖
  • 注册表单测:tests/test_tool_registry.py(6 个用例)
  • Agent loop 集成测:tests/test_agent_tool_loop.py(8 个用例)— 单轮 / 工具回路 / 多工具同轮 / 迭代上限 / 错误回流
  • MockLLMClient 扩展:mock_tool_use() / mock_tool_use_with_text() 工厂函数
  • 老测试全部保留且通过

代码量

  • 新增源码 ~420 行(tools/base 80 / read 55 / write 30 / bash 45 / glob 45 / agent 50 / prompt 40 / 注册 75)
  • 新增测试 ~320 行(test_tools 110 / test_tool_registry 65 / test_agent_tool_loop 115 / mock_llm 扩展 30)
  • 累计源码 ~670 行,测试 ~440 行,合计 ~1110 行

验证记录

检查 结果
pytest -v ✅ 53 passed(21 old + 32 new)
真实端到端:"找出 .py 文件统计行数写入 stats.md" ✅ 成功执行 glob → read → write 完整回路
stats.md 内容验证 ✅ 格式化 table,数据正确

2026-04-28 — Phase 2:生产级核心 ✅

目标:agent 跑得"安全"——权限控制、流式输出、配置化、CLAUDE.md 加载、REPL 模式。

权限系统(src/my_agent/permission.py

  • PermissionMode 枚举:read_only / ask / allow_all / danger
  • PermissionPolicycheck(tool_name, input) -> Decision(allow/deny/ask)
  • 默认规则:read_only 拒绝 write/bash/edit,ask 对写工具弹确认
  • 内置 deny 模式:rm -rf /git push --forceshutdownmkfs.、fork bomb 等 10+ 条
  • from_string() 工厂方法

配置系统(src/my_agent/config.py

  • load_settings() 优先级链:CWD .my-agent/settings.json~/.my-agent/settings.json → 默认值
  • 环境变量覆盖:ANTHROPIC_MODELANTHROPIC_BASE_URLANTHROPIC_EFFORTMY_AGENT_PERMISSION_MODE
  • 损坏 JSON 优雅降级

新工具

  • tools/edit.py — 精确字符串替换,强制执行 read-before-edit 不变量(通过 Registry 共享 read_files)
  • tools/grep.py — ripgrep 优先(子进程),Python re fallback(递归搜索 + 文件过滤)
  • Read 工具扩展:自动追踪已读文件到 Registry.read_files

流式输出(src/my_agent/llm/anthropic_style.py

  • chat_stream() 方法:SDK messages.stream(),SSE 事件解析
  • StreamEvent 事件类型:text_delta / tool_use_start / tool_use_delta / done
  • _build_kwargs() 重构,chat() 和 chat_stream() 共享参数构建

TUI 渲染(src/my_agent/ui/render.py

  • rich.live.Live + Spinner 流式文本输出
  • 工具调用实时显示(黄色 ⚙ name + dim 输入参数)
  • 完成提示(✓ tool_name: summary)

权限集成(src/my_agent/agent.py

  • Agent 构造接受 PermissionPolicy + ask_callback
  • 每个 tool_use 执行前通过 policy.check() 判定
  • DENY → is_error ToolResultBlock 喂回 LLM
  • ASK → 调 ask_callback,用户拒绝 → is_error ToolResultBlock
  • 权限变更不影响消息历史(slash command /permission 动态切换模式)

Prompt 扩展(src/my_agent/prompt.py

  • 自动加载 CWD 的 CLAUDE.md / AGENTS.md / .my-agent/instructions.md
  • 限制 4000 字符,超出截断

CLI 扩展(src/my_agent/cli.py

  • --permission-mode / -p 选项(支持 env var MY_AGENT_PERMISSION_MODE
  • --repl / -r 交互模式
  • REPL slash 命令:/help/clear/permission/history
  • Confirm.ask() 权限确认提示(显示工具名 + 输入摘要)
  • 注册 6 个工具(Read / Write / Edit / Bash / Glob / Grep)

测试

  • test_permission.py(14 个用例)— 四种模式 / deny 模式 / from_string
  • test_edit.py(7 个用例)— 替换 / replace_all / read-before-edit / 错误处理
  • test_grep.py(6 个用例)— 搜索 / 过滤 / 递归 / 非法正则
  • test_config.py(6 个用例)— 默认值 / 文件加载 / env 覆盖 / 损坏 JSON
  • test_agent_permission.py(5 个用例)— deny / ask+callback / allow_all

代码量

  • 新增源码 ~630 行(permission 85 / config 85 / edit 75 / grep 85 / render 80 / anthropic_style stream 90 / agent 50 / cli 80)
  • 新增测试 ~340 行(test_permission 90 / test_edit 60 / test_grep 55 / test_config 50 / test_agent_permission 85)
  • 累计源码 ~1300 行,测试 ~780 行,合计 ~2080 行

验证记录

检查 结果
pytest -v ✅ 90 passed(53 old + 37 new)
流式输出 ✅ rich Live + Spinner 实时展示
read_only 模式端到端 ✅ glob/grep 允许,write 正确拒绝,agent 智能恢复
allow_all 模式端到端 ✅ 完整 glob → grep → write 回路
summary2.md 内容 ✅ 格式化正确

2026-04-28 — Phase 3.1:会话持久化 ✅

目标:会话能保存、能续接、能列出、能删除。

Session 数据模型(src/my_agent/session.py

  • Session 类:messages / id / created_at / updated_at / model / permission_mode / working_dir
  • save() → JSON 到 ~/.my-agent/sessions/<id>.json
  • load(id) → Session | None
  • list_recent(limit=20) → 最新的 sessions 列表
  • resume_latest() → 最新 session 或 None
  • delete() → 删除持久化文件
  • summary() → 单行摘要(ID / 消息数 / 时间 / 预览)

CLI 集成

  • --resume <id> / --resume latest 恢复会话
  • my-agent sessions list 子命令(rich Table 展示)
  • my-agent sessions delete <id> 子命令
  • 每次 chat 结束后自动保存 session
  • REPL 内 /save/session 命令
  • 恢复时消息列表注入 agent.messages,无缝续接

测试

  • tests/test_session.py(8 个用例)— save/load round-trip / list_recent / resume_latest / delete / empty / invalid JSON

验证记录

检查 结果
pytest -v ✅ 98 passed(90 old + 8 new)
my-agent sessions list ✅ 空列表正常
my-agent chat "记住我的名字" ✅ 自动保存 session
my-agent sessions list ✅ 显示已保存 session
my-agent chat --resume latest "我叫什么?" ✅ 正确恢复记忆,跨轮问答

2026-04-28 — Phase 3.2:上下文压缩 ✅

目标:长对话自动压缩,tool_use/tool_result 配对不拆。

压缩引擎(src/my_agent/compact.py

  • estimate_tokens() — 按字符数 / 4 粗估 token(English/中文混合)
  • should_compact(messages, threshold) — 超阈值时触发(默认 40K tokens)
  • compact_messages(messages) — 压缩策略:保留最近 6 条,旧消息生成摘要
  • _align_to_pair_boundary() — 核心不变量:tool_use / tool_result 对永不拆分
  • build_compaction_summary() — 生成结构化摘要(角色 / 工具名 / 参数 / 结果)
  • Agent loop 集成:每次 LLM 调用前检查 + 自动压缩

测试

  • tests/test_compact.py(6 个用例)— token 估算 / 阈值判断 / 短对话不压缩 / pair 保留

验证记录

检查 结果
pytest -v ✅ 106 passed(98 old + 8 new)

2026-04-28 — Phase 3.3:子 Agent ✅

目标:agent 可以 spawn 子 agent 做独立任务。

Task 工具(src/my_agent/tools/task.py

  • Task 工具:description / prompt / subagent_type 参数
  • general-purpose 类型:共享父 agent 的 ToolRegistry + PermissionPolicy
  • Explore 类型:只读(read/glob/grep)+ read_only 权限
  • 独立 messages 上下文,返回最终 text 给父 agent
  • MAX_SUB_TURNS=10 防子 agent 死循环
  • IterationLimitError 优雅降级
  • ToolRegistry 扩展:set_context(client, policy) + _registry 注入

测试

  • tests/test_task.py(4 个用例)— 子 agent 执行 / Explore 模式 / 未初始化 / 迭代上限

验证记录

检查 结果
pytest -v ✅ 110 passed(106 old + 4 new)

2026-04-28 — Phase 3.4:钩子系统 ✅

目标:settings 驱动的 shell 命令,在 tool 执行前后自动触发。

钩子引擎(src/my_agent/hooks.py

  • HookEvent 枚举:pre_tool_use / post_tool_use / stop
  • HookConfig:从 settings.json hooks 字段加载命令列表
  • run_hooks(event, commands, context)HookResult(allowed, stdout, stderr)
  • 环境变量注入:MY_AGENT_EVENT / MY_AGENT_TOOL_NAME / MY_AGENT_TOOL_INPUT
  • pre_tool_use 非零退出 → 拒绝工具执行
  • post_tool_use / stop 非零退出 → 无视(仅告警)
  • 超时保护(单钩子 10s)

Agent 集成

  • 每个 tool_use 执行前:pre_tool_use hooks
  • 每个 tool 执行后:post_tool_use hooks
  • Hook 拒绝 → is_error ToolResultBlock 喂回 LLM

测试

  • tests/test_hooks.py(7 个用例)— 配置加载 / 环境变量传递 / 非零退出 / 超时

2026-04-28 — Phase 3.5:Provider 切换 ✅

目标:多 provider 可切换(Anthropic / OpenAI),build_client() 工厂。

llm/openai_style.py 重生

  • 完整 tool_callsToolUseBlock 双向翻译
  • _to_openai():ToolUseBlock → assistant tool_calls / ToolResultBlock → tool role 消息
  • _from_openai():响应 tool_calls → ToolUseBlock(JSON arguments 解析 + fallback)
  • tool_choice="auto" 默认

llm/__init__.pybuild_client() 工厂

  • provider="anthropic" → AnthropicStyleClient(DeepSeek 代理 / 官方 Claude)
  • provider="openai" → OpenAIStyleClient(DeepSeek 原生 / 百炼 / vLLM)
  • base_url / model 参数透传
  • auth_tokenapi_key 兼容

CLI 扩展

  • --provider anthropic|openai 参数
  • build_client() 替换硬编码 AnthropicStyleClient
  • REPL 兼容 LLMClient 基类

测试

  • tests/test_openai_style.py(5 个用例)— to_openai / from_openai 双向翻译

验证记录

检查 结果
pytest -v ✅ 123 passed(117 old + 6 new)

2026-04-28 — Phase 4:生态扩展 ✅

目标:CLI 修复、Doctor 健康检查、插件系统、Slash 命令完善、可观测性。

CLI 修复(src/my_agent/cli.py

  • my-agent "msg" 恢复工作(不再需要显式 chat 子命令)
  • main() 中自动检测:第一个位置参数非已知命令 → 插入 "chat"
  • doctor 子命令:API key 检查 / 配置显示 / 工具列表 / 会话数 / 连通性 ping
  • 重构为 _run_chat() 辅助函数,callback/subcommand 共用

插件系统(src/my_agent/plugins.py

  • discover_plugins() 扫描 ~/.my-agent/plugins/*.py
  • 支持 get_tools() 导出函数 + Tool 子类自动检测
  • _ 前缀文件跳过
  • 损坏插件静默跳过,不阻塞 agent 启动
  • 已集成到 _make_registry()

Slash 命令完善(src/my_agent/cli.py

  • /compact — 手动压缩上下文(显示 token 变化)
  • /history — 消息数 + token 估算
  • /doctor — 会话健康概览
  • REPL 内共 8 个 slash 命令

可观测性 + 重试(src/my_agent/llm/anthropic_style.py

  • Usage 数据类:input_tokens / output_tokens / duration_ms
  • chat() 解析 resp.usage 存入 last_usage
  • _retry_call() 指数退避重试(502/503/504/429/timeout/connection)
  • verbose=True 时 stderr 打印 token 消耗 + 耗时
  • max_retries=2 默认配置

测试

  • tests/test_plugins.py(4 个用例)— 空目录 / get_tools / 跳过下划线 / 损坏静默

验证记录

检查 结果
pytest -v ✅ 127 passed(123 old + 4 new)
my-agent "一句话介绍自己" ✅ 自动路由到 chat
my-agent doctor ✅ API key ✓ / 7 tools / 连通性 1.1s
my-agent sessions list ✅ 子命令正常

2026-04-28 — Phase 4.6:Prompt Caching ✅

  • use_cache=True 默认,system prompt + tools 加 cache_control: {type:"ephemeral"}
  • cache_hits / cache_misses 追踪

2026-04-28 — Phase 4.7:MCP 客户端 ✅

  • McpServer — JSON-RPC over stdio(initialize / tools/list / tools/call)
  • McpToolWrapper — MCP 工具包装为 Agent Tool
  • Settings.json mcpServers 配置 + 自动启动
  • 测试:tests/test_mcp.py(8 个用例)

验证记录

检查 结果
pytest -v ✅ 135 passed
my-agent "一句话"
my-agent doctor
Prompt caching ✅ cache_control markers present
MCP config parsing

2026-04-28 — 二轮 Code Review Bug 修复 ✅

目标:集中修复 ToDo.md 中 B-编号系列 17 个 bug + D-10 / D-16 / D-18。

严重(B-1 ~ B-4)

# 文件 修复
B-1 tools/bash.py cwd="/"cwd=os.getcwd()
B-2 tools/edit.py replace_alloriginal.count() 统计实际替换次数
B-3 ui/render.py Text(...)Text.from_markup(...)(3 处)
B-4 tools/task.py / tools/base.py / cli.py _ask_callback 注入 + set_context / register 传播到子 agent

中等(B-5 ~ B-11)

# 文件 修复
B-5 llm/anthropic_style.py chat_stream() 通过 stream.get_final_message() 更新 last_usage / cache_hits / cache_misses
B-6 llm/anthropic_style.py chat_stream()_retry_call 包装 _do_stream 闭包,添加指数退避重试
B-7 llm/anthropic_style.py _retry_call 直接从 resp.usage 打印当前调用统计,不再用滞后一轮的 last_usage
B-8 llm/openai_style.py tool 消息连续排列,user TextBlock 置后,满足 OpenAI "tool 消息必须连续"约束
B-9 llm/openai_style.py assistant content: Nonecontent: "",兼容拒绝 null 的端点
B-10 tools/read.py .split("\n").splitlines(),消除尾部空元素
B-11 agent.py agent 正常结束 / 迭代上限时调用 HookEvent.STOP

低 / 配置脱节(B-12 ~ B-17)

# 文件 修复
B-12 agent.py / cli.py / tools/task.py Agent(max_iterations=settings.max_iterations),替代硬编码 MAX_ITERATIONS
B-13 permission.py 移除未使用的 READ_ONLY_TOOLS 死代码
B-14 agent.py / cli.py 新增 on_tool_result 回调参数,接入 Renderer.add_tool_result()
B-15 tools/base.py / cli.py 新增 ToolRegistry.register_instance() 方法,MCP 工具不走旁路
B-16 tools/bash.py 8000 字节 / 200 行硬截断,防止 stdout 爆 LLM 上下文
B-17 llm/anthropic_style.py max_tokens clamp 到 32000,避免超 DeepSeek 模型上限

技术债务

# 文件 修复
D-10 pyproject.toml 添加 [tool.hatch.build.targets.wheel.sources] "src" = "" 修复 Python 3.14 .pth 隐藏文件问题
D-16 mcp.py _build_input_model 使用 pydantic.create_model + ConfigDict(extra="allow") fallback
D-18 compact.py 移除未使用的 from .session import Session 导入

测试调整

  • tests/test_anthropic_style.py:251test_effort_max_forwards_thinking_budget 断言更新:> 32000== 32000(匹配 B-17 clamp)

验证记录

检查 结果
pytest -v ✅ 135 passed(全部通过,无退化)

2026-04-28 — 深度测试 Bug 修复(C-系列)✅

目标:集中修复 ToDo.md 中 C-编号系列 12 个深度测试发现的 bug。

🔴 严重(C-1 ~ C-7)

# 文件 修复
C-1 安装产物 .pth chflags nohidden 清除 macOS hidden flag + pyproject.toml sources 配置
C-2 cli.py ask_callback() 定义移动到 registry.set_context() 之前,消除 UnboundLocalError
C-3 tools/grep.py _rg_searchre.compile 校验正则;returncode not in (0,1) 时 fallback 到 Python
C-4 permission.py read_only 改为显式 allowlist(read/glob/grep/task);ask 模式未知工具默认 ASK
C-5 permission.py shlex tokenize 命令 + 识别 rm -rf/rm -fr/-- 变体 + ///* 目标检测
C-6 mcp.py Content-Length framed JSON-RPC 读写(LSP-style),兼容 newline-delimited fallback
C-7 mcp.py threading.Thread + join(timeout) 带 deadline 读 stdout;超时 kill 子进程

🟡 中等(C-8 ~ C-12)

# 文件 修复
C-8 mcp.py _build_input_model 读取 JSON Schema required 数组;非必填字段 default=None
C-9 mcp.py call_tool 返回 (content, is_error) tuple;McpToolWrapper.run() 遇 isError 抛 RuntimeError
C-10 tools/grep.py 截断前保存 total = len(lines),提示 total - MAX_RESULTS
C-11 session.py Session.load 新增 _resolve_id 前缀匹配;8 位短 ID 可唯一匹配到 12 位完整 ID
C-12 全局 49 个 ruff 告警清零:load_dotenv 移到 import 之后、移除 unused import、Any 正确导入

测试调整

  • tests/test_agent_tool_loop.py — GetTool name "get""read"(适配 allowlist 权限模型)
  • test_tool_error_is_reported_to_llm — 添加 ask_callback=lambda: True 通过未知工具权限检查

验证记录

检查 结果
pytest -v ✅ 135 passed
ruff check src/ ✅ All checks passed
.pth hidden flag ✅ 已清除


2026-04-28 — 深度测试 Bug 修复(二轮复测 C-13 ~ C-18)✅

目标:修复 C 系列首轮修复后的残余问题 + 复测新增的 6 个 bug。

🔴 严重

# 文件 修复
C-1 .pth / scripts/fix_pth.sh xattr -d com.apple.provenance + chflags nohidden + 工具脚本
C-13 permission.py _has_destructive_command 按 `&&/;/
C-14 mcp.py _send_request 校验 resp["jsonrpc"] == "2.0"resp["id"] == req_id
C-15 mcp.py Popen(text=False) binary pipes;_read_framestdout.read(content_length) 字节精确读取 + .decode("utf-8")
C-16 mcp.py _read_frame 循环读 header 直到空行,忽略 Content-Type 等未知 header

🟡 中等

# 文件 修复
C-12 tests/ ruff 26 个告警全部修复:F401 unused import / E721 == typeis type / F841 unused variable
C-17 cli.py doctor build_client(base_url=settings.base_url or None)
C-18 mcp.py _build_input_model non-required 字段类型 T | None,显式 null 通过 Pydantic 校验

验证记录

检查 结果
pytest -v ✅ 135 passed
ruff check . ✅ All checks passed
my-agent --help ✅ 可用(需 scripts/fix_pth.sh 修复 .pth)

Plan.md 完成总览

Phase 内容 测试数
0 Hello Loop 7
0.5 Anthropic SDK 切换 21
1 Tool Loop 53
2 权限/流式/REPL 90
3 会话/压缩/子Agent/Hook/多Provider 123
4 Doctor/插件/Cache/MCP 135

累计:18 个模块,135 个测试。Plan.md 全部完成。