# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
## [0.4.0] - 2026-05-16
> **Phase 12 产品化与公开基准包 — 核心库** 正式发布。
> 本次发布覆盖 W1(底座)+ W2(隔离与安全)+ W3(CLI/Plugin/可观测)+ v0.4.1
> 增强(NEW.1 完整版 / NEW.3 approve_always / 12K.4 cookbook)的全部 7 项 NEW 项。
> 子库部分(cmdc_memory_pg / cmdc_sandbox_* / cmdc_cli / cmdc_acp / cmdc_eval /
> cmdc_examples)将作为独立 Hex 包随后续版本发布。
### Highlights(v0.3.0 → v0.4.0)
- 🪓 **NEW.1 完整版 — 大工具结果 0 token 占用** — 新增 Plugin Pipeline
`:replace_tool_result` action,LargeResultOffload 让 200KB+ result 不再进
message history(写 backend `/large_tool_results/<call_id>`,Agent 看 preview)
- 🛂 **NEW.3 HumanApproval `approve_always` 白名单** — session-scoped
`MapSet<{tool, command_family}>`,连续 `ls /tmp` 5 次后第 6 次自动放行;
原生对接 ACP `request_permission` 三态权限(allow_once / allow_always / reject_once)
- 🏛️ **会话 checkpoint 一等公民** — 新 `CMDC.Checkpoint` facade + `Backend` behaviour
+ ETS/DETS 内置后端;BEAM 重启 / Gateway 滚动 / 跨设备恢复同一会话
- 🗂️ **`CMDC.Backend` 文件抽象(NEW.2 + 1:1 对齐 deepagents BackendProtocol)**
— 10 callback + 8 Result struct + 4 错误码 atom;内置 `State / Filesystem / Composite`
三件套;Composite 支持 prefix 路由(一个会话同时挂 sandbox + PG memory + ETS history)
- 🛡️ **Sandbox 安全模式强化(NEW.4)** — `Backend.Filesystem.virtual_mode=true`
拦截 `..` / `~` traversal + `O_NOFOLLOW` 等价 symlink 防护
- 📜 **`CMDC.Skill` v2 Anthropic spec 对齐(12E.2)** — 加 `license / compatibility /
metadata` 字段 + 名称规范验证 + 文件大小防 DoS + `to_prompt_snippet` 渲染 allowed_tools
- ✂️ **NEW.1 LargeResultOffload Plugin** — `:after_tool` 拦截大工具结果,超
20K tokens 自动写 backend `/large_tool_results/<call_id>` + intervene 注入
read_file 引导
- 🚧 **NEW.6 ContentPolicy Plugin** — LLM-as-Judge 内容安全拦截,4 大策略
类别(越狱/有害/离题/品牌),默认启发式 + judge_fn 扩展点
- 🧠 **NEW.7 EpisodicMemory Plugin** — ADP Ch.8 三类长期记忆补齐情景记忆,
成功 session → few-shot 复用;按 user_id namespace 多租户隔离
- 📊 **`CMDC.Telemetry` 标准事件契约(12G)** — 6 个核心 :telemetry 事件
(agent.turn / llm.request / tool.exec start/stop),emitter 桥接零侵入;接
Langfuse / LangSmith / Tempo
- 🪝 **A2A webhook 异步模式(NEW.5 / cmdc_gateway 0.4)** — `POST /v1/a2a/tasks/
sendWithWebhook` 立即返回 accepted + 后台 Task 派发 5 类回调事件 +
HMAC-SHA256 签名 + 3 次指数退避重试
### Added (核心库 cmdc)
- `CMDC.Checkpoint` 模块 + `Checkpoint.Backend` behaviour + `Snapshot` struct
+ `Backend.ETS` + `Backend.DETS`(17 测试)
- `CMDC.Backend` behaviour + `Results` 8 struct + `State / Filesystem / Composite`
三个内置实现(28 测试)
- `Backend.Filesystem.virtual_mode` + symlink 拦截(1 新增测试)
- `CMDC.Skill` 加 `license / compatibility / metadata` 字段 + Anthropic spec
name 规范验证 + 文件大小 10MB 上限(5 新增测试)
- `Plugin.Builtin.LargeResultOffload` v0.4.1 完整版(4 测试 + Pipeline action 扩展)
- `Plugin.Builtin.ContentPolicy` 默认启发式 + judge_fn 扩展点(7 测试)
- `Plugin.Builtin.EpisodicMemory` 多租户情景记忆 few-shot(8 测试)
- `CMDC.Telemetry` 标准 :telemetry 事件契约 + emitter 桥接(7 测试)
- **Plugin Pipeline 新 action `:replace_tool_result`**(`:after_tool` 钩子专用,
让 plugin 在 raw_result 进入 message list 前替换它 — 12K.1 完整版的基础)
- **HumanApproval `approve_always` session-scoped 白名单 + `:tool_approved_always`
事件 + `command_family/2`**(6 新增测试)
- **`docs/dev/plugin-cookbook.md` 章节七 +184 行**:5 个新配方(LargeResultOffload
/ ContentPolicy / EpisodicMemory / approve_always / 三层组合)
### Added (网关 cmdc_gateway)
- `CMDCGateway.Webhook` 模块:HMAC-SHA256 签名 + 指数退避派发(12 测试)
- `POST /v1/a2a/tasks/sendWithWebhook` 端点 + `CMDCGateway.A2A.start_with_webhook/3`
### Changed
- 命名调整:原 TASK.md 写的 `CMDC.Memory.Backend` 改为 `CMDC.Backend`
(避免与现有 `CMDC.Memory` 语义记忆 behaviour 命名冲突,与 deepagents
`deepagents.backends.*` 1:1 对齐)
### 测试
- cmdc core: **1219 tests + 21 doctests + 0 failures**(+66 vs v0.3.0)
- cmdc_gateway: **125 tests + 0 failures**(+12 vs v0.3.0)
- mix compile --warnings-as-errors / mix format / mix credo --strict 路径全通
### Phase 12 已完成里程碑
✅ NEW.1 LargeResultOffload(v0.4.1 完整版) / ✅ NEW.2 CompositeBackend /
✅ NEW.3 HumanApproval approve_always / ✅ NEW.4 Sandbox virtual_mode + O_NOFOLLOW /
✅ NEW.5 A2A webhook / ✅ NEW.6 ContentPolicy / ✅ NEW.7 EpisodicMemory
**7/7 NEW 项全部达成**。
### 留给子库后续 minor 版本(独立 Hex 包)
- 12A cmdc_cli 子库(escript + headless + exec + threads + mcp 子命令)
- 12B.4 cmdc_memory_pg 子库(PG + pgvector)
- 12D.2/12D.4 Checkpoint facade + Postgres backend
- 12C.1/12C.2/12C.3 cmdc_sandbox_docker / modal / e2b
- 12E.4 cmdc_tui `/skills` slash command
- 12F cmdc_eval(BFCL v3 / tau2 / MemoryAgentBench)
- 12G.6 docs/recipes/observability/ 3 份配方(Langfuse / LangSmith / Tempo)
- 12H cmdc_acp 子库(已具备 NEW.3 事件协议 / Checkpoint resume 等所有依赖)
- 12I cmdc_examples 子库(deep_research / text_to_sql / ralph_mode / coding_assistant)
- 12J 多子库统一发布
### 推迟到 v0.5
- 12C.0 `CMDC.Sandbox` extends `CMDC.Backend` 重构(避免破坏现有 11 Tool + 7 Plugin)
## [0.3.0] - 2026-05-16
**Minor release** — 来自 **Hive 团队 RFC v2 实战反馈**的 13 条 API 升级 + A2A 协议
Task 端点 + Phase 11 多子库联动。所有改动**有 1 条公共 API breaking change**(#B21),
其余对 v0.2.x 完全向后兼容。
### Highlights(v0.2.x → v0.3.0)
- 🔍 **Tool 耗时监控开箱即用** — `pending_tools[].started_at_ms` + 新事件
`:tool_execution_metrics`,无需自己埋点
- 🪝 **新 Plugin hook `:after_turn`** — Agent 回 idle 前结构化 payload,长期记忆闭环
延迟从"下一 session"降到"立刻可用"
- 🔄 **Provider 容灾平滑切换** — `switch_model/3` + 4 元 Plugin action 同步切
`provider_opts`,Anthropic ↔ OpenAI 自建网关零中断
- 📦 **批量原子工具管理** — `attach_tools/2 / detach_tools/2 / replace_tools/2`,
MCP Server 启停一键搞定
- 🛡️ **公共 API 不再 raise/exit** — 所有 facade 在 invalid session / dead pid 时返回
`{:error, :invalid_session|:not_alive}`,集成方告别 `try/rescue/catch :exit`
- 📡 **A2A 协议 Task 端点** — `POST /v1/a2a/tasks/send` 同步 + `/tasks/sendSubscribe`
流式 SSE(cmdc_gateway 0.3.0)
- 🚧 **Gateway Guardrails** — Input/Output filter Plug,黑名单关键字 / 超长 prompt
在 HTTP 边界拦截
- 📚 **完整 Plugin 13×8 矩阵文档** + 友好 Options 校验错误
### ⚠️ Breaking Changes(v0.2.x → v0.3.0)
#### #B21 公共 API 不再 raise/exit
所有 `CMDC.*` facade(含 `attach_tool / detach_tool / status / prompt / abort /
approve / reject / monitor / messages / agent_pid / steer / stop / switch_model /
attach_tools / detach_tools / replace_tools`)在传入 invalid session_id / 已死
pid / 非 pid 非 string 时,从 `raise ArgumentError` / `exit({:invalid_session, _})`
改为返回 `{:error, :invalid_session}` 或 `{:error, :not_alive}`。
**成功路径返回值保持不变**(`:ok` / map / `%CMDC.Message{}` 等)。
**Migration**:
```elixir
# v0.2.x(继续工作,无需改动)
:ok = CMDC.attach_tool(session, MyTool)
%{state: :idle} = CMDC.status(session)
# v0.2.x 在 invalid session 时 raise / exit,下面这种 try/rescue 模式现在可以删
# 旧代码:
try do
CMDC.monitor(session)
rescue
_ -> :ignore
catch
:exit, _ -> :ignore
end
# v0.3 新写法:直接拿 tuple,不再需要 catch
case CMDC.monitor(session) do
{:error, _} = err -> :ignore
ref when is_reference(ref) -> handle(ref)
end
# 旧 `:ok = CMDC.attach_tool(invalid_sid, T)` 模式在 invalid session 下会 MatchError,
# 但这本来就是程序错误(传错 session_id),新行为更可控、可观察。
```
### Added — Phase 11G · Hive RFC v2
来自 Hive 团队 v0.2.1 实战反馈的 `cmdc-rfc-v2.md`,**13 条全收**(A4 + B4 + C4 + D2;
#C25 ring buffer 动态扩容延 v0.4)。
#### A 级(必改 — Hive 有旁路代码可立刻清理)
- **`pending_tools[].started_at_ms` + `:tool_execution_metrics` 事件**(RFC #A15)
- `CMDC.status/1` 返回的 `pending_tools[]` 每项新增 `:started_at_ms` 字段
- 新事件 `{:tool_execution_metrics, name, call_id, meta}`,紧随
`:tool_execution_start` 与 `:tool_execution_end` 各发一次:
- start 时:`meta = %{started_at_ms: integer()}`
- end 时:`meta = %{started_at_ms, ended_at_ms, duration_ms}`
- 现有 `:tool_execution_start` / `:tool_execution_end` 4 元位置参数保持不变
- 适合做 tool 耗时 P99 监控 / 慢工具告警 / 自动 fallback
- **`:after_turn` Plugin hook**(RFC #A16)
- 新增 13 个 Plugin event 中的第 13 个,触发时机:Agent 即将回 idle 前
(finish + 所有 abort 路径)
- payload 含 `outcome / abort_reason / messages_diff / token_usage_diff /
duration_ms / started_at_ms / ended_at_ms`
- 与 `:session_end` 区别清晰:`:session_end` 保持现状(无 payload,向后兼容
EventLogger 等老 Plugin);`:after_turn` 带结构化 payload
- **`switch_model` 4 元组 + `:provider_opts`**(RFC #A17)
- `CMDC.switch_model/3` 新增 `:provider_opts` 选项
- Plugin Action 4 元组形态 `{:switch_model, model, state, provider_opts: [...]}`
- `{:model_switched, %{from, to, provider_opts_changed?}}` 事件 payload 加新字段
#### B 级(强烈建议)
- **`:plugin_event` 自动注入 `user_data`**(RFC #B18)
- `state.user_data` 非空时,emit 的 `{:plugin_event, name, payload}` 当 payload
是 map 时自动 merge `:user_data` 字段
- Plugin 可在 payload 加 `:_no_user_data` 键 opt-out(broadcast 前自动 pop)
- **`:agent_resumed` trigger 扩充**(RFC #B19)
- trigger 新增 `:user_respond / :steering`(除了原有的 `:tool_approved /
:tool_rejected / :tool_approval_timeout`)
- `CMDC.user_respond/3` 紧随 `:user_responded` 后 emit
`{:agent_resumed, %{trigger: :user_respond, ref}}`
- `inject_steering` 完毕后 emit `{:agent_resumed, %{trigger: :steering, refs, count}}`
- **批量原子工具管理**(RFC #B20)
- `CMDC.attach_tools/2` — 批量挂载,任何一个失败全回滚
- `CMDC.detach_tools/2` — 批量卸载
- `CMDC.replace_tools/2` — 替换整张工具表,自动 diff
- 新事件 `{:tools_updated, %{attached, detached}}` 批量操作汇总
- 单个事件 `:tool_attached` / `:tool_detached` 与 v0.2 一致
- **公共 API 返回 tuple**(RFC #B21)— **见上方 Breaking Changes**
#### C 级(锦上添花)
- **EventBus replay 按 type 过滤**(RFC #C22)
- `CMDC.EventBus.subscribe(sid, since: idx, types: [:agent_end, :stream_chunk])`
- 仅影响 replay 阶段,实时订阅不过滤(避免漏事件)
- **`status/1` 累计统计字段**(RFC #C23)
- 新增 `:turns_count`(与 `:turns` 等同,向后兼容别名)
- 新增 `:messages_count` — 当前 messages 列表长度
- 新增 `:active_since_ms` — Agent 进程启动时间戳
- **`abort/2` reason 接受 string + 白名单归一化**(RFC #C24)
- 6 个标准 reason:`:user_cancelled / :timeout / :shutdown / :budget_exceeded /
:permission_denied / :provider_error`
- 对应 string 自动转 atom;不在白名单的 string 归并为 `:unknown` + Logger.warning
(防止前端 JSON 注入任意 atom)
- Atom 入参原样透传(向后兼容)
- **MemoryFlush `:extract_fn` 3 元签名**(RFC #C26)
- 新签名:`extract_fn.(messages, ctx, opts)`,让提取器拿到 `ctx.user_data`
- 老 2 元签名 `extract_fn.(messages, opts)` 自动检测兼容
- 典型场景:按 `user_data.tier` 路由不同 LLM 做事实提取
#### D 级(文档与 DX)
- **完整 Plugin Hook × Action 矩阵**(RFC #D27)
- `CMDC.Plugin` moduledoc 含 13 hooks × 8 actions 完整 ✅/❌ 表
- 每 action 的累积/覆盖/短路语义详解
- 4 种 `:emit` 形态对照
- 4 元 `:switch_model` action 说明
- **`Options.new!` 友好 model 校验错误**(RFC #D28)
- `Options.new!(model: 42)` 报错 message 含 valid providers + 5 个 example
### Added — Phase 11C · cmdc_gateway 0.3 A2A 协议
> 详见 `cmdc_gateway/CHANGELOG.md` 0.3.0 段。
- `POST /v1/a2a/tasks/send` — JSON-RPC 2.0 Task 协议(同步)
- `POST /v1/a2a/tasks/sendSubscribe` — SSE 流式 Task 进度
- `CMDCGateway.Plugs.Guardrails` — Input filter Plug(denylist keywords + regex +
max_prompt_length),默认空,应用层按需配置
- `cmdc_gateway/examples/a2a/` — Elixir + Node.js + curl 客户端示例(11.14)
### Added — Phase 11E · 工具链 / 文档
- `benchmark/` 目录骨架(11.18)— cmdc_skill_engine / cmdc_orchestrator /
cmdc_gateway 各一份基线脚本(Benchee),开发期可跑:
```
MIX_ENV=test mix run benchmark/<name>.exs
```
- `docs/dev/PLANNING.md` Phase 11 决策日志(11.19)— 含 Phase 11G ↔ ADP 章节
追溯表(13 条 RFC 对应 ADP 4/5/7/8/10/14/15/18 多章)
- `docs/dev/rfc/` — RFC 模板 + README + EXAMPLE RFC(11.20),后续集成方按
4 状态流程(DRAFT/IN REVIEW/ACCEPTED/REJECTED)提交
### Tests
- 1136 tests / 21 doctests / 0 failures / 5 skipped(主库)
- 11G 各条带专项集成测试(共 ~65 个新测试)
- cmdc_gateway 113 tests(含 6 个 A2A 端点 + Guardrails 测试)
### Migration Guide
- 大多数代码无需改动 — 成功路径完全向后兼容
- **唯一例外**:依赖 `try/rescue/catch :exit, _` 捕获 invalid session 的代码可以
删掉了,改用 `case CMDC.api(s) do {:error, _} -> ... ; ok -> ... end`
- 如果想用新能力:
- 监控 tool 耗时 → 订阅 `:tool_execution_metrics` 或读 `status.pending_tools[].started_at_ms`
- 长期记忆闭环 → 在 `:after_turn` hook 中处理 `payload.messages_diff`
- Provider 容灾 → 在 Plugin `:before_request` 返回 `{:switch_model, "openai:...", state, provider_opts: [base_url: ...]}`
- MCP 批量挂载 → `CMDC.replace_tools(session, new_mcp_tools)`
### 致谢
- Hive 团队(@hive-platform)— 提交 RFC v2 14 条 issue,13 条全收,1 条延 v0.4
## [0.2.1] - 2026-04-25
**Patch release** — 修掉 v0.2.0 的 Reflection iteration-reset bug,并新增 Planning Pattern
与 Producer-Reviewer Reflection 两大 Agentic Design Patterns 能力。所有改动对 v0.2.0 完全
**向后兼容**;老 Plugin / 老 API 零改动即可升级。
### Fixed
- **`CMDC.Plugin.Builtin.Reflection` iteration reset 死循环** — v0.2.0 该插件在多轮评审时
`iteration` 会被意外重置,导致在某些回合顺序下 Agent 永远不会真正 finish。引入 `phase ::
:idle | :reviewing | :done` 状态机彻底修复,`:done` 之后 `:before_finish` 不再触发。
- **`CMDC.Plugin` behaviour `describe/0` callback 类型声明** — 放宽到 `String.t() | map()`,
消除 `CMDC.Plugin.Builtin.ModelRouter.describe/0` 的 dialyzer callback_type_mismatch 警告。
老插件返回 String 保持有效。
### Added — Phase 11D · Planning + Reflection(对齐 ADP Ch4+Ch6+Ch7+Ch11)
Agentic Design Patterns 对齐首批能力,基于 O'Reilly《Agentic Design Patterns》一书 Ch4 Reflection、
Ch6 Planning、Ch7 Multi-Agent Collaboration、Ch11 Goal Setting and Monitoring 四章设计。
- **`CMDC.Plan` / `CMDC.Plan.Step`(new)** — 显式 Plan 数据结构,含 `step_started/2`、`step_completed/3`、
`step_failed/3`、`step_skipped/3`、`annotate_step/3`、`approve/1`、`progress/1`、`to_markdown/1`、
`to_prompt_section/1`。每个 step 有 `:pending | :in_progress | :completed | :failed | :skipped` 状态。
- **`CMDC.Plan` replan API(ADP Ch6 适应性要求)** — `replace_steps/2` 整体重规划、`add_step/3` 追加、
`insert_step/4` 在指定锚点前/后插入、`remove_step/2` 删除。所有修改自动打 `last_replanned_at` 时戳。
- **`CMDC.Agent.State.dynamic_context_sections`(new)** — Agent 状态新增此字段,Plugin 可通过
`{:emit, {:update_system_context, key, text}, state}` 事件把内容动态注入下一轮 system prompt。
`SystemPrompt` 的 `:full / :task / :minimal` 三种模式都会合并这些动态段落。
- **`CMDC.Context.last_assistant_reply`(new)** — 只读 Context 新增此字段,Plugin / Tool 可直接拿到
最后一条 AI 回复全文,无需自己翻 `messages`。
- **`CMDC.Plugin.Builtin.Planning`(new)** — plan-first 规划插件。对较长 prompt 先 `intervene` 要求
LLM 产出 markdown checklist,`after_response` 解析为 `CMDC.Plan` 并通过 `dynamic_context_sections`
把 plan 持续注入 system prompt。失败重试(`max_plan_attempts: 2`)兜底,放弃后不阻塞主流程。
emit `{:plan_generated, %CMDC.Plan{}}`。
- **`CMDC.Plugin.Builtin.Reflection` 大重构(modified)** — 修掉 v0.2 的 iteration reset 死循环 bug:
- 新 `phase :: :idle | :reviewing | :done` 状态机,`:done` 之后 `:before_finish` 不再触发,杜绝无限循环。
- `max_reviews`(原 `max_iterations` 作为兼容别名)。`pass_signal` 支持字符串或 `%Regex{}`。
- **`reviewer_subagent: true`** — ADP Ch4+Ch7 推荐的 Producer-Reviewer 分离:启动独立 Reviewer
SubAgent(`CMDC.Agent.start_link` 新进程),可用 `reviewer_model` 指定不同模型评审主 Agent 输出,
显著降低同模型自评的认知偏差。SubAgent 失败自动降级为内联自评,永不阻塞主会话。
- emit `{:reflection_approved, %{critique, iteration}}`。
- **Agent before_prompt intervene(modified)** — `CMDC.Agent` 在 `idle` 状态处理 `{:prompt, text}`
和 `do_steer/5` 中的 `:passthrough_to_prompt` 分支,现在正确处理 `{:intervene, prompt, state}`
返回值:把 intervene prompt 作为 user 消息追加,并广播 `{:intervention, prompt}` 事件。
### Changed
- `CMDC.Agent.broadcast_emitted_events/2` 支持 3-tuple emit 事件(被包装成
`{:plugin_event, name, {a, b}}`),用于 `{:update_system_context, key, text}` 等 Plugin→Agent
状态同步。
- `CMDC.Agent.State.to_context/1` 自动填充 `last_assistant_reply`。
### Tests
- `test/cmdc/plan_test.exs` — `CMDC.Plan` 全量单测(新加 47 tests, 16 doctests)。
- `test/cmdc/plugin/builtin/planning_test.exs` — Planning 插件 14 tests。
- `test/cmdc/plugin/builtin/reflection_test.exs` — Reflection 18 tests(完整多轮循环、`phase` 状态机、
regex pass_signal、SubAgent 兜底降级)。
- `test/cmdc/agent/integration_test.exs` — 新增 Planning E2E 2 tests + Reflection SubAgent Reviewer
E2E 3 tests,含多轮 Producer-Reviewer 循环。
- 全量 **21 doctests + 1063 tests, 0 failures, 5 skipped**(v0.2.0 基线 1060 → v0.2.1 共 1063,
所有新模块单元测试累计 47 (Plan) + 14 (Planning) + 18 (Reflection) = 79,
集成测试累计 Planning E2E ×2 + Reflection SubAgent E2E ×3 = 5 条新端到端)。
- `mix dialyzer` passed successfully(v0.2.0 遗留 `model_router.ex` callback 警告一并修复)。
## [0.2.0] - 2026-04-24
This is a major feature release aligning CMDC with the 13 RFC proposals from the
Hive enterprise-agent team (April 2026) **plus** the four Phase 10 items originally
planned for v0.2 (`Steering`, `PromptMode`, `MemoryFlush`, `ModelRouter`).
All additions are **additive and backward-compatible** unless otherwise noted under
"Breaking". Integration code written for v0.1 continues to work with zero changes.
**Stats**: `+17` new features • `991` total tests (0 failures, 5 skipped) • `82.5%`
line coverage (up from 79.2%; four built-in plugins lifted from 0% → 100%) • `0` deprecations.
### Added — Facade API (RFC A1–A4)
- **`CMDC.Options.user_data`** (RFC A1) — opaque business-context map, propagated verbatim
into `CMDC.Context.user_data`. SubAgent and `Tool.Task` inherit automatically unless
the subagent explicitly sets its own `user_data`.
- **`CMDC.create_agent(messages: [...])`** (RFC A2) — inject prior history at boot so
resumed / cloned sessions continue the LLM turn sequence naturally; accepts
`%CMDC.Message{}` structs or maps.
- **`CMDC.approve/3` and `CMDC.reject/3` with `:auto_resume`** (RFC A3) — approve now
auto-resumes the turn by default (`auto_resume: true`); reject defaults to
`auto_resume: false`. Both emit `:agent_resumed` event when they actually restart a
turn, so UIs can follow without race conditions. Legacy `approve/2` / `reject/2`
still work (`auto_resume: true / false` defaults).
- **`normalize_session/1` + session-as-string everywhere** (RFC A4) — every public API
accepts `pid() | String.t()`; `subscribe/1` can target not-yet-started sessions
(common for UI pre-mount subscribe); `user_respond/3` broadcasts by session id
without SessionRegistry round-trip.
### Added — Protocol (RFC B5–B7)
- **`%CMDC.TokenUsage{}`** (RFC B5) — typed struct `{input, output, total, cache_read,
cache_write}`; all token-bearing events (`:after_response`, `:turn_complete`,
`:agent_finished`) now emit this struct. Legacy map format remains readable.
- **`CMDC.abort/2` options** (RFC B6) — `reason:` (defaults `:user_abort`, embedded in
`:agent_abort` event), `kill_tools:` (`:running` default / `:all` / `:none`),
`clear_queue:` (default `true`). Documented 4-state behavior matrix and the
`100ms within` emit guarantee for `:agent_abort`.
- **Plugin Hook × Action matrix** (RFC B7) — `docs/guides/plugin-matrix.md` with full
11×7 table plus 5 copy-paste Cookbook scenarios (block tool, rate-limit, audit
log, cost guard, steering-on-loop).
### Added — Runtime Control (RFC C8–C12)
- **`CMDC.switch_model/2`** (RFC C8) — change the LLM model mid-session; emits
`:model_switched` with `{from, to, reason, turn, ts}`. Also exposed as a Plugin
action `{:switch_model, new_model, state}` (used by the upgraded `ModelRouter`).
- **`CMDC.attach_tool/2` / `CMDC.detach_tool/2`** (RFC C9) — runtime toolset mutation.
Emits `:tool_attached` / `:tool_detached`. If the LLM later calls a detached tool,
the kernel emits `:tool_call_unknown` (no crash, no hang) and returns a tool_result
error so the next turn lets the LLM self-correct.
- **EventBus replay buffer + `subscribe(:since)`** (RFC C10) — every session keeps a
bounded ring of past events (default 500); subscribers can recover missed events on
reconnect via `CMDC.subscribe(session, since: ts | event_id)`.
- **`CMDC.status/1` extensions** (RFC C11) — now returns
`pending_tools`, `pending_approvals`, `pending_user_inputs`, `queue_sizes`
(pending prompts / steerings) so dashboards can reflect the true "what is the
agent blocked on right now".
- **`CMDC.monitor/1` + structured reason** (RFC C12) — `Process.monitor`-style API
that returns a structured reason map (`{:normal | :shutdown | :exception |
:max_turns_exceeded | :provider_timeout | {:plugin_aborted, name, why}}`) instead
of the raw OTP term. Use `CMDC.demonitor/2` to cancel.
### Added — Event Protocol (RFC D14)
- **Generic `:plugin_event` event** — unified envelope
`{:plugin_event, %{kind: atom, v: integer, session_id, occurred_at, ...}}` that all
built-in and third-party plugins use to publish business-level events to EventBus.
Subscribing to a single event gives the integrator access to every plugin's
structured output. First producer: `MemoryFlush` (`kind: :memory_flush`).
### Added — Phase 10 (original roadmap)
- **10A. Steering** — `CMDC.steer(session, instruction)` injects a mid-run "soft
interrupt" without aborting. Queued when busy (default `max=3`), applied at the
next safe point, emits `:steering_applied`. Plugins can gate via new
`:before_steering` hook.
- **10B. PromptMode** — new `CMDC.Options.prompt_mode` field with 4 values:
- `:full` (default) — full BasePrompt + identity + tools + Skills + Memory
- `:task` — compact base for focused subagents (saves ~50% tokens)
- `:minimal` — tool-name list only, no descriptions (saves ~90%)
- `:none` — completely delegated to user-provided `system_prompt`
`SubAgent` defaults to `:task` (SDK-level token savings); `Tool.Task` propagates
the mode to children; 8-layer SubAgent chain drops from ~7200 to ~2400 tokens.
- **10C. MemoryFlush plugin** — new `CMDC.Plugin.Builtin.MemoryFlush` subscribes
to the new `:before_compact` event, extracts key facts via configurable
`extract_fn` (heuristic default, LLM-pluggable), deduplicates with SHA256, and
appends to `working_dir/MEMORY.md`. Closes the loop with `MemoryLoader` for
true long-session memory across restarts. Emits both `:memory_flushed`
(internal) and `:plugin_event` (kind `:memory_flush`, per RFC D14).
- **10D. ModelRouter v2** — `Plugin.Builtin.ModelRouter` now uses
`{:switch_model, ...}` action (no more `[系统]` message pollution) and adds five
new business-friendly condition families on top of the original three runtime
conditions:
- `:token_budget_lt` — remaining budget from `user_data[:token_budget]`
- `:task_complexity` / `:task_complexity_in` — `:simple` / `:normal` / `:complex`
- `:time_of_day_in` — list of UTC-hour ranges (with injectable `now_fn`)
- `:user_tier` / `:user_tier_in` — `:free` / `:pro` / `:enterprise` / custom
- `:user_data, key, value` and `:user_data, key, op, value` (`:eq/:gt/:lt/:gte/:lte`)
Robustness: all conditions run inside a `rescue` wrapper; `user_data = nil` and
unknown condition tuples safely degrade to `false`.
### Changed
- `ModelRouter` no longer injects `[系统] 已切换到模型 X` assistant messages; uses
`{:switch_model, ...}` Plugin action + `:model_switched` event instead. Conversation
history remains clean.
- `HumanApproval` / HITL flow now emits `:agent_resumed` when `approve(auto_resume: true)`
actually restarts the turn (was previously silent).
- `CMDC.Agent` emits `:before_compact` event (new plugin hook) before Compactor runs,
giving plugins a chance to persist facts before summarization.
### Fixed
- `CMDC.subscribe("session-id")` on a not-yet-started session no longer raises
`ArgumentError`; it now succeeds and delivers events as soon as the session starts
(RFC A4).
- `Plugin.Pipeline` `{:emit, ...}` action can now emit multiple events in a single
return (`{:emit, [{name1, payload1}, ...], state}`) and accepts a 3-tuple shortcut
`{:emit, name, payload, state}`.
### Breaking
- `Plugin.Builtin.ModelRouter` behavior change: existing users who relied on the
`[系统] 已切换到模型 X` message being injected into context must migrate to subscribe
`:model_switched` events or consume the new `:switch_model` action's side effects.
Most users will experience this as a cleaner UX.
### Documentation
- `docs/guides/plugin-matrix.md` — complete 11 hooks × 7 actions matrix + 5 Cookbook
scenarios (RFC B7).
- `docs/dev/rfc/2026-04-hive-feedback-review.md` — official response to the Hive team,
documenting every accepted RFC's design decisions and migration paths.
- `llm.txt` / `llms-full.txt` — updated with PromptMode, MemoryFlush, ModelRouter v2,
`:plugin_event`, `switch_model/2`, `attach_tool/2`, `monitor/1`, `:since` replay,
and `status/1` extensions.
- `docs/dev/KNOWLEDGE.md` — added sections 5.24 / 5.25 / 5.26 documenting pitfalls
found during 10B / 10C / 10D implementation (SubAgent token explosion, memory
flush robustness, ModelRouter current_model state chain).
[0.2.0]: https://github.com/tuplehq/cmdc/releases/tag/v0.2.0
## [0.1.1] - 2026-04-08
### Fixed
- 修复 ex_doc 文档 10 处引用 warning(隐藏函数引用、不存在函数引用、LICENSE 文件缺失)
- LICENSE 文件加入 HexDocs extras
- README 许可证描述和联系方式更正
## [0.1.0] - 2026-04-08
Initial release of CMDC — Elixir Agent Kernel.
### Added
#### Core Infrastructure (L0)
- `CMDC.Options` — typed struct with NimbleOptions schema for AI-friendly agent configuration; all fields with precise `doc:` annotations
- `CMDC.Config` — application-level configuration struct with provider routing (`resolve_provider/2`)
- `CMDC.Context` — runtime execution context passed to Tools and Plugins
- `CMDC.Message` — typed message struct supporting system/user/assistant/tool_result roles; `@derive Jason.Encoder`
- `CMDC.Event` — 22 structured event types covering full agent lifecycle
- `CMDC.EventBus` — Registry-based PubSub; `subscribe/1`, `broadcast/2`, `subscribe_all/0`
- `CMDC.SubAgent` — declarative sub-agent specification struct with `nil`-means-inherit semantics
#### Core Abstractions (L1)
- `CMDC.Plugin` — behaviour with 11 event hooks and 7 action types (continue/intervene/abort/skip/block_tool/replace_tool_args/emit)
- `CMDC.Plugin.Pipeline` — priority-ordered plugin execution with short-circuit support
- `CMDC.Plugin.Registry` — plugin registration with deduplication and priority sorting
- `CMDC.Tool` — behaviour with `name/0`, `description/0`, `parameters/0`, `execute/2`; result type `{:ok, text} | {:error, text} | {:effect, term}`
- `CMDC.Sandbox` — behaviour abstracting file/command execution (8 callbacks); `CMDC.Sandbox.Local` as default OS implementation
- `CMDC.Skill` — SKILL.md discovery, loading, and system prompt injection
- `CMDC.Blueprint` — behaviour for declarative reusable agent configurations; struct pipeline helpers (`add_tools/2`, `add_plugins/2`, etc.)
- `CMDC.Provider` — thin `req_llm` wrapper; `stream/4`, `convert_messages/2`, `convert_tools/1`
- `CMDC.Provider.StreamBridge` — converts `ReqLLM.StreamResponse` into gen_statem messages
#### Agent Kernel (L2)
- `CMDC.Agent` — `gen_statem` state machine with 4-state loop: `idle → running → streaming → executing_tools`
- `CMDC.Agent.State` — runtime state with token/cost tracking, loop detection hashes, sandbox/todos/memory fields
- `CMDC.Agent.Stream` — streaming delta accumulation with XML tag extraction (`<status>`, `<title>`)
- `CMDC.Agent.ToolRunner` — parallel tool execution with built-in loop detection (exact duplicate + pattern + consecutive failure) + tool retry with `on_tool_error` Plugin hook; configurable via `:tool_max_retries` (default 0) and `:tool_retry_delay_ms` (default 500ms)
- `CMDC.Agent.Emitter` — EventBus event broadcasting with ETS ring buffer for recent event retrieval
- `CMDC.Agent.BasePrompt` — default base prompt aligned with DeepAgents `BASE_AGENT_PROMPT`
- `CMDC.Agent.SystemPrompt` — system prompt assembly: BasePrompt + user prompt + blueprint identity + skills + memory
- `CMDC.Agent.Compactor` — automatic context compaction; token-based trigger with character estimation fallback; offload to file
- `CMDC.Agent.Compactor.ArgTruncator` — pre-truncation of large tool arguments (write_file/edit_file/execute)
#### Built-in Plugins (6)
- `CMDC.Plugin.Builtin.SecurityGuard` (priority 10) — path and command blacklist enforcement
- `CMDC.Plugin.Builtin.HumanApproval` (priority 15) — HITL approval flow via `approval_required` events
- `CMDC.Plugin.Builtin.EventLogger` (priority 50) — JSON Lines session audit log
- `CMDC.Plugin.Builtin.MemoryLoader` (priority 100) — AGENTS.md loading and `<agent_memory>` injection; auto-reload on write_file/edit_file
- `CMDC.Plugin.Builtin.PatchToolCalls` (priority 120) — synthetic tool result injection for dangling tool_calls
- `CMDC.Plugin.Builtin.PromptCache` (priority 130) — Anthropic prompt caching headers; auto-skip for other providers
#### Built-in Tools (11)
- `CMDC.Tool.ReadFile` — file reading with offset/limit pagination; Sandbox proxy
- `CMDC.Tool.WriteFile` — file writing with parent directory creation; Sandbox proxy
- `CMDC.Tool.EditFile` — exact string replacement (str_replace); Sandbox proxy
- `CMDC.Tool.Shell` — shell command execution; large output auto-saved to temp file; Sandbox proxy
- `CMDC.Tool.Grep` — regex file search with line numbers and glob filtering; Sandbox proxy
- `CMDC.Tool.ListDir` — directory listing with type and size; Sandbox proxy
- `CMDC.Tool.Glob` — glob pattern file matching; Sandbox proxy
- `CMDC.Tool.Task` — OTP-process-level sub-agent spawning under SubAgent.Supervisor; broadcasts `subagent_start`/`subagent_end`
- `CMDC.Tool.WriteTodos` — Context.todos update with `todo_change` event broadcast
- `CMDC.Tool.AskUser` — pause execution, wait for `user_responded` event
- `CMDC.Tool.CompactConversation` — manual context compaction trigger
#### Integration Layer (L3)
- `CMDC.SessionServer` — per-session Supervisor tree (Agent + SubAgent.Supervisor)
- `CMDC.SubAgent.Supervisor` — DynamicSupervisor for isolated child agent processes (`:temporary` restart)
- `CMDC.MCP.Bridge` — dynamic CMDC.Tool module generation from MCP server tool definitions
- `CMDC.MCP.Client` — `anubis_mcp`-based MCP client with Registry naming per server
- `CMDC.MCP.Supervisor` — DynamicSupervisor for MCP client processes
- `CMDC.MCP.Config` — mcp.json discovery with multiple path fallbacks
- `CMDC.Memory.ETS` — ETS-backed key-value memory store with keyword search
- `CMDC.Gateway` / `CMDC.Gateway.Local` — outbound event reporting contract and local EventBus implementation
#### Public API (L4)
- `CMDC` — facade with `create_agent/1`, `prompt/2`, `collect_reply/2`, `stop/2`, `abort/1`, `subscribe/1`, `unsubscribe/1`, `approve/2`, `reject/2`, `status/1`, `agent_pid/1`, `session_id/1`
- `CMDC.Blueprint.Base` — built-in base blueprint (SecurityGuard + EventLogger + PatchToolCalls)
#### Documentation
- `README.md` — Quick Start, feature comparison table (CMDC vs DeepAgents), architecture diagram, built-in tool/plugin tables
- `llm.txt` — AI quick reference (~230 lines): all public API signatures, parameter types, common patterns
- `llms-full.txt` — AI complete reference (~999 lines): event protocol, Tool/Plugin development guide, 14 known pitfalls
[0.1.0]: https://github.com/tuplehq/cmdc/releases/tag/v0.1.0