# CMDC

**Elixir Agent Kernel** — OTP `gen_statem` 驱动的 AI Agent 开发库，对标 [DeepAgents](https://github.com/deepagents/deepagents)，在并发隔离、类型安全、Plugin 精度上全面超越。

[![Hex.pm](https://img.shields.io/hexpm/v/cmdc.svg)](https://hex.pm/packages/cmdc)
[![Docs](https://img.shields.io/badge/docs-hexdocs-blue.svg)](https://hexdocs.pm/cmdc)
[![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE)

---

## 功能亮点

| 维度 | DeepAgents (Python) | CMDC (Elixir) |
|------|---------------------|---------------|
| **并发模型** | asyncio + Thread | OTP gen_statem + Supervisor — 原生容错、热更新、进程隔离 |
| **SubAgent** | 同步阻塞 | OTP 进程级隔离 + 真并发，子 Agent crash 不传染父 Agent |
| **Plugin 系统** | Middleware 线性链 | Pipeline：11 个 hook × 7 种 action，更精细的拦截和控制力 |
| **安全** | 无内置 | SecurityGuard Plugin — 内置路径/命令安全防护 |
| **成本控制** | 无 | Agent.State 自动累加 token / cost_usd |
| **类型安全** | Python type hints | TypedStruct + NimbleOptions + `@spec` 五层 AI-Friendly 防护 |
| **声明式定义** | 无等价物 | Blueprint 系统 — 可复用的 Agent 蓝图 |

---

## 安装

将 `cmdc` 添加到 `mix.exs` 依赖列表：

```elixir
def deps do
  [
    {:cmdc, "~> 0.1"}
  ]
end
```

然后获取依赖：

```bash
mix deps.get
```

---

## 快速开始

### 最简 Agent

```elixir
# 1. 在应用监控树中启动 Session
{:ok, pid} = CMDC.create_agent(
  model: "anthropic/claude-3-5-sonnet-20241022",
  api_key: System.get_env("ANTHROPIC_API_KEY")
)

# 2. 发送提示词（异步流式）
:ok = CMDC.prompt(pid, "你好，请介绍一下你自己")

# 3. 收集完整回复
{:ok, reply} = CMDC.collect_reply(pid)
IO.puts(reply)

# 4. 停止
CMDC.stop(pid)
```

### 带工具的 Agent

```elixir
{:ok, pid} = CMDC.create_agent(
  model: "anthropic/claude-3-5-sonnet-20241022",
  api_key: System.get_env("ANTHROPIC_API_KEY"),
  tools: [CMDC.Tool.ReadFile, CMDC.Tool.WriteFile, CMDC.Tool.Shell],
  working_dir: "/tmp/workspace"
)

CMDC.prompt(pid, "读取 README.md 并写一份中文摘要到 summary.md")
{:ok, reply} = CMDC.collect_reply(pid)
```

### 订阅事件流

```elixir
CMDC.subscribe(pid)

CMDC.prompt(pid, "写一段 Elixir 代码示例")

# 实时接收流式事件
receive do
  {:cmdc_event, %CMDC.Event{type: :stream_delta, data: %{delta: text}}} ->
    IO.write(text)
  {:cmdc_event, %CMDC.Event{type: :stream_stop}} ->
    IO.puts("\n[完成]")
end
```

### 使用 Blueprint 声明式定义

```elixir
defmodule MyApp.CodingAgent do
  @behaviour CMDC.Blueprint

  @impl true
  def build(_opts) do
    %CMDC.Options{
      system_prompt: "你是一名资深 Elixir 工程师。",
      tools: [CMDC.Tool.ReadFile, CMDC.Tool.WriteFile, CMDC.Tool.Shell],
      plugins: [CMDC.Plugin.Builtin.SecurityGuard],
      skills_dirs: ["priv/skills"]
    }
  end
end

{:ok, pid} = CMDC.create_agent(MyApp.CodingAgent,
  model: "anthropic/claude-3-5-sonnet-20241022",
  api_key: System.get_env("ANTHROPIC_API_KEY")
)
```

### 自定义 Plugin

```elixir
defmodule MyApp.AuditPlugin do
  @behaviour CMDC.Plugin

  @impl true
  def init(_opts), do: {:ok, %{count: 0}}

  @impl true
  def priority, do: 100

  @impl true
  def handle_event({:before_tool, name, args}, state, _ctx) do
    IO.puts("[审计] 调用工具: #{name}, 参数: #{inspect(args)}")
    {:continue, %{state | count: state.count + 1}}
  end
  def handle_event(_event, state, _ctx), do: {:continue, state}
end
```

---

## 架构

```
CMDC（公共 API 入口）
├── SessionServer（Supervisor Tree）
│   ├── Agent（gen_statem 状态机）
│   │   ├── State          — 运行时状态 + token/cost 追踪
│   │   ├── Stream         — 流式响应 delta 组装
│   │   ├── ToolRunner     — 工具执行 + 循环检测
│   │   ├── Emitter        — EventBus 事件广播
│   │   ├── SystemPrompt   — 提示词组装（BasePrompt + Skills + Memory）
│   │   └── Compactor      — 上下文压缩 + ArgTruncator
│   └── SubAgent.Supervisor（DynamicSupervisor）
│       └── 子 Agent 进程（并行、隔离）
│
├── Plugin Pipeline（11 hooks × 7 actions）
├── Tool（11 个内置工具）
├── Provider（req_llm 封装，支持多 LLM 提供商）
├── MCP（Bridge + Client + Supervisor）
├── Sandbox（可插拔文件系统抽象）
├── Blueprint（声明式 Agent 蓝图）
├── Skills（渐进式 SKILL.md 发现）
└── Memory.ETS（ETS 持久记忆）
```

### 模块依赖层级

```
L0  基础类型    Options / Config / Context / Message / Event / EventBus / SubAgent
L1  核心抽象    Blueprint / Plugin / Tool / Sandbox / Skill / Provider
L2  Agent      Agent (gen_statem) + State + Stream + ToolRunner + Compactor
L3  集成       SessionServer + MCP.* + Memory.ETS + SubAgent.Supervisor
L4  Facade     CMDC（公共 API 入口）
```

---

## 内置功能

### Plugin（6 个）

| Plugin | 说明 |
|--------|------|
| `SecurityGuard` | 拦截危险路径和系统命令，防止越权操作 |
| `EventLogger` | 记录所有 Agent 事件，便于调试和审计 |
| `HumanApproval` | HITL 审批流，工具调用前等待人工确认 |
| `MemoryLoader` | 加载 AGENTS.md 持久记忆并注入 System Prompt |
| `PatchToolCalls` | 自动修复悬空 tool_call（无对应 ToolMessage 的响应） |
| `PromptCache` | Anthropic 模型 prompt caching 支持，降低成本 |

### Tool（11 个）

| Tool | 说明 |
|------|------|
| `ReadFile` | 读取文件，支持 offset/limit 分页 |
| `WriteFile` | 写入文件 |
| `EditFile` | 精确字符串替换（str_replace 模式） |
| `Shell` | 执行 shell 命令，大输出自动存文件 |
| `Grep` | 正则搜索，支持 glob 文件过滤 |
| `ListDir` | 列出目录内容 |
| `Glob` | 模式匹配文件列表 |
| `Task` | 启动 SubAgent 子进程（OTP 进程级并发） |
| `WriteTodos` | 更新 Agent 的 Todo 列表 |
| `AskUser` | 暂停执行，等待用户输入 |
| `CompactConversation` | 手动触发上下文压缩 |

### 事件系统（22 种事件）

所有事件通过 `CMDC.EventBus` 广播，消费者通过 `CMDC.subscribe/1` 订阅：

```
session_start / session_end
stream_start / stream_delta / stream_stop
tool_start / tool_end / tool_batch_end
approval_required / approval_responded
todo_change
cost_update
compact_start / compact_end
subagent_start / subagent_end
memory_loaded
ask_user / user_responded
context_overflow
error
```

---

## MCP（Model Context Protocol）支持

```elixir
{:ok, pid} = CMDC.create_agent(
  model: "anthropic/claude-3-5-sonnet-20241022",
  api_key: System.get_env("ANTHROPIC_API_KEY"),
  mcp_servers: [
    %CMDC.MCP.Config{
      name: "filesystem",
      command: "npx",
      args: ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"]
    }
  ]
)
```

---

## AI-Friendly 类型系统

CMDC 的核心差异化之一是「AI-Friendly 类型系统」，让 AI 生成的调用代码更准确：

```elixir
# 精确的 NimbleOptions schema，每个字段含类型 + 默认值 + 中文说明
%CMDC.Options{
  model: "anthropic/claude-3-5-sonnet-20241022",  # 必填
  system_prompt: "...",                             # 可选，nil 表示使用 BasePrompt
  tools: [CMDC.Tool.ReadFile],                      # 可选，Tool 模块列表
  plugins: [CMDC.Plugin.Builtin.SecurityGuard],     # 可选，Plugin 模块列表
  max_tokens: 8192,                                 # 可选，默认 8192
  max_turns: 10,                                    # 可选，默认 10，nil 表示无限制
  working_dir: "/tmp/workspace",                    # 可选，工具执行根目录
  skills_dirs: ["priv/skills"],                     # 可选，Skills SKILL.md 搜索目录
  memory_dir: "~/.cmdc/memory"                      # 可选，AGENTS.md 持久记忆目录
}
```

---

## 开发

```bash
# 测试
mix test

# 格式化
mix format

# 静态分析
mix credo --strict

# 类型检查
mix dialyzer

# 一键质量检查
mix quality.check
```

---

## 许可证

本项目采用 **Apache 2.0 + Commons Clause** 许可证。

- **允许**：学习、修改、自由使用（包括内部商业用途）、基于 CMDC 构建自己的应用/产品
- **不允许**：将 CMDC 本身作为托管服务、云服务或 SaaS 对外提供，或出售以 CMDC 功能为核心价值的产品

详见 [LICENSE](LICENSE)。商业授权合作请联系：https://github.com/tuplehq/cmdc

---

## 文档

- [HexDocs API 参考](https://hexdocs.pm/cmdc)
- `llm.txt` — AI 快速参考（~200 行，API 签名 + 类型 + 示例）
- `llms-full.txt` — AI 完整参考（~800 行，含事件协议、Plugin/Tool 开发、已知陷阱）
