# `CMDC.Backend.Composite`
[🔗](https://github.com/tuplehq/cmdc/blob/v0.4.0/lib/cmdc/backend/composite.ex#L1)

路由后端 — 按路径前缀转发到不同子 backend（对标 deepagents `CompositeBackend`）。

让一个会话**同时挂载多种存储**，例如：

- `/workspace/` → `Sandbox.Docker`（隔离代码执行）
- `/memories/` → `Backend.Postgres`（持久化记忆，跨 session）
- `/conversation_history/` → `Backend.State`（短期 ETS）
- 默认（其他路径）→ `Backend.Filesystem`（本地工作目录）

这是 ACP（Zed / Cursor）部署模式的**事实标准**，deepagents demo 90% 用 Composite。

## 路由规则

- 按 `routes` 中 prefix 从**最长到最短**匹配
- 命中 prefix → strip 该前缀后转发到子 backend（virtual_mode 友好）
- 未命中 → fallback 到 `:default` backend
- `:default` 必填

## 示例

    backend =
      CMDC.Backend.Composite.new(
        default: CMDC.Backend.Filesystem.new(root_dir: "/tmp/ws"),
        routes: %{
          "/memories/" => CMDC.Backend.State.new(:agent_memories),
          "/conversation_history/" => CMDC.Backend.State.new(:histories)
        }
      )

    # 走 default (Filesystem) — 实际路径 /tmp/ws/notes/todo.md
    CMDC.Backend.write(backend, "/notes/todo.md", "buy milk")

    # 走 State 表 :agent_memories — 子 backend 看到的路径就是 /user-id.md
    CMDC.Backend.write(backend, "/memories/user-id.md", "John")

# `t`

```elixir
@type t() :: %CMDC.Backend.Composite{
  default: CMDC.Backend.t(),
  routes: %{required(String.t()) =&gt; CMDC.Backend.t()},
  sorted_prefixes: [String.t()]
}
```

# `new`

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

构建 Composite backend。

## 选项
- `:default` — 必填，默认 backend（未命中 routes 走它）
- `:routes` — `%{prefix => backend}` map，prefix 必须以 `/` 开头 + 结尾

# `route`

```elixir
@spec route(t(), String.t()) :: {CMDC.Backend.t(), String.t()}
```

根据 path 找到对应 backend 与 strip 后的子路径。

匹配规则：按 `sorted_prefixes`（最长在前）逐个尝试，命中 prefix 则
返回 `{routes[prefix], "/" <> trailing}`。

## Examples

    iex> c = CMDC.Backend.Composite.new(
    ...>   default: CMDC.Backend.State.new(:default_t),
    ...>   routes: %{"/mem/" => CMDC.Backend.State.new(:mem_t)}
    ...> )
    iex> {backend, sub} = CMDC.Backend.Composite.route(c, "/mem/key.txt")
    iex> {backend.table, sub}
    {:mem_t, "/key.txt"}

---

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