CMDC.Checkpoint.Snapshot (cmdc v0.5.2)

Copy Markdown View Source

会话快照标准 payload。

统一 CMDC.Checkpoint.save/3 的输出与 load/2 的输入。 含 @schema_version 便于未来 schema 演进时向前兼容。

不可序列化字段策略

Agent.State 中以下字段在 save/2 时会被自动剥离, 并在 resume_session!/2 时由 plugin :session_start hook 重建:

  • pid() 字段(如 :agent_pid / :owner_pid
  • Stream / Task 引用
  • :reference 字段(如 :monitor_ref

这一策略避免序列化死引用、同时保证 plugin 状态可以靠 :session_start 重新初始化。Snapshot 会保留这些字段名加 :_stripped 标记 以便恢复时知道哪些 plugin 需要重置。

Provider Registry 协议兼容(v0.5.1+)

state.model 字段可能含 "registry:profile_name:provider:model_id" 前缀 (CMDC.Provider.Registry 命名 Provider Profile 协议)。

  • Snapshot 序列化时原样保留 "registry:..." 字符串(不解析)
  • CMDC.resume_session!/2 会重新触发 CMDC.Provider.Registry.lookup/1
  • 若 profile 已被 unregister 或迁移到其它节点,resume 返 {:error, {:registry_profile_missing, name}} —— 集成方可 re-register 后重试

典型用例:Studio 多租户重启后,集成方 init 时灌入持久层所有 profile, 即可平滑 resume 历史会话;若集成方误删 profile,resume 失败给出明确恢复路径。

Examples

iex> snap = Snapshot.new(session_id: "sess-1", state: %{messages: []})
iex> snap.schema_version
1

Summary

Types

可被序列化为 snapshot 的负载(通常是 Agent.State 或 map)。

t()

Functions

构建新的 Snapshot,自动生成 checkpoint_id + saved_at, 并剥离不可序列化字段。

对 snapshot 的 :state 字段应用一个 redact 函数,返回新的 Snapshot。

返回 schema 版本号常量。

Types

serializable()

@type serializable() :: map() | struct()

可被序列化为 snapshot 的负载(通常是 Agent.State 或 map)。

t()

@type t() :: %CMDC.Checkpoint.Snapshot{
  checkpoint_id: String.t(),
  label: String.t() | nil,
  metadata: map(),
  saved_at: DateTime.t(),
  schema_version: pos_integer(),
  session_id: String.t(),
  state: serializable(),
  stripped_fields: [atom()]
}

Functions

new(opts)

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

构建新的 Snapshot,自动生成 checkpoint_id + saved_at, 并剥离不可序列化字段。

选项

  • :session_id — 必填
  • :state — 必填(Agent.State 或任意 map)
  • :label — 可选标签
  • :metadata — 用户附加 map(默认 %{}

redact(snap, redact_fn)

@spec redact(t(), (serializable() -> serializable())) :: t()

对 snapshot 的 :state 字段应用一个 redact 函数,返回新的 Snapshot。

常见用途:backend 在 save/3 前去除敏感字段(API key / token / PII), 让 CMDC 不强制 encryption_at_rest,但给集成方留官方 hook 接 Cloak / KMS。

行为

  • redact_fn 接受当前 snapshot.state(map 或 struct)返回处理后的 map / struct
  • 其他字段(checkpoint_id / session_id / saved_at / stripped_fields / metadata / label)保持不变
  • 不变更 schema_version

示例

# 去掉所有以 :api_ / :token 开头的 key
Snapshot.redact(snap, fn state ->
  Enum.reject(state, fn {k, _v} ->
    ks = to_string(k)
    String.starts_with?(ks, "api_") or String.contains?(ks, "token")
  end)
  |> Map.new()
end)

# 接 Cloak 加密敏感字段
Snapshot.redact(snap, &MyApp.Vault.encrypt_sensitive/1)

schema_version()

@spec schema_version() :: pos_integer()

返回 schema 版本号常量。