module

LLM::Cache

Constants

CACHE_DIR_PERMISSIONS = 448

0700, and entries below are written 0600 (see store). A cache entry is the model's answer about a specific chunk of the user's source, and the prompt it answers is that source — private code, on a box that may have other accounts. The default 0755/0644 published it to every local user. $NOIR_HOME/config.yaml is already 0600 for the same reason.

CACHE_FILE_PERMISSIONS = 384
CACHE_FILE_SUFFIX = ".json"

All cache entries are stored as <sha256>.json flat in cache_dir. The bulk operations below (clear, purge_older_than, stats) filter on this suffix so a stray .lock or user-dropped file in the directory is left alone.

CACHE_TMP_MARKER = ".tmp-"

Infix store stamps onto its in-flight temp file (see store). Kept as a constant so the writer and the sweepers below can't drift apart: a stranded temp file whose name the sweepers don't recognize is a file nothing can ever delete.

Class methods

cache_dir
Source
clear
Source
delete(key : String) : Bool
Source
disable
Source
disabled_by_env?
Source
enable
Source
enabled?
Source
ensure_dir
Source
fetch(key : String) : String | Nil
Source
key(provider : String, model : String, kind : String, format : String, payload : String) : String

Build a deterministic cache key from inputs

  • provider: "openai", "ollama", url, etc.
  • model: "gpt-4o", "llama3", etc.
  • kind: logical operation e.g. "FILTER", "ANALYZE", "BUNDLE_ANALYZE"
  • format: response_format string (e.g., "json" or JSON schema string)
  • payload: variable content (file list, source code, bundle, etc.)

Returns a hex-encoded SHA256 digest.

Source
logger
Source
logger=(logger : NoirLogger | Nil) : Nil
Source
path_for(key : String) : String
Source
purge_older_than(days : Int32) : DeleteOutcome
Source
stats
Source
store(key : String, content : String) : Bool

Write atomically: a partially-written file from a crash mid-write would parse as broken JSON on the next fetch, forcing a spurious fresh API call. By writing to a tmp sibling and renaming we either leave the previous (valid) entry in place or atomically publish the new one.

Source
tmp_entry?(name : String) : Bool

True for a temp file stranded by a crash between File.write and File.rename. These do not end in .json, so the bulk operations used to skip them entirely — clear could not remove them and stats did not count their bytes, leaving files that grew the cache directory with no way to reclaim them from the CLI.

Source

Nested types