Gralkor.Client behaviour (jido_gralkor v11.0.0)

Copy Markdown View Source

Public entry point and adapter port for Gralkor memory.

Named Lens operations use ingest/1 and replace/1; search/1 reads registered Destinations and may filter episode writers by Lens. Ingestion resolves an appending Lens and invokes its ingestion process with a Lens-bound store. Replacement validates and stores the complete graph for a replaceable Lens. Lenses and Reflections reference first-class Destinations, each of which names one graph. Appending Lenses select the ontology for their writes; Reflection Destination outputs select it for runtime-delivered artefacts. The runtime-targeted arities resolve names from one consuming AgentServer's atomic configuration snapshot. reflect/5 admits an invocation without waiting for production and reports its terminal result through the supplied callback. With empty selectors, search runs every accessible registered Destination concurrently and returns episodes from direct, Lens, and Reflection writers. Destination and Lens names are ORed within their respective selectors and ANDed across them; Lens filters are applied to episodes and facts. Each result identifies its Destination. Direct episodes retain their source without Lens or Reflection authorship; real Lens and Reflection records retain their named writer. Historical unmarked and operator-labelled records remain readable without an active operator Lens. Facts, nodes, and Reflection artefacts are explicit advanced result types.

Capture uses capture/2 with an owning AgentServer PID and an explicit Gralkor.Capture route. Direct capture selects a registered Destination; Lens capture runs distinct selected processes without an implicit direct write. Positional capture adapters raise migration guidance. The low-level adapter ports retain recall/4, memory_add/3 or /4, and flush operations. Logical graph IDs are encoded exactly once as g_ plus the lowercase hexadecimal encoding of every original byte (sanitize_group_id/1). The personal Destination resolves to personal/<operator id>; other registered Destinations resolve to their exact shared names. Retired operator inputs require an explicit migration and never become shared private-memory graphs.

flush/1 returns :ok before the buffered turns have landed (fire-and-forget — appropriate for shutdown paths that cannot block). flush_and_await/2 returns :ok only after buffered ingestion completes, for callers that must observe completion before rotating state (for example session-id rotation in JidoGralkor.ContextRotator).

The concrete adapter is resolved from Application.get_env(:jido_gralkor, :client); defaults to Gralkor.Client.Native (in-process via Pythonx). Tests swap in Gralkor.Client.InMemory.

No health_check/0 — the embedded runtime is ready by the time Application.start/2 returns; runtime failures surface from the next call.

Summary

Types

agent_name()

@type agent_name() :: String.t()

group_id()

@type group_id() :: String.t()

messages()

@type messages() :: [Gralkor.Message.t()]

runtime_owner()

@type runtime_owner() :: pid()

search_result()

@type search_result() :: Gralkor.Search.result()

session_id()

@type session_id() :: String.t()

user_name()

@type user_name() :: String.t()

Callbacks

build_communities(group_id)

@callback build_communities(group_id()) ::
  {:ok, %{communities: non_neg_integer(), edges: non_neg_integer()}}
  | {:error, term()}

build_indices()

@callback build_indices() :: {:ok, %{status: String.t()}} | {:error, term()}

capture(runtime_owner, t)

@callback capture(runtime_owner(), Gralkor.Capture.t()) :: :ok | {:error, term()}

flush(session_id)

@callback flush(session_id()) :: :ok | {:error, term()}

flush_and_await(session_id, timeout_ms)

@callback flush_and_await(session_id(), timeout_ms :: pos_integer()) ::
  :ok | {:error, :timeout} | {:error, term()}

memory_add(group_id, content, source_description)

@callback memory_add(
  group_id(),
  content :: String.t(),
  source_description :: String.t() | nil
) :: :ok | {:error, term()}

memory_add(group_id, content, source_description, source_kind)

@callback memory_add(
  group_id(),
  content :: String.t() | map() | list(),
  source_description :: String.t() | nil,
  source_kind :: Gralkor.Ingest.source_kind()
) :: :ok | {:error, term()}

recall(group_id, agent_name, arg3, query)

@callback recall(group_id(), agent_name(), session_id() | nil, query :: String.t()) ::
  {:ok, String.t()} | {:error, term()}

Functions

capture(runtime_owner, request)

@spec capture(runtime_owner(), Gralkor.Capture.t()) :: :ok | {:error, term()}

impl()

@spec impl() :: module()

ingest(request)

@spec ingest(Gralkor.Ingest.t()) :: :ok | {:error, term()}

ingest(runtime_owner, request)

@spec ingest(runtime_owner(), Gralkor.Ingest.t()) :: :ok | {:error, term()}

lens!(name)

reflect(runtime_owner, reflection_name, invocation, callback, opts \\ [])

@spec reflect(runtime_owner(), String.t(), map(), (term() -> any()), keyword()) ::
  {:ok, String.t()} | {:error, term()}

replace(request)

@spec replace(Gralkor.Replace.t()) :: :ok | {:error, term()}

replace(runtime_owner, request)

@spec replace(runtime_owner(), Gralkor.Replace.t()) :: :ok | {:error, term()}

sanitize_group_id(id)

@spec sanitize_group_id(String.t()) :: String.t()

search(request)

@spec search(Gralkor.Search.t()) :: {:ok, [search_result()]} | {:error, term()}

search(runtime_owner, request)

@spec search(runtime_owner(), Gralkor.Search.t()) ::
  {:ok, [search_result()]} | {:error, term()}