Raxol.Agent.Skills.Store (Raxol Agent v2.6.0)

Copy Markdown View Source

Disk-backed index of procedural-memory skills, with usage telemetry.

A skill is a directory on disk holding a SKILL.md (parsed by Raxol.Agent.Skill) plus optional supporting files. Disk is the source of truth; this BaseManager GenServer is a warm index over it. The index is built by scanning a managed root (writable, default ~/.raxol/skills) and any read-only external_dirs (default ~/.agents/skills), so an agent can read the user's existing skill library.

Per-skill usage telemetry (use_count, view_count, last_used_at, state, pinned) is the store's own state and is persisted to a DETS file via Raxol.Core.Stores.Dets so it survives a restart; the skills themselves are re-read from disk every boot, so no stale skill content can outlive its file.

Tables (derived from the registered name)

  • primary :set {name, %{skill, dir, source}} -- the live skill index
  • Usage :set {name, usage_map} -- telemetry, mirrored to DETS

source is :managed (under skills_root, writable) or :external (read-only). skill_manage writes only ever touch :managed skills.

Summary

Functions

Archive a managed skill: move its directory under <root>/.archive/ and drop it from the index, so it no longer appears in list/1. Telemetry is retained with state: :archived.

Returns a specification to start this module under a supervisor.

Create (or overwrite) a managed skill from attrs (%{name, description, category, body, created_by, version, metadata}). Writes SKILL.md under skills_root and re-indexes.

Delete a managed skill (its directory) and drop it from the index.

Full parsed %Skill{} for name, or {:error, :not_found}.

Skill metadata only (the cheap level): name, category, description, state, source.

Merge changes (any of :description, :category, :version, :body, :metadata) into a managed skill.

Pin a skill so the Curator never ages or rewrites it.

Derived ETS table names. Public for tests and tooling.

Record that a skill was used (increments use_count, sets last_used_at).

Force a re-scan of disk into the index. Telemetry is preserved.

The managed skills root directory (where new skills are written).

Set a skill's lifecycle state (:active/:stale/:archived). Used by the Curator.

Per-skill telemetry snapshot for every indexed skill, for the Curator to decide lifecycle transitions: name, created_by, source, state, pinned, last_used_at, created_at.

Remove a skill's pin.

Usage telemetry for a skill, or {:error, :not_found}.

Read a skill's SKILL.md body (when path is nil) or one supporting file relative to the skill directory. Bumps the skill's view telemetry.

Types

skill_state()

@type skill_state() :: :active | :stale | :archived

usage()

@type usage() :: %{
  use_count: non_neg_integer(),
  view_count: non_neg_integer(),
  last_used_at: integer() | nil,
  created_at: integer() | nil,
  state: skill_state(),
  pinned: boolean()
}

Functions

archive(name, opts \\ [])

@spec archive(
  String.t(),
  keyword()
) :: :ok | {:error, term()}

Archive a managed skill: move its directory under <root>/.archive/ and drop it from the index, so it no longer appears in list/1. Telemetry is retained with state: :archived.

child_spec(init_arg)

Returns a specification to start this module under a supervisor.

See Supervisor.

create(attrs, opts \\ [])

@spec create(
  map(),
  keyword()
) :: {:ok, Raxol.Agent.Skill.t()} | {:error, term()}

Create (or overwrite) a managed skill from attrs (%{name, description, category, body, created_by, version, metadata}). Writes SKILL.md under skills_root and re-indexes.

delete(name, opts \\ [])

@spec delete(
  String.t(),
  keyword()
) :: :ok | {:error, term()}

Delete a managed skill (its directory) and drop it from the index.

get(name, opts \\ [])

@spec get(
  String.t(),
  keyword()
) :: {:ok, Raxol.Agent.Skill.t()} | {:error, :not_found}

Full parsed %Skill{} for name, or {:error, :not_found}.

handle_manager_info(msg, state)

Callback implementation for Raxol.Core.Behaviours.BaseManager.handle_manager_info/2.

list(opts \\ [])

@spec list(keyword()) :: [map()]

Skill metadata only (the cheap level): name, category, description, state, source.

patch(name, changes, opts \\ [])

@spec patch(String.t(), map(), keyword()) ::
  {:ok, Raxol.Agent.Skill.t()} | {:error, term()}

Merge changes (any of :description, :category, :version, :body, :metadata) into a managed skill.

pin(name, opts \\ [])

@spec pin(
  String.t(),
  keyword()
) :: :ok | {:error, :not_found}

Pin a skill so the Curator never ages or rewrites it.

primary_table(name)

@spec primary_table(atom()) :: atom()

Derived ETS table names. Public for tests and tooling.

record_use(name, opts \\ [])

@spec record_use(
  String.t(),
  keyword()
) :: :ok

Record that a skill was used (increments use_count, sets last_used_at).

reload(opts \\ [])

@spec reload(keyword()) :: :ok

Force a re-scan of disk into the index. Telemetry is preserved.

root(opts \\ [])

@spec root(keyword()) :: String.t()

The managed skills root directory (where new skills are written).

set_state(name, new_state, opts \\ [])

@spec set_state(String.t(), skill_state(), keyword()) :: :ok | {:error, :not_found}

Set a skill's lifecycle state (:active/:stale/:archived). Used by the Curator.

start_link(init_opts \\ [])

@spec start_link(keyword()) :: GenServer.on_start()

telemetry(opts \\ [])

@spec telemetry(keyword()) :: [map()]

Per-skill telemetry snapshot for every indexed skill, for the Curator to decide lifecycle transitions: name, created_by, source, state, pinned, last_used_at, created_at.

unpin(name, opts \\ [])

@spec unpin(
  String.t(),
  keyword()
) :: :ok | {:error, :not_found}

Remove a skill's pin.

usage(name, opts \\ [])

@spec usage(
  String.t(),
  keyword()
) :: {:ok, usage()} | {:error, :not_found}

Usage telemetry for a skill, or {:error, :not_found}.

usage_table(name)

@spec usage_table(atom()) :: atom()

view(name, path \\ nil, opts \\ [])

@spec view(String.t(), String.t() | nil, keyword()) ::
  {:ok, String.t()} | {:error, term()}

Read a skill's SKILL.md body (when path is nil) or one supporting file relative to the skill directory. Bumps the skill's view telemetry.