Packages

AI integration layer for the Jido ecosystem - Actions, Workflows, and LLM orchestration

Current section

Files

Jump to
jido_ai lib jido_ai reasoning chain_of_draft cli_adapter.ex
Raw

lib/jido_ai/reasoning/chain_of_draft/cli_adapter.ex

defmodule Jido.AI.Reasoning.ChainOfDraft.CLIAdapter do
@moduledoc """
CLI adapter for Chain-of-Draft-style agents.
"""
@behaviour Jido.AI.CLI.Adapter
@default_model :fast
@impl true
def start_agent(jido_instance, agent_module, _config) do
Jido.start_agent(jido_instance, agent_module)
end
@impl true
def submit(pid, query, config) do
agent_module = config.agent_module
agent_module.draft(pid, query)
end
@impl true
def await(pid, timeout_ms, _config) do
poll_interval = 100
deadline = System.monotonic_time(:millisecond) + timeout_ms
poll_loop(pid, deadline, poll_interval)
end
@impl true
def stop(pid) do
try do
GenServer.stop(pid, :normal, 1000)
catch
:exit, _ -> :ok
end
:ok
end
@impl true
def create_ephemeral_agent(config) do
suffix = :erlang.unique_integer([:positive])
module_name = Module.concat([JidoAi, EphemeralAgent, :"CoD#{suffix}"])
model = config[:model] || @default_model
system_prompt = config[:system_prompt]
contents =
if system_prompt do
quote do
use Jido.AI.CoDAgent,
name: "cli_cod_agent",
description: "CLI ephemeral CoD agent",
model: unquote(model),
system_prompt: unquote(system_prompt)
end
else
quote do
use Jido.AI.CoDAgent,
name: "cli_cod_agent",
description: "CLI ephemeral CoD agent",
model: unquote(model)
end
end
Module.create(module_name, contents, Macro.Env.location(__ENV__))
module_name
end
defp poll_loop(pid, deadline, interval) do
now = System.monotonic_time(:millisecond)
if now >= deadline do
{:error, :timeout}
else
case Jido.AgentServer.status(pid) do
{:ok, status} ->
if status.snapshot.done? do
answer =
case status.snapshot.result do
nil -> Map.get(status.raw_state, :last_result, "")
"" -> Map.get(status.raw_state, :last_result, "")
result -> result
end
{:ok, %{answer: answer, meta: extract_meta(status)}}
else
Process.sleep(interval)
poll_loop(pid, deadline, interval)
end
{:error, reason} ->
{:error, reason}
end
end
end
defp extract_meta(status) do
details = status.snapshot.details || %{}
%{
status: status.snapshot.status,
steps_count: Map.get(details, :steps_count, 0),
phase: Map.get(details, :phase),
duration_ms: Map.get(details, :duration_ms)
}
end
end