# `CMDC.Options`
[🔗](https://github.com/tupleyun/cmdc/blob/v0.5.3/lib/cmdc/options.ex#L1)

创建 CMDC Agent 的类型化选项 struct。

替代裸 keyword list，通过 NimbleOptions 在运行时校验所有字段，
提供清晰的错误信息和文档，实现 AI-Friendly 类型系统的第一层防护。

## 快速开始

    opts = CMDC.Options.new!(
      model: "anthropic:claude-sonnet-4-5",
      tools: [CMDC.Tool.ReadFile, CMDC.Tool.Shell],
      system_prompt: "你是一个专业的代码助手。",
      max_turns: 50
    )

## 字段说明

- `:model` — 必填，模型标识符，格式 `"provider:model_id"`，如 `"anthropic:claude-sonnet-4-5"`
- `:tools` — Tool behaviour 模块列表，空则不加载任何工具
- `:system_prompt` — 自定义系统提示词，拼接在 BasePrompt 之前；nil 则只用 BasePrompt
- `:plugins` — Plugin 列表，支持 `Module` 或 `{Module, keyword()}` 两种形式
- `:subagents` — SubAgent 声明式规格列表（`CMDC.SubAgent.t()` 的列表）
- `:skills_dirs` — Skills 目录列表，Agent 自动发现 SKILL.md 文件
- `:memory` — Memory 文件路径列表，如 `["AGENTS.md", "~/.cmdc/AGENTS.md"]`
- `:sandbox` — Sandbox behaviour 实现模块，nil 则直接 OS 执行
- `:response_format` — 结构化输出 JSON Schema，nil 则自由文本
- `:provider_opts` — 传递给 req_llm 的选项，如 `[api_key: "sk-..."]`
- `:max_turns` — 最大对话轮数，默认 100
- `:max_tokens` — 模型最大输出 token，nil 则由 Provider 决定
- `:working_dir` — 工作目录，工具的文件操作相对此路径，默认 `"."`
- `:max_steering_queue` — Steering queue 最大长度，默认 3（详见 `guides/cookbook.md` 中段干预配方）
- `:interrupt_immune_tools` — Steering 触发时不会被强杀的工具白名单
- `:user_data` — 业务上下文透传 map，原样写入 `ctx.user_data`，SubAgent 自动继承
- `:messages` — 历史消息列表（`[CMDC.Message.t()]`），创建 Agent 时直接写入 `state.messages`，
  用于 idle 休眠唤醒 / 跨进程恢复，跳过把历史灌成 prompt 让 LLM 重读的开销
- `:event_buffer_size` — EventBus per-session ring buffer 大小，默认 `0`（关闭）。
  设置 > 0 后该 session 的事件会按 FIFO 缓存，订阅者可用 `subscribe(sid, since: idx)`
  实现断线重连补帧。典型值 `50 ~ 200`。
- `:prompt_mode` — 系统提示词模式，`:full | :task | :minimal | :none`，默认 `:full`。
  控制 `Agent.SystemPrompt.build/1` 注入的段落密度，用于 SubAgent / 长会话降本。
- `:hibernate_after_ms` — 进程空闲超过 N 毫秒后自动 `:erlang.hibernate/3`，
  单进程内存从约 8 KB 降到 1.5 KB（节省约 80%）。`nil`（默认）= 不主动 hibernate,
  行为与 v0.4 一致。典型值 `60_000 ~ 300_000`(长会话 / 多租户场景)。

# `plugin_spec`

```elixir
@type plugin_spec() :: module() | {module(), keyword()}
```

# `prompt_mode`

```elixir
@type prompt_mode() :: :full | :task | :minimal | :none
```

# `t`

```elixir
@type t() :: %CMDC.Options{
  event_buffer_size: non_neg_integer(),
  hibernate_after_ms: pos_integer() | nil,
  interrupt_immune_tools: [String.t()],
  max_steering_queue: pos_integer(),
  max_tokens: pos_integer() | nil,
  max_turns: pos_integer(),
  memory: [String.t()],
  messages: [CMDC.Message.t()],
  model: String.t(),
  plugins: [plugin_spec()],
  prompt_mode: prompt_mode(),
  provider_opts: keyword(),
  response_format: map() | nil,
  sandbox: module() | nil,
  skill_selector: module() | nil,
  skills_dirs: [String.t()],
  subagents: [map()],
  system_prompt: String.t() | nil,
  tools: [module()],
  user_data: map(),
  working_dir: String.t()
}
```

# `merge`

```elixir
@spec merge(
  t(),
  keyword()
) :: t()
```

从已有 Options struct 合并覆盖字段，返回新 struct。

# `new`

```elixir
@spec new(keyword()) :: {:ok, t()} | {:error, NimbleOptions.ValidationError.t()}
```

从 keyword list 构建 Options struct，返回 `{:ok, t()}` 或 `{:error, NimbleOptions.ValidationError.t()}`。

# `new!`

```elixir
@spec new!(keyword()) :: t()
```

从 keyword list 构建 Options struct，校验失败时抛出异常。

## 示例

    iex> CMDC.Options.new!(model: "anthropic:claude-sonnet-4-5")
    %CMDC.Options{model: "anthropic:claude-sonnet-4-5", tools: [], ...}

    iex> CMDC.Options.new!([])
    ** (NimbleOptions.ValidationError) required option :model not found

# `schema`

```elixir
@spec schema() :: NimbleOptions.t()
```

返回 NimbleOptions schema（用于文档生成和运行时检查）。

---

*Consult [api-reference.md](api-reference.md) for complete listing*
