Mock LLM provider — Builder API 构造响应队列,配合 CMDC.Config.provider_fn 注入。
替代集成方各自实现的 inline mock,统一所有第三方测试的 mock LLM 行为。
设计
内部用 :persistent_term 存储响应队列 + 索引(避免持有 GenServer 进程生命周期),
to_provider_fn/1 返回一个 Config.provider_fn 接口的闭包,每次调用从队头取响应:
- 文本响应 → spawn 一个 stream bridge 进程,分块 emit 给 Agent
- 工具调用响应 → spawn 一个 bridge,emit 单个 tool_call chunk
- 错误响应 → 直接返回
{:error, reason}
Quick Start
provider =
CMDCTest.MockProvider.new()
|> CMDCTest.MockProvider.respond("Hello, world!")
|> CMDCTest.MockProvider.respond_tool_call("shell", %{"cmd" => "ls"})
|> CMDCTest.MockProvider.respond("done")
{:ok, session} =
CMDC.create_agent(
model: "mock:test",
config: %{provider_fn: CMDCTest.MockProvider.to_provider_fn(provider)}
)
CMDC.prompt(session, "go") # 第 1 个 prompt 用第 1 个响应
CMDC.prompt(session, "tool") # 第 2 个 prompt 用 tool_call 响应
CMDC.prompt(session, "end") # 第 3 个 prompt 用 "done"清理
:persistent_term 在测试结束后会随 BEAM 节点持续存在;可在 on_exit 调用
cleanup/1 主动释放。短测试通常无需清理(数据量很小)。
setup do
provider = MockProvider.new() |> MockProvider.respond("ok")
on_exit(fn -> MockProvider.cleanup(provider) end)
%{provider: provider}
end
Summary
Functions
释放该 MockProvider 在 :persistent_term 中的存储。
构造新的 MockProvider,初始响应队列为空。
追加一条文本响应。
追加一条错误响应。Agent 收到后走错误恢复路径(可能 retry 或 abort)。
追加一条工具调用响应。
导出 Config.provider_fn 兼容的闭包。
Types
Functions
@spec cleanup(t()) :: :ok
释放该 MockProvider 在 :persistent_term 中的存储。
@spec new() :: t()
构造新的 MockProvider,初始响应队列为空。
示例
iex> provider = CMDCTest.MockProvider.new()
iex> provider.responses
[]
追加一条文本响应。
追加一条错误响应。Agent 收到后走错误恢复路径(可能 retry 或 abort)。
追加一条工具调用响应。
参数
name— 工具名(必须与 Agent.tools 列表中某个tool.name()匹配,否则 Agent 会发:tool_call_unknown事件并注入 error tool_result)args— 工具参数 map(按工具自身的 parameters schema 序列化)
Agent 收到此响应后会:
- 在当前 turn 调用对应工具
- 收集结果作为 ToolMessage
- 进入下一 turn 继续找 mock 队列中的下一个响应
@spec to_provider_fn(t()) :: (String.t(), list(), list(), keyword() -> {:ok, map()} | {:error, term()})
导出 Config.provider_fn 兼容的闭包。
接口签名:fn model, messages, tools, opts -> {:ok, %{bridge_pid: pid}} | {:error, term}
与 cmdc 主库 Agent.Integration 测试中的 mock 完全一致。