NAME

Langertha::CachedContent - Immutable value object for a Gemini explicit cachedContent resource

VERSION

version 0.503

SYNOPSIS

# Create-input shape (no name yet)
my $cc = Langertha::CachedContent->new(
    model              => 'models/gemini-2.5-pro',
    system_instruction => 'You are a careful reviewer.',
    ttl                => '300s',
    contents           => [ { role => 'user', parts => [ { text => 'long prompt...' } ] } ],
);
my $body = $cc->to_create_body;
# { model => 'models/gemini-2.5-pro',
#   systemInstruction => { parts => [ { text => '...' } ] },
#   ttl => '300s',
#   contents => [ ... ] }

# Server-returned shape
my $cc2 = Langertha::CachedContent->from_hash({
    name          => 'cachedContents/abc123',
    model         => 'models/gemini-2.5-pro',
    displayName   => 'reviewer-context',
    createTime    => '2026-08-11T10:00:00Z',
    updateTime    => '2026-08-11T10:00:00Z',
    expireTime    => '2026-08-11T10:05:00Z',
    usageMetadata => { totalTokenCount => 4096 },
});
$cc2->is_expired;   # bool (vs. cached expireTime + clock)
$cc2->age_seconds;  # since updateTime

DESCRIPTION

Canonical value object for the Gemini explicit context-cache resource (https://ai.google.dev/api/caching) — a server-side managed cache of input context with its own lifecycle (create / get / list / patch / delete).

Distinct from Langertha::PromptCache:

  • Langertha::PromptCache models the request-side caching knob (Anthropic cache_control breakpoint, OpenAI prompt_cache_key) that flips behaviour on the next request. ADR 0009.

  • This class models the resource itself — a long-lived cached context blob identified by name (cachedContents/{id}) that the client manages across requests.

The two seams are deliberately separate: a CachedContent resource lives across many requests and the engine request body references it by name (via the cachedContent field on a generateContent body). See Langertha::Role::CachedContent for the create / get / list / update / delete wrappers around this object.

The value object carries one wire shape today: Gemini cachedContent. Like Langertha::Tool/Langertha::PromptCache, future providers that expose the same resource can add a to_$fmt serializer without touching the engines.

name

Resource name, cachedContents/{id}. undef for create-input objects that have not yet been persisted; populated from the server response or set manually when wrapping an externally-obtained cache.

model

Required on create. Full model name (models/gemini-2.5-pro) per the Gemini REST contract. Optional on read-only shapes (Langertha::Engine::Gemini always populates it on responses, but a future response-less path may not).

contents

ArrayRef of content parts (the same shape Langertha::Engine::Gemini puts in the contents request body field: [{ role => 'user', parts => [{text => '...'}] }]). Immutable on the server once created — input only, never echoed back as updatable.

system_instruction

Optional systemInstruction text. The Gemini REST contract accepts text only (no structured parts).

tools

Optional ArrayRef of tool definitions in the canonical Langertha::Tool form (or any shape Langertha::Tool::from_list accepts). Serialized on create as the Gemini tools list, [ { functionDeclarations => [...] } ], the shape a generateContent request uses.

ttl

Optional Duration string ("300s", "3600s"). Mutually exclusive with "expire_time" — exactly one of the two is permitted per "BUILD". "create_f" in Langertha::Role::CachedContent sends whichever was set.

expire_time

Optional absolute expiration as an RFC 3339 timestamp string ("2026-08-11T10:05:00Z"). Mutually exclusive with "ttl".

display_name

Optional human-readable label (max 128 Unicode chars on the server). Only the create body carries it; updates can PATCH it via updateMask.

create_time

Server-set RFC 3339 timestamp. Populated from the create / get / list response.

update_time

Server-set RFC 3339 timestamp of last update. Populated from the response.

total_token_count

From usageMetadata.totalTokenCount in the create / get / list response. Useful for cache-hit accounting; the per-request hit count surfaces via the "usage" in Langertha::Response cached_content_token_count field.

to_create_body

my $href = $cc->to_create_body;

Returns the POST cachedContents request body HashRef. Croaks if "model" is unset. "ttl" / "expire_time" serialize into the expiration oneof as ttl or expireTime.

to_reference

my $href = $cc->to_reference;
# { cachedContent => 'cachedContents/abc123' }

Returns the HashRef Langertha::Engine::Gemini merges into a generateContent body to reference this cachedContent by name.

from_hash

my $cc = Langertha::CachedContent->from_hash($response_href);

Builds a value object from a cachedContent response hash (GET / POST / LIST). Returns undef if $hash is not a hashref or carries no name. The expiry is read from the top-level expireTime (or ttl) the server sends; an expiration wrapper holding either is read as well. When both an expireTime and a ttl are present, expireTime is kept. Accepts an existing Langertha::CachedContent as a pass-through.

age_seconds

Returns whole seconds since the cache's "update_time" (or "create_time" as fallback), or undef if neither is set. Useful for diagnosing TTL drift between the client's clock and the server.

is_expired

Returns true when the cache is past its "expire_time" (server-reported), or when update_time + ttl has elapsed for caches that did not report an absolute expiry. Returns false when no expiry information is available.

SEE ALSO

SUPPORT

Issues

Please report bugs and feature requests on GitHub at https://github.com/Getty/langertha/issues.

IRC

Join #langertha on irc.perl.org or message Getty directly.

CONTRIBUTING

Contributions are welcome! Please fork the repository and submit a pull request.

AUTHOR

Torsten Raudssus <getty@cpan.org>

COPYRIGHT AND LICENSE

This software is copyright (c) 2026 by Torsten Raudssus https://raudssus.de/.

This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.