TemplateContextBuilder

Struct TemplateContextBuilder 

Source
pub struct TemplateContextBuilder { /* private fields */ }
Expand description

Template context builder for AGPM resource installation.

This struct is responsible for building the template context that will be available to Markdown templates during rendering. It collects data from the manifest, lockfile, and current resource being processed.

§Context Structure

The built context follows this structure:

{
  "agpm": {
    "resource": {
      "type": "agent",
      "name": "example-agent",
      "install_path": ".claude/agents/example.md",
      "source": "community",
      "version": "v1.0.0",
      "resolved_commit": "abc123...",
      "checksum": "sha256:...",
      "path": "agents/example.md"
    },
    "deps": {
      "agents": {
        "helper": {
          "install_path": ".claude/agents/helper.md",
          "version": "v1.0.0",
          "resolved_commit": "def456...",
          "checksum": "sha256:...",
          "source": "community",
          "path": "agents/helper.md"
        }
      },
      "snippets": { ... },
      "commands": { ... }
    }
  }
}

Implementations§

Source§

impl TemplateContextBuilder

Source

pub fn new( lockfile: Arc<LockFile>, project_config: Option<ProjectConfig>, cache: Arc<Cache>, project_dir: PathBuf, ) -> Self

Create a new template context builder.

§Arguments
  • lockfile - The resolved lockfile, wrapped in Arc for efficient sharing
  • project_config - Optional project-specific template variables from the manifest
  • cache - Cache instance for reading source files during content extraction
  • project_dir - Project root directory for resolving local file paths
Source

pub fn clear_render_cache(&self)

Clear the render cache.

Should be called after installation completes to free memory and ensure next installation starts with a fresh cache.

Source

pub fn clear_custom_names_cache(&self)

Clear the custom names cache.

Should be called after installation completes to free memory and ensure next installation starts with a fresh cache.

Source

pub fn clear_dependency_specs_cache(&self)

Clear the dependency specs cache.

Should be called after installation completes to free memory and ensure next installation starts with a fresh cache.

Source

pub fn render_cache_stats(&self) -> Option<(usize, usize, f64)>

Get render cache statistics.

Returns (hits, misses, hit_rate) where hit_rate is a percentage.

Source

pub async fn build_context( &self, resource_id: &ResourceId, variant_inputs: &Value, ) -> Result<(TeraContext, Option<String>)>

Build the complete template context for a specific resource.

§Arguments
  • resource_name - Name of the resource being rendered
  • resource_type - Type of the resource (agents, snippets, etc.)
  • template_vars_override - Optional template variable overrides for this specific resource. Overrides are deep-merged into the base context, preserving unmodified fields.
§Returns

Returns a Tera Context containing all available template variables.

§Template Variable Override Behavior

When template_vars_override is provided, it is deep-merged into the base template context:

  • Objects: Recursively merged, preserving fields not present in override
  • Primitives/Arrays: Completely replaced by override value
  • Null values: Replace existing value with JSON null (may cause template errors)
  • Empty objects: No-op (no changes applied)

Special handling for project namespace: Updates both agpm.project (canonical) and top-level project (convenience alias) to maintain consistency.

§Examples
// Base context has project.name = "agpm" and project.language = "rust"
let overrides = json!({
    "project": {
        "language": "python",  // Replaces existing value
        "framework": "fastapi" // Adds new field
    }
});

use agpm_cli::lockfile::ResourceId;
use agpm_cli::utils::compute_variant_inputs_hash;
// Create ResourceId with template_vars and ResourceType included
let variant_hash = compute_variant_inputs_hash(&overrides).unwrap_or_default();
let resource_id = ResourceId::new("agent", None::<String>, Some("claude-code"), ResourceType::Agent, variant_hash);
let (context, _context_checksum) = builder
    .build_context(&resource_id, &overrides)
    .await?;

// Result: project.name preserved, language replaced, framework added
Source

pub fn compute_context_digest(&self) -> Result<String>

Compute a stable digest of the template context data.

This method creates a deterministic hash of all lockfile metadata that could affect template rendering. The digest is used as part of the cache key to ensure that changes to dependency versions or metadata properly invalidate the cache.

§Returns

Returns a hex-encoded string containing the first 16 characters of the SHA-256 hash of the serialized template context data. This is sufficient to uniquely identify context changes while keeping the digest compact.

§What’s Included

The digest includes all lockfile metadata that affects rendering:

  • Resource names, types, and installation paths
  • Dependency versions and resolved commits
  • Checksums and source information
§Determinism

The hash is stable across runs because:

  • Resources are sorted by type and name before hashing
  • JSON serialization uses consistent ordering (BTreeMap)
  • Only metadata fields that affect rendering are included
§Examples
use agpm_cli::templating::TemplateContextBuilder;
use agpm_cli::lockfile::LockFile;
use std::path::{Path, PathBuf};
use std::sync::Arc;

let lockfile = LockFile::load(Path::new("agpm.lock"))?;
let cache = Arc::new(agpm_cli::cache::Cache::new()?);
let project_dir = std::env::current_dir()?;
let builder = TemplateContextBuilder::new(
    Arc::new(lockfile),
    None,
    cache,
    project_dir
);

let digest = builder.compute_context_digest()?;
println!("Template context digest: {}", digest);

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more