Skip to content

Latest commit

 

History

History
782 lines (540 loc) · 53.7 KB

plan.md

File metadata and controls

782 lines (540 loc) · 53.7 KB

MiniCode-go 开发计划

目标:用 Go 实现一个面向学习的迷你版 Pi。
交互方式:CLI 优先。
当前状态:Day 0~Day 15 已完成。Day 14 真实模型三轮压缩验收和三个负例均通过;Day 15 已实现常驻记忆、按需目录与详情、文件工具维护及 apps 工作区布局,真实模型的选择与维护验收按用户决定跳过,阶段已收尾。下一阶段为 Day 16,尚未开始。记忆统一通过普通对话维护,专用命令不在范围内。CLI 已支持全屏会话、固定底部输入区和等待输入时的鼠标滚动。

状态标记

  • ✅ 已完成
  • ⬜ 未开始
  • 🔄 进行中
  • ⏸️ 暂缓或延期

总体阶段

Day 0          项目规划
Day 1~Day 7   基础可用版:非流式 Agent + 工具 + CLI + 安全控制
Day 8          可观测性增强:Token 统计 + 过程可视化
Day 9~Day 10  可持续运行版:Session + Provider 抽象
Day 11~Day 12 交互增强版:SSE 流式输出 + 工具参数分片 + 流式 Markdown 渲染
Day 13~Day 14 长任务版:上下文压缩与合法切分
Day 15        项目记忆:跨会话保存、按任务读取与更新
Day 16~Day 17 后续扩展:Subagent 任务委派 + 并行调度与结果汇总
Day 18        运行观测:Session 时间线 + Agent 执行图 + 效率分析与失败诊断

Day 0~Day 14 仍作为单 Agent 的 v0.1 路线;项目记忆、Subagent 与运行观测增强安排在其后的扩展阶段,不作为 v0.1 的验收条件。主 Agent 接收用户任务,把适合独立分析的部分交给子 Agent,再根据返回结果继续执行。

项目记忆放在 Day 15:此前已具备 Session 存储、上下文预算与合法压缩,便于控制记忆注入的大小和位置;随后 Subagent 可以复用项目知识。当前使用工作区根目录的 MiniCode.md 和现有文件工具完成跨会话保存、读取、更新、删除,并通过简短目录按任务读取专题详情。本项目从 apps/ 启动,记忆入口为 apps/MiniCode.md。

后续范围聚焦 MiniCode 本身的执行、工具、上下文、会话恢复、项目记忆、Subagent 和运行诊断。开发验证沿用本项目的自动化测试,并将 MiniCode 自身的典型失败补充为回归用例。

当前已接入可选的 Langfuse / OpenTelemetry 基础链路追踪,覆盖任务、模型请求与响应、工具参数与结果、usage、耗时和错误。Day 18 在此基础上补充会话关联、Subagent 执行图、效率分析和失败诊断。

Session、上下文压缩与项目记忆

能力 保存或处理的内容 使用方式
Session(Day 9 已完成) 完整原始消息及独立压缩检查点(v2);系统 Prompt 恢复时重建 用 --session <id> 继续同一个会话
上下文压缩(Day 13~Day 14 已完成) 当前会话中较早的历史与任务进度 固定保留最近约 20k token,旧历史生成滚动摘要;连续压缩的真实模型验收已通过
项目记忆(Day 15 已完成,真实模型验收按用户决定跳过) 用户明确要求保存的稳定约定、常用命令、专题目录与详情 新会话先读取整个 MiniCode.md,模型再按任务用 read 读取详情,无需恢复旧 Session

当前已完成:Day 0(规划)、Day 1(模型调用)、Day 2(工具协议)、Day 3(Agent Loop)、Day 4(内置工具与注册表)、Day 5(系统 Prompt 与交互会话)、Day 6(资源控制与执行审批)、Day 7(中断与取消)、Day 8(Token 统计与过程可视化)、Day 9(Session 持久化与恢复)、Day 10(Provider 抽象)、Day 11(SSE 流式解析与终端预览)、Day 12(工具分片校验与流式 Markdown 渲染)、Day 13(上下文预算、压缩触发与 LLM 摘要)、Day 14(合法切分、严格消息校验与真实模型语义验收)、Day 15(跨会话项目记忆,真实模型验收按用户决定跳过)。

2026-10-18 收尾 Day 15:按用户决定跳过真实模型的专题选择与记忆维护验收,以“功能已实现,真实模型验收跳过”标为 ✅。跳过项未执行,不记为验收通过;现有本地测试结果保留原记录。下一阶段为 Day 16:Subagent 任务委派与独立上下文,尚未开始。

2026-10-13 完成 Day 14 真实模型验收:通过现有配置的 gpt-5.6-sol 运行 TestCompact_LiveSemanticAcceptance,三轮压缩分别通过 8、7、8 项事实检查,保存恢复与检查点构造均通过;遗漏目标、约束反转和过时测试状态三个负例均被正确拒绝。测试耗时 54.46 秒,Day 14 标为 ✅。本次未显式发送思考强度参数,实际采用模型服务或网关的默认设置。

2026-10-13 接入全屏会话与鼠标滚动:会话共用一个备用屏幕,输入区固定底部,回复、工具状态、审批、统计和错误统一显示在会话区;窗口变化重新排版,退出恢复原屏幕及终端模式。等待输入或审批时支持滚轮、触控板与 PageUp/PageDown,兼容 SGR/X10 鼠标报告,滚动及点击不改动草稿。对应提交为 090c640、410863e;全屏实现后的全量 race 测试、滚动修复后的 CLI 全量 race 测试、go vet 和编译已通过。生成中滚动仍未实现,后续需统一持续接收终端事件并处理自动跟随。

2026-10-13 接入按需记忆并迁移工作区:MiniCode.md 常驻关键约定和 Markdown 目录,模型按适用场景调用 read 读取 .minicode/memory/*.md;详情共用 UTF-8、NUL 和 64 KiB 校验,不套用常驻 token 预算。入口移到 apps/MiniCode.md,四个本地专题位于 apps/.minicode/memory/;配置优先读取工作区内 config/config.toml,仅缺失时兼容旧路径。专题读取、创建/更新/忘记、压缩恢复及 apps 启动测试通过,全量 race 测试、go vet 和编译通过,对应提交为 9e9a857。按用户约定不实现专用记忆命令;当时 Day 15 仅剩真实模型验收,状态为 🔄,后于 2026-10-18 按上述决定收尾。

2026-10-13 初步接入 Day 15:新增 MiniCode.md 读取与完整内容校验,复用 internal/token 粗估预算;Session 独立加载记忆、加入主对话上下文并在压缩后保留。通过现有 read / write / edit 和审批维护文件,根目录记忆写入前校验完整候选内容,整批工具完成后刷新。临时工作区、Fake Provider 和文件工具回归覆盖加载、维护、隔离、预算、连续压缩与恢复;全量 race 测试、go vet 和编译已通过。对应提交为 90e0399、bc6a5d1;当时仅整文件常驻,按需能力与工作区迁移已在后续提交中接入。

2026-10-13 补充 Day 14 实现:将消息序列校验统一到 provider.ValidateMessages,覆盖 Agent、流式与非流式请求、压缩前后和 Session 存档。加入三次连续压缩的事实输入、保存恢复和续接测试,以及显式启用的真实模型逐项语义验收和负例。本地回归、全量 race 测试及 go vet 已通过。早期两次真实模型请求均遇到上游 do_request_failed,当时尚未进入语义判定;后续成功结果见上述完成记录。对应提交为 bd53507、1532161。

2026-10-13 同步历史与上下文分离:compaction.State 保存摘要和 FirstKeptMessageIndex,Session.messages 保留完整原文,模型请求临时构造摘要与近期消息。Session v2 保存原始消息与独立检查点,支持迁移 v1 存档。对应提交为 bd7b824。

2026-10-12 完成 Day 13:固定使用 256 × 1024 token 的上下文窗口、16 × 1024 token 的触发余量和 8 × 1024 token 的输出上限;保留最近约 20,000 token 的完整原始消息,使用 pi 的首次摘要和更新摘要 Prompt 总结更早历史。摘要输入不截断,超预算或服务返回上下文超限时分块处理。手动 /compact、自动触发和超限恢复共用 compaction.Compact;当时的实现成功后替换内存历史,沿用 v1 Session 格式保存。全量测试已通过,相关代码提交为 02fa76e;当前已按上述后续更新分离完整原文与模型上下文。

2026-10-12 补齐 Day 12 实现记录:CLI 累积模型文本,在备用屏幕实时渲染 Markdown,后续增量按 50 毫秒间隔合并刷新;处理未闭合格式、长文本末尾视口、窗口尺寸变化及渲染失败回退。当时关闭预览会等待工作协程结束并恢复光标和主屏幕,当前已改为上述会话级全屏生命周期。实时渲染、合并刷新、并发关闭、PTY 显示与尺寸变化测试已接入;全量测试、CLI race 检查、go vet 和编译已通过。

2026-10-11 补齐 Day 11 实现记录:自动发送 SSE 请求,处理增量文本、工具分片、结束与独立用量事件;CLI 当时在交互终端预览文本,流结束后恢复主屏幕,当前已改为会话级全屏生命周期。断线、错误、取消和超时均关闭流,不写入半截 assistant 消息或执行未完成回复中的工具。工具分片的累积与校验已随本阶段接入。

2026-10-10 完成 Day 10:Agent 依赖统一的 Provider 接口,配置工厂创建 OpenAI 兼容实现;公共响应、错误和 Fake Provider 测试已接入。流式接口与事件契约为 Day 11 提供基础。模型输出 Token 上限配置和默认值已移除。

2026-10-09 完成 Day 9:新会话默认生成 UUID,并将版本、工作区、任务状态和完整协议消息原子保存到 .minicode/sessions/<id>.json;--session <id> 可在同一工作区恢复,恢复时重新生成系统 Prompt,并严格校验 ID、版本、工作区以及工具调用与结果配对。

2026-10-08 完成 Day 8:每项任务结束时汇总模型调用、工具调用、累计耗时和模型响应中的 token usage;交互模式写入标准输出,非交互模式写入标准错误。模型未提供 usage 时显示不可用,部分响应提供时标记为 partial。

2026-10-06 完成中断、超时和普通失败的提示区分,并将原 Day 8(Ctrl+C 中断与 context 取消)调整为 Day 7、原 Day 7(Token 统计与过程可视化)调整为 Day 8。

2026-10-02 补充完成 CLI 多行编辑、运行输出隔离和 Ctrl+C 终端兼容修复。截至当时,这些改动不改变 token 统计、流式输出和会话持久化的待办状态。


Day 0:项目规划 ✅

目标

明确项目定位、核心功能、首版边界和开发路线,不实现运行时代码。

已完成

  • ✅ 确定项目是一个 CLI 优先的迷你版 Pi;
  • ✅ 明确项目主要用于学习 Coding Agent 原理;
  • ✅ 明确 Agent、模型、工具和 CLI 的职责边界;
  • ✅ 梳理核心功能和非目标;
  • ✅ 制定 Day 1~Day 14 开发计划;
  • ✅ 将规划写入 docs/spec.md 和 README.md。

验收标准

  • 能够用一句话说明项目是什么;
  • 能够列出首版必须实现的功能;
  • 能够明确首版不做什么;
  • 后续开发不需要反复重新讨论项目边界。

Day 1:协议结构体 + 单次非流式模型调用 ✅

目标

完成模型 API 的最小非流式调用链路。

内容

  • ✅ 定义请求结构体(ChatRequest / Message / Role);
  • ✅ 定义响应结构体(ChatResponse / Choice / Usage);
  • ✅ 定义消息、错误和响应内容结构(APIError + Error() 实现);
  • ✅ 实现 HTTP 请求(internal/provider/openai.go 内的 Client.Chat);
  • ✅ 处理鉴权(Authorization: Bearer)和基础错误(APIError + 通用 http 错误);
  • ✅ 完成一次用户输入到模型文本输出的调用(cmd/minicode/main.go);
  • ✅ 兼容 OpenAI 风格的嵌套错误格式 {"error": {...}} 与平铺格式;
  • ✅ 入口优先从启动目录的 config/config.toml 读取模型配置,仅文件名确实不存在时兼容旧路径 apps/config/config.toml;旧版 flag 与 MINICODE_* 环境变量已移除;
  • ✅ httptest 覆盖:成功、模型覆盖、API 错误、嵌套错误、非 JSON 错误、context 取消、入参校验、URL 斜杠归一。

产出

  • ✅ 可以发送一条文本请求;
  • ✅ 可以解析模型返回的文本(ChatResponse.Content);
  • ✅ API 错误能够被明确报告(*APIError 通过 errors.As 暴露);
  • ✅ 入口二进制 minicode 已通过端到端 smoke test(happy path + 401 错误 + 网络错误 + 配置缺失)。

Day 2:工具 Schema 定义 + 工具调用响应解析 ✅

目标

让模型知道有哪些工具,并能够解析模型返回的工具调用。

内容

  • ✅ 定义工具 schema;
  • ✅ 定义工具名称、描述和参数;
  • ✅ 解析工具调用名称;
  • ✅ 解析工具调用参数;
  • ✅ 校验参数 JSON;
  • ✅ 区分普通文本响应和工具调用响应;
  • ✅ 定义工具执行结果回传结构。

产出

模型可以返回类似以下信息:

tool: bash
arguments: {"command":"go test ./..."}

程序可以稳定解析并准备执行。

已完成:

  • ✅ 请求通过 tools 携带函数名称、描述和 JSON Schema;
  • ✅ 响应支持一个或多个 tool_calls,并保留调用 ID、名称和原始参数;
  • ✅ 参数须为顶层 JSON 对象,空值、畸形 JSON、数组、null 和标量会被拒绝;
  • ✅ content: null 可无损解析和回传,工具结果使用 role: tool + tool_call_id;
  • ✅ CLI 能区分文本和工具调用,展示全部合法调用但不执行;
  • ✅ black-box 测试覆盖协议线格式、参数校验、多调用、结果消息和 CLI smoke。

Day 3:Agent Loop ✅

目标

打通迷你版 Coding Agent 的核心循环。

内容

  • ✅ 调用模型;
  • ✅ 判断是否存在工具调用;
  • ✅ 执行工具;
  • ✅ 将工具结果回传模型;
  • ✅ 支持多轮工具调用;
  • ✅ 处理工具错误;
  • ✅ 支持最终文本回答;
  • ✅ 设置基础最大轮数。
  • ✅ 达到轮数上限后停止工具执行,额外请求一次最终总结;总结失败时输出停止说明。
  • ✅ 将循环抽到 internal/agent,管理模型调用、消息历史与工具分发;CLI 通过 Output 接口负责展示,并处理任务上下文和退出码。

产出

完成以下闭环:

用户输入
→ 模型请求工具
→ 工具执行
→ 结果回传模型
→ 模型继续判断
→ 最终回答

Day 4:bash、read、write、edit 工具 + 工具注册表 ✅

目标

让 Agent 能够真正操作本地工作区。

内容

  • ✅ 实现 bash 工具(当前目录执行、实时输出、任务超时和输出截断);
  • ✅ 实现 read、write、edit 工具(共享工作区与内容版本记录);
  • ✅ 定义统一工具接口;
  • ✅ 实现工具注册表;
  • ✅ 根据工具名称分发调用;
  • ✅ 为工具生成 schema;
  • ✅ 统一处理工具成功和失败结果。

注意

当前的权限边界采用用户审批,不提供 shell 命令内容黑名单或硬拦截:bash、write、edit 默认逐次展示调用并请求确认,用户拒绝时不执行并把拒绝结果回传模型;--yes 可自动批准。bash 仍按 shell 字符串通过 bash -c 执行,工作目录仅作为启动目录,不提供文件系统隔离。

后续可增加 list_files 和 git_diff 工具,减少对 bash 的依赖。当前工具实现与注册机制位于 apps/internal/tools/。


Day 5:系统 Prompt + CLI 输入循环 ✅

目标

让 Agent 从一次性调用变成可交互的 CLI 程序。

已完成

  • ✅ 编写系统 Prompt,声明 MiniCode 身份、工作区和工具规则;
  • ✅ 说明先读后改、修改后验证、限定任务范围和失败后调整策略;
  • ✅ 默认进入 CLI 输入循环,位置参数作为第一轮任务;
  • ✅ 同一 Session 支持连续多轮输入并保留消息历史,长任务可由 Day 13 的滚动摘要控制历史大小;
  • ✅ 系统 Prompt 始终位于消息历史首位;
  • ✅ 支持 /exit、/quit 和 EOF 退出,空行直接跳过;
  • ✅ 单轮失败后会话仍可继续,同时最终退出码保留失败状态;
  • ✅ 文件工具工作区句柄在 Session 内复用,使“先读后改”校验可以跨轮生效;
  • ✅ CLI 实现集中到 internal/cli,通过 Input / Output 接口与 Agent 会话解耦;
  • ✅ 终端支持多行编辑、自动折行、上下光标移动和滚动显示,上下键不浏览历史;
  • ✅ Shift+Enter / Ctrl+J 插入换行,Enter 提交整段输入;管道输入仍逐行提交;
  • ✅ 支持全屏会话、固定底部输入区与消息滚动;临时流式预览结束后显示完整回复,退出整个会话时恢复原终端屏幕、光标、键盘和鼠标模式。

产出

终端中可以连续使用,后续任务能够引用本次进程中前几轮的对话和工具结果:

> 分析一下这个项目
> 重点看看 main.go
> 根据刚才的分析修改它
> 运行测试
> /exit

当前会话在进程内持续保留,并默认自动保存;跨进程恢复由 Day 9 完成。


Day 6:输出截断 + 轮数上限 + 执行前确认 ✅

目标

为 Agent 增加基础的资源控制和副作用保护。

当前进度

  • ✅ 单次工具输出最多保留 64 KiB,并标记截断;
  • ✅ 每项任务最多进行 500 轮可使用工具的模型请求;
  • ✅ 达到轮数上限后停止工具执行,并额外请求一次不带工具的最终总结;
  • ✅ 每轮任务有独立超时,默认 1 小时,覆盖模型请求、工具执行和最终总结;
  • ✅ 修改文件前请求确认;
  • ✅ 执行 bash 前请求确认;
  • ✅ 用户拒绝后将结果回传模型;
  • ✅ 确认机制作为命令安全边界,不提供危险命令黑名单或硬拦截;--yes 可自动批准。

普通模型请求和达到轮数上限后的总结不设置输出 Token 上限,使用模型服务的默认值。

产出

Agent 具备基本可控性,而不是任由模型无限执行。


Day 7:Ctrl+C 中断与 context 取消 ✅

目标

支持用户随时停止当前任务,并正确取消底层操作。

已完成

  • ✅ 捕获运行期间的 Ctrl+C 与 SIGTERM(signal.NotifyContext 位于 internal/cli/run.go);
  • ✅ 创建可取消的根 context,每轮任务在其之上派生带超时的子 context;
  • ✅ 取消模型 HTTP 请求(provider.Client.Chat 用 http.NewRequestWithContext 构造请求);
  • ✅ 取消正在执行的 bash(命令放入独立进程组,取消时 SIGKILL 整个进程组);
  • ✅ 任务取消时回滚未配对的半轮消息,保证下一次请求合法;
  • ✅ 确保资源释放(延迟关闭 Session 工作区句柄、清理残留后台命令、设置 cmd.WaitDelay);
  • ✅ 识别终端输入阶段传统、Kitty / CSI-u 和 xterm 编码的 Ctrl+C,退出且不提交草稿;
  • ✅ 扩展键盘协议仅随输入 raw 模式启用,提交或退出后恢复,运行中 Ctrl+C 继续触发 SIGINT;
  • ✅ 根 context 取消后不再启动下一轮输入,避免退出时重新进入编辑模式;
  • ✅ 区分用户取消、任务超时和普通失败,分别显示明确的中文提示或原始错误;
  • ✅ 输入、等待模型和等待审批时取消均只输出一次「任务已中断」;
  • ✅ PTY 子进程回归覆盖输入、等待模型、等待审批、位置参数任务及终端状态恢复。

产出

用户按下 Ctrl+C 后退出整个会话,Agent 不会继续执行后续工具;输入模式、扩展键盘协议和备用屏幕得到恢复。中断退出码为 1,CLI 显示「任务已中断」;任务达到时限时显示「任务执行超时」,普通失败保留具体错误。


Day 8:Token 统计 + 过程可视化 ✅

目标

让用户能够看到 Agent 的运行过程和资源消耗。

已完成

  • ✅ 按任务累计模型响应中的输入、输出和总 token;
  • ✅ 统计模型调用次数,包括达到轮数上限后的总结请求;
  • ✅ 统计实际开始处理的工具调用次数;
  • ✅ 展示当前模型轮次和当前工具;
  • ✅ 展示工具执行完成、失败、拒绝或取消状态及耗时;
  • ✅ 在任务成功、失败、超时或取消后展示累计耗时和任务统计;
  • ✅ 模型完全未返回 usage 时显示 Token 不可用;
  • ✅ 仅部分模型响应返回 usage 时显示 (部分统计),避免把不完整数据误作完整统计;
  • ✅ 当响应的 total_tokens 为 0、但输入或输出 token 非零时,以两者之和补全该次总数;
  • ✅ 交互模式将统计写入标准输出,非交互模式写入标准错误,保持标准输出中的最终回答可供管道处理;
  • ✅ 测试覆盖完整、缺失和部分 usage,以及 CLI 端到端累计结果。

产出

CLI 在每项任务结束后展示类似:

[turn 2] calling bash
[state] bash completed in 1.2s
[统计] 2.3 秒 | 模型 2 次 | 工具 1 次 | Token 3,740(输入 3,200 / 输出 540)

统计是当前任务级汇总,不是整个交互 Session 的累计值。token 数取自模型服务返回的 OpenAI 兼容 usage,MiniCode 不在本地估算缺失的 token;因此不提供 usage 的服务会显示 Token 不可用。


Day 9:Session 持久化与恢复 ✅

目标

让 CLI 会话可以保存,并在下次启动时恢复。

已完成

  • ✅ 定义带版本号、UUID、工作区、上一轮状态和协议消息的 JSON Session 结构;
  • ✅ 保存用户消息、模型响应、工具调用和工具结果;
  • ✅ 每轮结束后保存 completed 或 failed 状态;
  • ✅ 新会话默认生成 UUID,并立即创建 .minicode/sessions/<id>.json;
  • ✅ 使用权限为 0600 的临时文件、磁盘同步和原子重命名写入;
  • ✅ CLI 显示会话 ID,并通过 --session <id> 恢复当前工作区已有存档;
  • ✅ 恢复时按当前版本重新生成系统 Prompt,不恢复运行中进程、审批状态或文件读取缓存;
  • ✅ 严格校验 ID、文件大小、JSON 字段、版本、工作区和工具调用结果配对;
  • ✅ 单元测试与 CLI 双进程端到端测试覆盖自动保存、恢复和错误路径。

产出

新会话直接启动并记下输出的 ID:

$ minicode
[会话] 550e8400-e29b-41d4-a716-446655440000

随后在同一工作区恢复:

minicode --session 550e8400-e29b-41d4-a716-446655440000

恢复后与正常启动一样进入输入循环,可以直接输入下一项任务,无需附加提示词。--session 只接收已有会话的标准小写 UUID,不接收文件路径。


Day 10:Provider 抽象层 ✅

目标

将 Agent 核心与具体模型服务解耦。

内容

  • ✅ 定义 Provider.Chat 接口,Agent 和最终总结依赖接口,不依赖具体 Client;
  • ✅ 使用公共 ChatRequest 和 ChatResponse 表达请求与完整响应,保留消息、工具调用与可选 usage;
  • ✅ 定义可选的 StreamingProvider.ChatStream、Stream.Recv/Close、StreamEvent 和工具调用增量;
  • ✅ 模型服务的 HTTP 错误统一为 APIError,网络与 context 取消错误保留可追溯的错误链;
  • ✅ 通过 provider.New 选择实现并校验配置,model.provider 可选,默认为 "openai";
  • ✅ 使用 Fake Provider 测试工具调用与历史、错误恢复、用量统计、500 轮上限及最终总结,不调用真实模型服务。

当前实际适配器只有 OpenAI 兼容 Chat Completions 实现。兼容服务可通过地址、密钥和模型名切换;新增专用协议需实现 Provider 并接入配置工厂。Day 11 已实现 Client.ChatStream 的 SSE 请求与解析,Agent 自动使用流式能力。

产出

Agent Loop 和工具系统可以复用同一个模型调用接口;新增适配器时无需修改这两部分。接口与工厂见 apps/internal/provider/provider.go,测试见 apps/test/provider/provider_test.go 和 apps/test/agent/run_test.go。


Day 11:SSE 流式解析 ✅

目标

实现模型响应的流式接收。

内容

  • ✅ 建立 SSE HTTP 请求,发送 stream: true 和 stream_options.include_usage: true;
  • ✅ 按空行分隔事件,解析 event / data,合并多行数据;支持 LF、CRLF、CR、BOM、注释及长事件,并限制单个事件大小;
  • ✅ 处理增量文本、按索引关联的工具分片和最终用量;
  • ✅ 读取到 [DONE] 才结束,finish_reason 后继续接收可能单独返回的 usage;
  • ✅ 处理 HTTP / SSE 业务错误、JSON 解析错误、提前断线与异常结束;
  • ✅ 支持 context 取消、超时和并发关闭,关闭流可中断阻塞读取;
  • ✅ 通过可选的 StreamOutput 把增量传给 CLI,流结束或失败时清理预览;
  • ✅ 自动使用 Provider 的流式能力,不设置 CLI 或 Session 流式开关;仅不具备该能力或明确返回 ErrStreamingUnsupported 的 Provider 回退到 Chat;
  • ✅ 保留任务用量统计和 Langfuse 追踪,并覆盖 Provider、Agent、CLI、会话存档及 PTY 终端恢复测试。

产出

Day 11 接入了备用屏幕中的即时增量预览。当前 CLI 按后续全屏实现共用会话屏幕,完整最终回复、工具状态及审批信息均在会话区显示;非交互输出只交付完整回复,不包含增量预览。

为保持四个内置工具在流式模式下可用,本阶段同时接入了工具名称、参数累积和完整校验;流失败时不执行该次回复中的工具,也不将半截 assistant 消息写入历史。

实现见 apps/internal/provider/openai_stream.go、apps/internal/agent/stream.go 和 apps/internal/cli/output.go。流式回归入口位于 apps/test/provider/openai_stream_test.go、apps/test/agent/stream_test.go、apps/test/cli/stream_test.go 及 apps/test/cli/run_terminal_test.go。


Day 12:tool_calls 参数分片累积 + 流式 Markdown 渲染 ✅

目标

完善流式工具调用,并让文本在生成过程中持续呈现 Markdown 排版。

内容

  • ✅ 累积分片的工具名称;
  • ✅ 累积分片的工具参数,支持多个调用交错返回并按索引恢复顺序;
  • ✅ 处理参数 JSON 尚未完整的中间状态,不在接收片段时执行工具;
  • ✅ 整条流正常结束后校验工具 ID、类型、名称、JSON 参数和结束原因,再进入审批与执行;
  • ✅ 累积收到的文本,复用现有 Markdown 渲染器,在交互终端的备用屏幕更新预览;
  • ✅ 合并高频增量,首帧直接渲染,后续按 50 毫秒间隔检查文本与尺寸变化;同宽度下复用渲染器,相同预览帧不重复写入;
  • ✅ 处理尚未闭合的代码块、加粗、列表和表格,保证中间内容可读;渲染失败时回退到原文预览;
  • ✅ 处理终端宽度变化和长文本末尾视口,逐行清理旧内容,并使用同步更新序列减少重排闪烁;没有新分片时也能响应尺寸变化;
  • ✅ 流结束时清除临时预览,在当前会话屏幕展示完整 Markdown;退出会话或 Ctrl+C 时恢复原终端,非交互输出只交付完整回复;
  • ✅ 区分文本增量和工具调用增量,CLI 只预览文本;
  • ✅ 处理流式响应结束前的异常,关闭流并丢弃未完成回复。

工具分片与执行前校验已随 Day 11 接入。本阶段完成生成过程中的 Markdown 渲染,采用累计文本、定时合并刷新与备用屏幕重绘。当前 CLI 共用全屏会话,预览自动跟随末尾,完整回复进入会话区;流关闭后不再追加上一轮临时文本,下一次模型调用创建新的预览内容。

验收标准

  • 标题、列表和代码块在模型回复结束前即可呈现 Markdown 排版;后续分片到来时更新已有预览;
  • Markdown 标记跨分片或尚未闭合时,中间内容可读,完整回复的最终排版正确;
  • 高频分片、长文本和终端尺寸变化不会导致重复内容或旧排版残留;
  • 单次流正常结束、错误或超时后清除临时预览,退出整个会话或 Ctrl+C 时恢复原终端;管道输出不包含预览或终端控制字符;
  • 使用分片响应与 PTY 测试覆盖中间渲染、合并刷新、渲染失败回退及终端恢复。

产出

CLI 在生成过程中持续展示 Markdown 排版,结束后在会话区保留完整回复,并在工具参数接收完整、校验通过后执行工具。

实现见 apps/internal/cli/stream_preview.go、apps/internal/cli/output.go 和 apps/internal/cli/markdown.go;当前全屏 CLI 的渲染与视口位于 apps/internal/cli/screen.go。回归测试位于 apps/test/cli/stream_preview_test.go、apps/test/cli/stream_preview_terminal_test.go、apps/test/cli/output_test.go、apps/test/cli/screen_terminal_test.go 及 apps/test/cli/run_terminal_test.go。


Day 13:上下文压缩触发与摘要 ✅

目标

避免长任务导致上下文无限增长。

内容

  • ✅ 使用最近一次主对话 usage 校准上下文占用,并估算新增消息、工具参数、结果和工具声明;
  • ✅ 固定 ContextWindow = 256 * 1024、ReservedTokens = 16 * 1024,剩余空间严格小于余量时触发压缩;
  • ✅ 在每次模型请求前检查预算,包含本次新用户输入;工具执行期间等待完整批次结果追加后再检查;
  • ✅ 保留系统 Prompt,摘要使用目标、约束与偏好、进度、关键决策、下一步和关键上下文的结构;
  • ✅ 固定 KeepRecentTokens = 20000,按完整消息和工具批次选择接近预算的边界,不提供配置项;
  • ✅ 使用当前 Provider 的独立、无工具 Chat 请求生成摘要,借用 pi 的首次和更新摘要模板;
  • ✅ 完整序列化旧用户消息、assistant 文本、工具名称、参数、调用 ID 和结果,摘要输入不做固定字符截断;
  • ✅ 摘要输入超预算时按 UTF-8 边界分块,每块更新已有摘要;服务端上下文超限时拆小当前块继续处理;
  • ✅ 修改文件、测试状态、已知错误与后续工作由 LLM 归纳到进度和关键上下文中,暂未提供独立元数据字段;
  • ✅ 手动 /compact、自动压缩、上下文超限恢复共用同一函数;主对话超限仅重试当前模型请求一次,不重新执行工具;
  • ✅ 摘要调用和 usage 计入任务统计,成功更新检查点后清空旧预算校准,下一次主对话回复重新校准;
  • ✅ 手动压缩成功后立即保存,自动压缩和超限恢复在本轮结束时保存;恢复完整原始消息与检查点,模型只读取摘要和近期原文;
  • ✅ 摘要失败、为空、被输出长度限制截断、返回工具调用或被取消时,保留压缩前历史;没有可压缩旧内容时不调用模型。

20k 是近期原文的近似目标,始终至少保留最新的一条完整消息或工具批次;这个整体本身很大时,保留量可能超过 20k。会话保留边界不拆协议消息,摘要请求的文本分块可以跨消息或参数文本,但不会省略剩余内容。

256k 是代码中的固定窗口假设,未自动读取所用模型的实际窗口。最新输入本身过大或最新工具批次无法放入模型窗口时,历史压缩不保证请求一定成功。

产出

压缩后的模型上下文为“系统 Prompt → 项目记忆(Day 15 接入,如有)→ 新摘要 → 近期原始消息”,后续请求临时构造这份上下文。完整原始历史继续保留在 Session.messages 和 v2 存档中,独立检查点记录摘要与近期消息起点。v1 存档迁移后保留其现存原文,已被旧版压缩丢弃的内容无法恢复。摘要中的工作区和文件信息仍需结合当前实际状态验证。

实现见 apps/internal/compaction/trigger.go、compact.go、prompt.go 和 apps/internal/agent/compact.go。测试见 apps/test/compaction/trigger_test.go、compact_test.go、apps/test/agent/compact_test.go 与 apps/test/cli/compact_test.go,覆盖阈值、完整输入、滚动更新、分块、工具配对、失败与取消、统计校准、超限恢复不重放工具及手动压缩存档恢复。go -C apps test ./... 已通过。


Day 14:压缩切分合法性与上下文保留验收 ✅

目标

保证压缩后的模型请求具有合法消息结构,并验收连续压缩后的目标、约束和最新进度保留情况。

内容

  • ✅ 会话保留边界按完整协议消息切分;
  • ✅ 不拆分 assistant 工具调用和该批次的全部工具结果;
  • ✅ 工具批次全部完成后才检查压缩预算,未完成响应继续由原有回滚逻辑处理;
  • ✅ 会话保留边界不拆开单条工具调用中的 JSON 参数;
  • ✅ 公共 provider.ValidateMessages 校验角色字段、工具调用 ID、类型、名称、参数 JSON 和调用结果配对;工具批次结束前不能插入其他角色的消息;
  • ✅ Agent 的上下文构造和 s.chat、Provider 的共用 prepareRequest 接入发送前校验;覆盖流式、非流式、超限重试和轮数上限总结,非法消息在本地报错;
  • ✅ 压缩输入和候选输出共用校验;检查点校验通过后才提交,构造上下文前检查保留起点,存档保存和恢复复用协议校验并保留禁止保存 system 消息的规则;
  • ✅ 三次连续压缩的固定场景覆盖“测试失败 → 修复后通过 → 再次修改尚未复测”,每轮确认实际推进切分边界,并保存恢复检查点;Fake Provider 验证原始事实和旧摘要完整传递,恢复后的 Agent 读取最终摘要继续任务;
  • ✅ 真实模型语义验收入口逐项检查任务目标、用户约束、工作区、修改文件、测试命令、最新测试状态和下一步;准确路径、命令及当前失败信息另做原文检查;
  • ✅ 验收者使用同一配置模型的独立请求,肯定结论必须引用摘要原文;加入遗漏目标、约束反转、过时测试状态的负例,以及报告缺项、重复 ID、无证据、无效 JSON 和回复截断的本地检查;
  • ✅ 摘要失败或取消时保留压缩前历史,超限恢复不重放已执行工具。

验证结果

消息结构校验、三次压缩的流程回归及验收报告检查已通过;全量 race 测试和 go vet 已通过。Fake Provider 的参考摘要验证传递和恢复流程,真实摘要的语义质量由显式启用的模型验收判断。

2026-10-13 使用配置模型 gpt-5.6-sol 完成真实模型测试,耗时 54.46 秒,全部通过:

场景 验收内容 结果
failed 测试失败阶段,8 项事实及准确引用 通过
passed 修复后测试通过阶段,7 项事实及准确引用 通过
modified_after_pass 再次修改尚未复测阶段,8 项事实及准确引用 通过
missing_goal 摘要遗漏目标 正确拒绝
reversed_constraint 摘要反转依赖约束 正确拒绝
stale_progress 摘要把尚未复测写成已通过 正确拒绝

三轮均实际推进压缩边界,并完成保存、恢复和模型上下文检查。验收没有显式设置 reasoning_effort,采用服务端默认值。早期两次请求曾在首次摘要时遇到上游 do_request_failed;本次已获得完整通过结果,Day 14 标为 ✅。该结果对应固定测试场景和当次模型配置,后续更换模型或修改摘要流程时可重新验收。

从仓库根目录运行;测试先切换到仓库根目录,优先读取 config/config.toml,不存在时读取本项目通常使用的 apps/config/config.toml:

MINICODE_TEST_LLM=1 go -C apps test ./test/compaction -run '^TestCompact_LiveSemanticAcceptance$' -count=1 -v -timeout=10m

普通 go test 默认跳过真实模型测试;语义验收仅在测试阶段运行。

产出

已实现压缩后和发送前的严格消息校验,建立连续压缩与恢复的回归场景和真实模型语义验收入口。实现见 apps/internal/provider/messages.go、apps/internal/agent/compact.go、stream.go 和 apps/internal/compaction/compact.go;测试见 apps/test/provider/messages_test.go、apps/test/compaction/semantic_test.go、semantic_live_test.go,以及现有 Agent、Session 和压缩测试。


Day 15:跨会话项目记忆 ✅

目标

让 MiniCode 在同一项目的新会话中复用稳定知识,例如测试命令、代码风格、模块职责和已经确认的技术决策。用户无需恢复旧 Session 或重复解释项目约定。

已实现

  • ✅ 使用当前工作区根目录的 UTF-8 文件 MiniCode.md 保存常驻记忆与目录;本项目工作区为 apps/,入口为 apps/MiniCode.md。不扫描父目录或全局目录,不使用 JSON 条目库;文件不存在或为空时不注入,不自动创建;
  • ✅ memory.Load 与 memory.NewDocument 共用完整内容校验:最多 64 KiB、不含 NUL、原文最多 4,096 个本地估算 token;读取还检查普通文件与工作区路径边界,失败明确返回,不截断;
  • ✅ 新建和恢复 Session 时读取当前文件,每个用户轮次和手动 /compact 前重新读取;模型上下文为“系统 Prompt → 项目记忆(如有)→ 摘要(如有)→ 近期原文”;
  • ✅ 项目记忆以带 <project-memory> 标记的独立 user 消息加入请求,提示模型按系统规则和本次用户要求处理冲突;正文与包装计入整体上下文预算;
  • ✅ 记忆缓存独立于原始消息和压缩检查点,不向 Session 快照增加字段,不将自动注入的记忆块送入摘要;连续压缩和恢复后仍读取当前项目记忆;
  • ✅ 复用现有 read / write / edit 与审批完成创建、更新、删除指定内容和清空。清空使用空内容覆盖,留下空文件;成功修改规范化路径为根目录 MiniCode.md 的文件后,整批工具结果完成再刷新;
  • ✅ write 和 edit 对根目录记忆的完整候选内容做落盘前校验,失败保留原文件;未新增工具、条目 ID 或通用文件版本机制;
  • ✅ 系统 Prompt 要求只有用户明确提出记忆维护时才写入,先读取并保留无关内容,避免重复、替换冲突约定,删除后未经重新授权不从历史写回;这些语义规则由模型遵循提示,宿主未实现逐条语义去重或意图判定;
  • ✅ 按需详情放在 .minicode/memory/*.md,目录项包含名称、适用场景和相对路径。模型根据任务选择 read,宿主不扫描或预读全部详情;读过的正文进入普通工具历史和压缩;
  • ✅ memory.ValidateFile 校验根目录完整候选及详情内容,read / write / edit 对详情共用 UTF-8、NUL 和 64 KiB 限制;详情不套用常驻 4,096 token 预算。提示模型先保存详情再更新目录,忘记专题先清空正文再移除目录项;
  • ✅ 索引已建立代码组织、会话与上下文压缩、项目记忆、终端交互四个专题,位于 apps/.minicode/memory/;该目录继续由 Git 忽略,作为本地资料;
  • ✅ 支持从 apps/ 启动:配置优先读取 config/config.toml,仅缺失时兼容旧路径,首选文件损坏或不可读不回退;不硬编码记忆工作区,也不移动原工作区的 Session;
  • ✅ 临时工作区与 Fake Provider 测试覆盖跨会话加载、项目隔离、预算、缺失与空文件、创建/更新/删除/清空、审批拒绝、失败写入、整批工具后刷新,以及连续压缩和恢复。

验证状态与收尾结论

上述加载、维护和按需流程已有本地回归,2026-10-13 全量 race 测试、go vet 和编译通过。新增测试覆盖未读取详情不注入、无关超限或缺失文件不阻断启动、已读正文参加压缩、恢复后重读当前详情、专题与目录的维护,以及 apps 工作区启动和配置回退。Fake Provider 固定工具调用和模型回复,用于验证宿主流程;实际模型的专题选择与维护行为未进行真实任务验收。

读取到损坏、不可读或超预算的根目录记忆时,启动或当前任务返回错误;不会跳过错误继续使用旧缓存。详情仅在显式 read 时返回读取错误,未选择的详情不影响启动。写入候选校验失败作为工具错误回传,模型可以修正重试;整批工具完成后的根目录刷新失败保留已完成历史并停止该次任务。

2026-10-18,用户决定跳过以下真实模型验收,不再作为 Day 15 的完成条件:

  • 已跳过:用真实模型验证按适用场景选择详情,相关任务能读取,无关任务无需读取,读取失败时不凭目录猜测正文;
  • 已跳过:用真实模型验证明确保存、冲突更新、避免重复和删除后不重新写回;关键命令与结论仍结合当前工作区验证。

Day 15 以“功能已实现,真实模型验收跳过”收尾,标记为 ✅;上述跳过项未执行,不记为验收通过。下一阶段为 Day 16,尚未开始。

按用户约定,查询和维护统一走普通对话与现有文件工具,/memory、/forget 不属于待实现项。

常驻与按需记忆(已接入)

参考 pi 的两种资源加载方式:项目上下文文件正文进入系统 Prompt;Skills 启动时只提供名称、描述和路径,模型在任务需要时读取全文。这里借鉴其加载方式设计项目记忆,不将 Skills 等同于长期记忆条目库。来源见 pi 系统 Prompt 实现 和 pi Skills 加载说明。

采用普通 Markdown 目录,复用现有 read,不新增索引数据库;下面是相对工作区的路径,本项目实际位于 apps/ 下:

位置 内容 加载方式
根目录 MiniCode.md 关键约束、常用命令,以及详情的名称、适用场景和路径 整文件常驻,目录也受 4,096 token 原文预算约束
.minicode/memory/<topic>.md Session、压缩等专题的详细结论 模型按任务选择,再用 read 读取

只在同一个 MiniCode.md 内标注“常驻”和“选择性”不会减少注入量;详情正文已放在独立文件中。模型可能漏读目录,因此关键约束仍放常驻部分,用户也可明确要求读取指定文件。目录选择、去重和同步由模型遵循提示完成,多文件修改不是一个原子事务。根目录与 apps/ 下的 .minicode/ 均被 Git 忽略,详情是本地资料;需要随仓库共享时另行确定位置。当前没有自动扫描、关键词匹配或向量检索。

产出

实现见 apps/internal/memory/load.go、files.go、apps/internal/token/estimate.go、apps/internal/agent/memory.go、compact.go、run.go、prompt.go,以及 apps/internal/tools/read.go、write.go、edit.go 和 apps/internal/config/config.go。测试见 apps/test/memory/load_test.go、files_test.go、apps/test/agent/memory_test.go、memory_mutation_test.go、memory_detail_test.go、apps/test/tools/memory_test.go 和 apps/test/cli/config_test.go。

会话 A:用户要求保存专题 → 读取现有文件 → 审批并保存详情 → 更新目录 → 刷新常驻记忆
会话 B:加载 MiniCode.md → 根据当前任务选择目录项 → read 对应详情 → 结合项目状态执行并验证

项目记忆复用稳定知识;任务续接使用 Session 保存的原始历史和检查点,长对话的长度控制由上下文压缩负责。删除或清空项目记忆不会清除旧会话中的用户消息、工具结果或摘要。


Day 16:Subagent 任务委派与独立上下文 ⬜

目标

主 Agent 可以把一个明确的子任务交给独立的 Agent 执行,并接收结果。例如,主 Agent 负责修复问题,子 Agent 负责阅读某个模块并找出相关调用链。

内容

  • 定义子任务请求,包含任务目标、必要背景、工作区和期望返回内容;
  • 为子 Agent 分配独立 ID,并记录父会话 ID,关联一次委派和对应结果;
  • 复用现有 Provider 和 Agent Loop,以独立消息历史运行子任务,不启动 CLI 输入循环;
  • 子 Agent 使用专用系统 Prompt,只接收主 Agent 提供的任务背景及选出的相关项目记忆,不自动复制父会话全部历史;
  • 为主 Agent 注册 delegate_task 工具;先实现一次委派、等待完成、结果回传的完整流程;
  • 首个版本子 Agent 仅开放 read 工具,代码修改和 bash 执行由主 Agent 统一处理;子 Agent 不开放委派工具,委派深度固定为一层;
  • 子任务继承父任务的取消和剩余时限,并设置独立模型轮数上限;
  • 返回明确的完成、失败、超时或取消状态,以及结论、文件位置、依据和未解决的问题;
  • 主 Agent 将子任务结果作为委派工具的结果写入历史,再决定下一步,不把子 Agent 全部消息合并到父上下文;
  • 使用 Fake Provider 覆盖委派参数、上下文隔离、工具权限、结果回传和失败路径。

验收标准

  • 主 Agent 可以委派一次模块分析,并基于子 Agent 的结果继续回答或调用工具;
  • 父子消息历史互不混入,子 Agent 无法调用未开放的工具或再次委派;
  • 子任务失败能作为工具结果回传主 Agent,不强制终止整个父任务;
  • 父任务取消时,子任务的模型请求同步取消,文件句柄等资源得到释放。

产出

用户要求修复问题
→ 主 Agent 委派“分析相关模块与调用链”
→ 子 Agent 独立阅读并返回结论与文件位置
→ 主 Agent 结合结果修改代码、运行验证并回答用户

Day 17:Subagent 并行调度、过程展示与恢复 ⬜

目标

支持同时处理多个互不依赖的分析任务,让用户能看到子任务进度,并能统一取消和汇总结果。

内容

  • 增加子任务管理器,维护排队、运行、完成、失败、超时和取消状态;
  • 支持批量委派独立子任务,配置同时运行的数量上限和单次委派数量上限,超出并发上限的任务排队;
  • 按任务 ID 等待和收集结果,允许部分子任务失败,主 Agent 能区分成功结果与失败原因;
  • 每个子任务独立管理消息历史、工作区句柄和输出事件;沿用只读工具范围,由主 Agent 统一执行修改;
  • 父任务取消时停止排队任务,并取消所有运行中子任务;等待它们退出后再结束父任务;
  • 为整项父任务设置模型调用总预算,覆盖父子 Agent,防止增加子任务后绕过资源限制;
  • CLI 按子任务 ID 展示开始、完成和失败状态,统一处理并发输出,避免多个 goroutine 同时读取 stdin 或直接写终端;
  • 汇总父子任务耗时、模型调用和 token usage;子任务数据计入父任务一次,缺失 usage 沿用现有不可用或部分统计语义;
  • 保存父子关联、子任务状态和已完成结果;恢复会话时,原先排队或运行的任务标记为已中断,由主 Agent 决定是否重新委派,不自动恢复进程;
  • 使用 Fake Provider 和可控制的阻塞点验证并发上限、排队、结果归属、部分失败、取消、统计及恢复行为;对并发路径运行 race 检查。

验收标准

  • 两个独立模块分析可以并行执行,运行数量始终不超过配置上限;
  • 一个子任务失败时,其他子任务仍可完成,主 Agent 能拿到全部结果和状态;
  • Ctrl+C 能停止所有子任务,退出后没有遗留 goroutine 或正在执行的模型请求;
  • 父任务统计不会漏计或重复计算子任务用量,非交互 stdout 仍只输出主 Agent 的最终回答;
  • 恢复会话后可以查看已完成的子任务结果,并明确识别中断任务。

产出

主 Agent 可以并行委派“分析配置加载”和“分析会话恢复”,等待结果后给出统一结论,并继续完成代码修改和验证。


Day 18:Langfuse / OpenTelemetry 会话追踪、效率分析与失败诊断 ⬜

目标

按 Session 回看 MiniCode 的任务过程,展示主 Agent 与 Subagent 的调用关系,定位失败原因及耗时和 Token 消耗较高的环节。

内容

  • 将本地 Session ID 关联到 Langfuse,每轮任务保持独立 Trace;跨进程恢复后仍归入同一 Session,形成连续的会话时间线;
  • 为主 Agent、子任务、模型请求与工具执行建立父子 Span,传递 OpenTelemetry context,并记录 Agent ID、父任务 ID、轮次和状态;
  • 使用 Langfuse 的 Agent 图与时间线展示委派、并行执行和结果汇总,点击记录可查看输入、回复、工具参数、结果及错误;
  • 区分模型等待、审批等待、工具执行和子任务排队的耗时,支持定位慢请求与失败步骤;
  • 按 Agent 和模型汇总模型调用次数、输入与输出 Token,并统计工具耗时、重复读取和连续失败重试;
  • 根据模型价格配置估算成本;缺少 usage 或价格时标记为不可用或部分统计,父子任务用量只累计一次,任务总耗时按实际起止时间计算;
  • CLI 可输出对应的 Trace / Session 查看链接;非交互模式写入 stderr,保留 stdout 的最终回答;
  • 保持追踪可选,上传失败不阻断 Agent 任务,关闭追踪时不影响原有执行与会话恢复;
  • 从 MiniCode 自身的失败记录中提炼最小文件样例、工具结果或固定模型响应,补充到现有 Agent、工具和 CLI 回归测试;
  • 通过本地 OTLP 接收端验证 ID 关联、父子关系、并发任务归属、错误状态、用量聚合与退出刷新。

验收标准

  • 同一 Session 在两次进程启动中的任务能归到同一会话时间线,历史记录不会因恢复而重复上传;
  • 一个包含两个并行 Subagent 的任务能展示完整调用关系,并定位各子任务的模型和工具调用;
  • 可以识别最慢步骤、Token 消耗最多的 Agent,以及重复读取或持续重试的任务;
  • 典型失败能定位到具体模型或工具调用,并通过本项目自动化测试复现和验证修复;
  • 缺失数据不会被显示为零成本,追踪服务不可用时任务仍可完成,非交互输出保持可供管道处理。

产出

从一个 Session ID 进入执行记录,查看“用户任务 → 主 Agent → 子 Agent → 模型 / 工具 → 汇总回答”,并比较各步骤的耗时与用量。

会话回看使用已记录的数据;任务执行与存档恢复仍由 MiniCode 管理。展示能力参考 Langfuse 的 Sessions、Agent Graphs 和 Token & Cost Tracking。


功能完成情况

当前仓库已完成 Day 0~Day 15,Day 15 的真实模型验收按用户决定跳过;已具备项目记忆加载与维护、流式 Agent、实时 Markdown 渲染、四个内置工具、全屏 CLI 会话、会话持久化、Provider 抽象及 LLM 上下文摘要压缩:

  • ✅ 项目定位与范围规划;
  • ✅ 基础功能清单;
  • ✅ Day 1~Day 14 基础开发计划与 Day 15~Day 18 项目记忆、Subagent、运行观测扩展规划;
  • ✅ v0.1 验收方向;
  • ✅ 模型调用实现;
  • ✅ 工具调用协议与响应解析;
  • ✅ 已支持 bash / read / write / edit 四个内置工具与通用工具注册表;
  • ✅ Agent Loop;
  • ✅ CLI 交互(多行编辑 + 光标移动 + 位置参数 + 管道输入 + 跨轮会话内记忆);
  • ✅ 全屏会话(固定底部输入区、会话记录滚动、流式 Markdown、审批和错误统一展示、退出恢复终端);
  • ✅ 资源控制(工具输出截断、500 轮上限、单轮超时、Ctrl+C 取消);
  • ✅ 执行前确认(bash / write / edit 默认逐次审批,拒绝结果回传模型,支持 --yes 自动批准;不提供命令黑名单或硬拦截);
  • ✅ token 统计与过程可视化(按任务汇总 usage、模型/工具调用次数与耗时;缺失或部分 usage 会明确标记);
  • ✅ 可选 Langfuse / OpenTelemetry 基础链路追踪(任务、模型请求与响应、工具调用、用量、耗时和错误);
  • ✅ Session 持久化与恢复(版本化 JSON、工作区与消息配对校验、原子写入);
  • ✅ Provider 抽象(配置工厂、公共响应与错误、Fake Provider 测试;当前使用 OpenAI 兼容适配器);
  • ✅ SSE 流式处理(自动启用、增量预览、用量事件、错误与中断、完整响应聚合);
  • ✅ 工具调用分片累积与完整校验(随 Day 11 接入);
  • ✅ 流式 Markdown 渲染(50 毫秒合并刷新、末尾视口、尺寸变化、原文回退与终端恢复);
  • ✅ 上下文压缩(固定保留约 20k token、pi 摘要模板、完整输入与分块处理、三个触发入口);
  • ✅ 压缩切分合法性与严格发送前消息校验(Day 14);
  • ✅ 关键上下文保留验收(Day 14,本地流程测试、真实模型三轮逐项验收和三个负例已通过);
  • ✅ 跨会话项目记忆(Day 15,常驻与按需流程、维护、写后刷新及 apps 工作区布局已完成;真实模型选择与维护验收按用户决定跳过,专用命令不在范围内);
  • ⬜ Subagent 任务委派与独立上下文(Day 16,v0.1 之后);
  • ⬜ Subagent 并行调度、过程展示与恢复(Day 17,v0.1 之后);
  • ⬜ Session 时间线、Agent 执行图、效率分析与失败诊断(Day 18,v0.1 之后)。

v0.1 完成标准

当以下流程可以稳定运行时,认为 v0.1 基本完成:

CLI 输入任务
→ 模型分析
→ 调用 bash 查看或验证项目
→ 用户确认后写入文件
→ 继续调用模型
→ 运行测试
→ 测试失败后继续修复
→ 输出最终总结

同时满足:

  • 有最大轮数;
  • 有超时和取消;
  • 有工具输出限制;
  • 有执行前确认;
  • 有 Session 保存和恢复;
  • 有 SSE 流式输出;
  • 有上下文压缩;
  • 有基本测试和过程可视化。