CMDC.Backend.Composite (cmdc v0.5.3)

Copy Markdown View Source

路由后端 — 按路径前缀转发到不同子 backend。

让一个会话同时挂载多种存储,例如:

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

这是 ACP(Zed / Cursor)部署模式的事实标准

路由规则

  • 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")

Summary

Functions

构建 Composite backend。

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

Types

t()

@type t() :: %CMDC.Backend.Composite{
  default: CMDC.Backend.t(),
  routes: %{required(String.t()) => CMDC.Backend.t()},
  sorted_prefixes: [String.t()]
}

Functions

new(opts)

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

构建 Composite backend。

选项

  • :default — 必填,默认 backend(未命中 routes 走它)
  • :routes%{prefix => backend} map,prefix 必须以 / 开头 + 结尾

route(c, path)

@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"}