Class: RailsAiContext::Fingerprinter

Inherits:
Object
  • Object
show all
Defined in:
lib/rails_ai_context/fingerprinter.rb

Overview

Computes a SHA256 fingerprint of key application files to detect changes. Used by BaseTool to invalidate cached introspection when files change.

Constant Summary collapse

WATCHED_FILES =
%w[
  db/schema.rb
  db/structure.sql
  config/routes.rb
  config/database.yml
  Gemfile.lock
  package.json
  tsconfig.json
].freeze
WATCHED_DIRS =
%w[
  app/models
  app/controllers
  app/views
  app/jobs
  app/mailers
  app/channels
  app/components
  app/javascript/controllers
  app/middleware
  config/initializers
  db/migrate
  lib/tasks
].freeze

Class Method Summary collapse

Class Method Details

.changed?(app, previous) ⇒ Boolean

Returns:

  • (Boolean)


112
113
114
# File 'lib/rails_ai_context/fingerprinter.rb', line 112

def changed?(app, previous)
  compute(app) != previous
end

.compute(app) ⇒ Object



35
36
37
38
39
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
# File 'lib/rails_ai_context/fingerprinter.rb', line 35

def compute(app)
  root = app.root.to_s
  digest = Digest::SHA256.new

  # Include the gem's own version so cache invalidates during gem development
  digest.update(RailsAiContext::VERSION)

  # Include gem lib directory fingerprint when using a local/path gem.
  # MEMOIZED — the gem lib contents don't change within a single process
  # lifetime unless a developer is actively editing the gem source (rare
  # audience, they should restart the server to see changes). Previously
  # this walked 123 gem files on every tool call, adding ~12ms to the
  # cached_context hot path for path:-installed users.
  digest.update(gem_lib_fingerprint(root))

  WATCHED_FILES.each do |file|
    path = File.join(root, file)
    digest.update(File.mtime(path).to_f.to_s) if File.exist?(path)
  rescue Errno::ENOENT
    # File deleted between exist? check and mtime read — skip
  end

  WATCHED_DIRS.each do |dir|
    full_dir = File.join(root, dir)
    next unless Dir.exist?(full_dir)

    Dir.glob(File.join(full_dir, "**/*.{rb,rake,js,ts,erb,haml,slim,yml}")).sort.each do |path|
      digest.update(File.mtime(path).to_f.to_s)
    rescue Errno::ENOENT
      # File deleted between glob and mtime read — skip
    end
  end

  digest.hexdigest
end

.reset_gem_lib_fingerprint!Object

Clear the memoized gem-lib fingerprint. Called by BaseTool.reset_cache! and LiveReload so active gem development gets a fresh scan on next call without requiring a process restart.



74
75
76
# File 'lib/rails_ai_context/fingerprinter.rb', line 74

def reset_gem_lib_fingerprint!
  @gem_lib_fingerprint = nil
end