[0.1.2] - 2026-05-25
Patch release — 对齐 cmdc 0.6.0
CMDC.Memorybehaviour 升级, 加入tags :: [String.t()]一等公民字段 +tags_any/tags_all高效 检索操作符 +schema_version/0callback。零 breaking,无需停机。
Added
tags一等公民字段 —cmdc_episodic_memories表新增tags :: text[]列 (NOT NULL default{}),与 cmdc 主库 v0.6+CMDC.Memory.entry()标准对齐tags_any/tags_all检索操作符 —search/3的filters接受:{:tags_any, ["a", "b"]}— entry.tags 与列表有任一交集(走 PG&&){:tags_all, ["a", "b"]}— entry.tags 全部包含列表元素(走 PG@>)- 空列表
{:tags_any, []}/{:tags_all, []}视为跳过过滤
- GIN 索引 —
cmdc_episodic_memories(tags)上的 GIN 索引让 tag 检索高效 c:schema_version/0callback — 实现 cmdc 0.6+ Memory behaviour 可选 callback, 返回1(tags字段 default{},老数据零 ETL,不算 schema breaking)store/3自动写入 tags —data[:tags]/data["tags"]自动落到 tags 列; 支持String.t() | [String.t()] | [atom()]多种入参形态,normalize 为[string]row_to_entry同步带回 tags — 检索结果含:tags字段(老 entry 自动为[])
Migration(0.1.1 → 0.1.2)
无破坏性变化,直接升 hex 版本号即可。运行新增 migration:
$ mix ecto.migrate
migration 文件 priv/repo/migrations/20260525_add_tags_to_cmdc_episodic_memories.exs
自动:
- 在
cmdc_episodic_memories加tags text[] NOT NULL DEFAULT '{}'列 - 创建 GIN 索引
cmdc_episodic_memories_tags_index
老数据全部自动获得 tags = '{}',行为与"未传 tags 过滤"一致。
不需要业务代码改动,新代码可逐步引入 tags 检索:
# 写入时按需要带 tags
backend.store(nil, "ep-1",
content: "...", user_id: "u-1", tags: ["domain:finance", "topic:tax"])
# 检索时按 tags 过滤
backend.search(nil, "tax",
filters: [user_id: "u-1", {:tags_any, ["topic:tax"]}])Compatibility
- 老代码零改动 —
store/3不传:tags时落[];search/3不传tags_*filter 时返回行为不变 row_to_entry一定带:tags字段(空 entry 也是[])。如下游业务代码用Map.fetch!(entry, :tags)会触发(老 entry migration 后也有[]);若有 下游代码key in Map.keys(entry)类逻辑会感知新键
[0.1.1] - 2026-05-25
Patch release — 多租户隔离安全修复 + 集成方反馈采纳。 行为变化提示:默认行为从"未传 user_id 时返全表"修复为"返空列表"。
Fixed — 多租户数据隔离(安全)
EpisodicMemoryBackend.search/3/similarity_search/3— 未传filters[:user_id]时的行为修复:- v0.1.0 缺陷:代码
maybe_filter_user(query, nil), do: query不过滤, 返回全表所有租户的 episodic 记录(注释声称"避免误泄"但实际未做) - v0.1.1 修复:新增
:on_missing_tenantopt 控制行为:return_empty(默认)— 返回{:ok, []}强制空结果:return_error— 返回{:error, :missing_tenant_filter}严格模式
- v0.1.0 缺陷:代码
Added
:on_missing_tenantopt 在search/3/similarity_search/3的 opts 中接受
Migration(0.1.0 → 0.1.1)
强烈建议多租户集成方采取以下步骤:
- 代码 review:确保所有调用都显式传
filters[:user_id] - 升级到 0.1.1 后短期可保持默认
:return_empty行为(返空兼容,不报错) - 验证业务流程后,逐步迁移到
opts[:on_missing_tenant] = :return_error, 让漏传 user_id 的代码路径在测试期就暴露
与 cmdc 主库的关系:cmdc 0.5.4 同步在 Plugin.Builtin.EpisodicMemory
新增 :require_user_id: true opt 形成"Plugin 层 + Backend 层"双重防护;
配合使用最佳实践:
{EpisodicMemory, memory_module: CMDCMemoryPg.EpisodicMemoryBackend,
memory_store: nil, require_user_id: true} # Plugin 层
# backend 调用时透传 on_missing_tenant: :return_error # Backend 层Compatibility
- 默认行为变化:返"全表"→ 返"空列表";单租户场景(只有 1 个 user_id)无影响
- 多租户场景:这是修复,先前行为是安全 bug,升级后应严格 review 代码
[0.1.0] - 2026-05-18
首发版本 — 与 cmdc 主库 0.5.0 协同发布。
Added
CMDCMemoryPg.Repo— Ecto Repo for cmdc_memory_pgCMDCMemoryPg.CheckpointBackend— 实现CMDC.Checkpoint.Backend4 callback- snapshot 序列化走
:erlang.term_to_binary(snap, [:compressed])写入 bytea - 复用 cmdc 主库
CheckpointBackend.ETS同套测试 suite
- snapshot 序列化走
CMDCMemoryPg.EpisodicMemoryBackend— 实现CMDC.Memory5 callback- 与 cmdc 主库
Plugin.Builtin.EpisodicMemory直接对接 - 按
user_idnamespace 隔离多租户 - v0.1
similarity_search/3降级为 ILIKE 文本匹配(pgvector 留 v0.2)
- 与 cmdc 主库
- Ecto migration 2 张表:
cmdc_checkpoints+cmdc_episodic_memories docker-compose.yml— Postgres 16 alpine 测试用- 完整 README + Cloak encryption 集成示例
v0.1 范围说明(明确不含)
- ❌ pgvector 真语义检索(v0.2)
- ❌ 3-tier Memory(Working / Semantic / Procedural)— 留 v0.2
- ❌ Composite 路由 backend(cmdc 主库
Backend.Composite) - ❌ KV jsonb backend(v0.2)
- ❌ Cloak encryption 强制集成(提供
Snapshot.redact/2hook 给集成方)
Migration
新引入,无 migration。配置 + mix ecto.migrate 即可使用。