Class: Aidp::Harness::ModelCache

Inherits:
Object
  • Object
show all
Defined in:
lib/aidp/harness/model_cache.rb

Overview

Manages caching of discovered models with TTL support

Cache is stored in ~/.aidp/cache/models.json Each provider’s models are cached separately with timestamps

Usage:

cache = ModelCache.new
cache.cache_models("anthropic", models_array)
cached = cache.get_cached_models("anthropic")
cache.invalidate("anthropic")

Defined Under Namespace

Classes: CacheError

Constant Summary collapse

DEFAULT_TTL =

24 hours in seconds

86400

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(cache_file: nil, cache_dir: nil) ⇒ ModelCache

Returns a new instance of ModelCache.



25
26
27
28
29
30
31
32
33
34
# File 'lib/aidp/harness/model_cache.rb', line 25

def initialize(cache_file: nil, cache_dir: nil)
  @cache_file = determine_cache_file(cache_file, cache_dir)
  @cache_enabled = ensure_cache_directory

  if @cache_enabled
    Aidp.log_debug("model_cache", "initialized", cache_file: @cache_file)
  else
    Aidp.log_warn("model_cache", "cache disabled due to permission issues")
  end
end

Instance Attribute Details

#cache_fileObject (readonly)

Returns the value of attribute cache_file.



23
24
25
# File 'lib/aidp/harness/model_cache.rb', line 23

def cache_file
  @cache_file
end

Instance Method Details

#cache_models(provider, models, ttl: DEFAULT_TTL) ⇒ Object

Cache models for a provider with TTL

Parameters:

  • provider (String)

    Provider name

  • models (Array<Hash>)

    Models to cache

  • ttl (Integer) (defaults to: DEFAULT_TTL)

    Time to live in seconds (default: 24 hours)



79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/aidp/harness/model_cache.rb', line 79

def cache_models(provider, models, ttl: DEFAULT_TTL)
  unless @cache_enabled
    Aidp.log_debug("model_cache", "caching disabled, skipping",
      provider: provider)
    return false
  end

  cache_data = load_cache

  cache_data[provider] = {
    "cached_at" => Time.now.iso8601,
    "ttl" => ttl,
    "models" => models
  }

  if save_cache(cache_data)
    Aidp.log_info("model_cache", "cached models",
      provider: provider, count: models.size, ttl: ttl)
    true
  else
    Aidp.log_warn("model_cache", "failed to cache models",
      provider: provider)
    false
  end
rescue => e
  Aidp.log_error("model_cache", "error caching models",
    provider: provider, error: e.message)
  false
end

#cached_providersArray<String>

Get list of providers with cached models

Returns:

  • (Array<String>)

    Provider names with valid caches



142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
# File 'lib/aidp/harness/model_cache.rb', line 142

def cached_providers
  cache_data = load_cache
  providers = []

  cache_data.each do |provider, data|
    cached_at = begin
      Time.parse(data["cached_at"])
    rescue
      nil
    end
    next unless cached_at

    ttl = data["ttl"] || DEFAULT_TTL
    expires_at = cached_at + ttl

    providers << provider if Time.now <= expires_at
  end

  providers
rescue => e
  Aidp.log_error("model_cache", "failed to get cached providers",
    error: e.message)
  []
end

#get_cached_models(provider) ⇒ Array<Hash>?

Get cached models for a provider if not expired

Parameters:

  • provider (String)

    Provider name

Returns:

  • (Array<Hash>, nil)

    Cached models or nil if expired/not found



40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/aidp/harness/model_cache.rb', line 40

def get_cached_models(provider)
  cache_data = load_cache
  provider_cache = cache_data[provider]

  return nil unless provider_cache

  cached_at = begin
    Time.parse(provider_cache["cached_at"])
  rescue
    nil
  end
  return nil unless cached_at

  ttl = provider_cache["ttl"] || DEFAULT_TTL
  expires_at = cached_at + ttl

  if Time.now > expires_at
    Aidp.log_debug("model_cache", "cache expired",
      provider: provider, cached_at: cached_at, expires_at: expires_at)
    return nil
  end

  models = provider_cache["models"]
  # Convert string keys to symbols for consistency with fresh discovery
  models = models.map { |m| m.transform_keys(&:to_sym) } if models
  Aidp.log_debug("model_cache", "cache hit",
    provider: provider, count: models&.size || 0)
  models
rescue => e
  Aidp.log_error("model_cache", "failed to read cache",
    provider: provider, error: e.message)
  nil
end

#invalidate(provider) ⇒ Object

Invalidate cache for a specific provider

Parameters:

  • provider (String)

    Provider name



112
113
114
115
116
117
118
119
120
121
122
123
124
# File 'lib/aidp/harness/model_cache.rb', line 112

def invalidate(provider)
  return false unless @cache_enabled

  cache_data = load_cache
  cache_data.delete(provider)
  save_cache(cache_data)
  Aidp.log_info("model_cache", "invalidated cache", provider: provider)
  true
rescue => e
  Aidp.log_error("model_cache", "failed to invalidate cache",
    provider: provider, error: e.message)
  false
end

#invalidate_allObject

Invalidate all cached models



127
128
129
130
131
132
133
134
135
136
137
# File 'lib/aidp/harness/model_cache.rb', line 127

def invalidate_all
  return false unless @cache_enabled

  save_cache({})
  Aidp.log_info("model_cache", "invalidated all caches")
  true
rescue => e
  Aidp.log_error("model_cache", "failed to invalidate all",
    error: e.message)
  false
end

#statsHash

Get cache statistics

Returns:

  • (Hash)

    Statistics about the cache



170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
# File 'lib/aidp/harness/model_cache.rb', line 170

def stats
  cache_data = load_cache
  file_size = begin
    File.size(@cache_file)
  rescue
    0
  end

  {
    total_providers: cache_data.size,
    cached_providers: cached_providers,
    cache_file_size: file_size
  }
rescue => e
  Aidp.log_error("model_cache", "failed to get stats",
    error: e.message)
  {total_providers: 0, cached_providers: [], cache_file_size: 0}
end