Class: Clacky::SessionManager
- Inherits:
-
Object
- Object
- Clacky::SessionManager
- Defined in:
- lib/clacky/session_manager.rb
Constant Summary collapse
- SESSIONS_DIR =
File.join(Dir.home, ".clacky", "sessions")
Class Method Summary collapse
-
.generate_id ⇒ Object
Generate a new unique session ID (16-char hex string).
Instance Method Summary collapse
-
#all_sessions(current_dir: nil, limit: nil) ⇒ Object
All sessions from disk, newest-first (sorted by created_at).
-
#cleanup(days: 90) ⇒ Object
Delete sessions not accessed within the given number of days (default: 90).
-
#cleanup_by_count(keep:) ⇒ Object
Keep only the most recent N sessions by created_at; delete the rest.
-
#delete(session_id) ⇒ Object
Physical delete — removes disk file + associated chunk files.
-
#delete_session_with_chunks(json_filepath) ⇒ Object
Delete a session JSON file and all its associated chunk MD files.
- #ensure_sessions_dir ⇒ Object
- #generate_filename(session_id, created_at) ⇒ Object
-
#initialize(sessions_dir: nil) ⇒ SessionManager
constructor
A new instance of SessionManager.
-
#last_saved_path ⇒ Object
Path of the last saved session file.
-
#latest_for_directory(working_dir) ⇒ Object
Return the most recent session for a given working directory, or nil.
-
#load(session_id) ⇒ Object
Load a specific session by ID.
- #load_session_file(filepath) ⇒ Object
-
#save(session_data) ⇒ Object
Save a session.
Constructor Details
#initialize(sessions_dir: nil) ⇒ SessionManager
Returns a new instance of SessionManager.
19 20 21 22 |
# File 'lib/clacky/session_manager.rb', line 19 def initialize(sessions_dir: nil) @sessions_dir = sessions_dir || SESSIONS_DIR ensure_sessions_dir end |
Class Method Details
.generate_id ⇒ Object
Generate a new unique session ID (16-char hex string). This is the single authoritative source for session IDs — all components (Agent, SessionRegistry) should receive an ID generated here rather than creating their own.
15 16 17 |
# File 'lib/clacky/session_manager.rb', line 15 def self.generate_id SecureRandom.hex(8) end |
Instance Method Details
#all_sessions(current_dir: nil, limit: nil) ⇒ Object
All sessions from disk, newest-first (sorted by created_at). Optional filters:
current_dir: (String) if given, sessions matching working_dir come first
limit: (Integer) max number of sessions to return
69 70 71 72 73 74 75 76 77 78 79 80 81 |
# File 'lib/clacky/session_manager.rb', line 69 def all_sessions(current_dir: nil, limit: nil) sessions = Dir.glob(File.join(@sessions_dir, "*.json")).filter_map do |filepath| load_session_file(filepath) end.sort_by { |s| s[:created_at] || "" }.reverse if current_dir current_sessions = sessions.select { |s| s[:working_dir] == current_dir } other_sessions = sessions.reject { |s| s[:working_dir] == current_dir } sessions = current_sessions + other_sessions end limit ? sessions.first(limit) : sessions end |
#cleanup(days: 90) ⇒ Object
Delete sessions not accessed within the given number of days (default: 90). Returns count of deleted sessions.
90 91 92 93 94 95 96 97 98 99 100 101 102 |
# File 'lib/clacky/session_manager.rb', line 90 def cleanup(days: 90) cutoff = Time.now - (days * 24 * 60 * 60) deleted = 0 Dir.glob(File.join(@sessions_dir, "*.json")).each do |filepath| session = load_session_file(filepath) next unless session if Time.parse(session[:updated_at]) < cutoff delete_session_with_chunks(filepath) deleted += 1 end end deleted end |
#cleanup_by_count(keep:) ⇒ Object
Keep only the most recent N sessions by created_at; delete the rest. Returns count of deleted sessions.
106 107 108 109 110 111 112 113 114 |
# File 'lib/clacky/session_manager.rb', line 106 def cleanup_by_count(keep:) sessions = all_sessions # already sorted newest-first return 0 if sessions.size <= keep sessions[keep..].each do |session| filepath = File.join(@sessions_dir, generate_filename(session[:session_id], session[:created_at])) delete_session_with_chunks(filepath) if File.exist?(filepath) end.size end |
#delete(session_id) ⇒ Object
Physical delete — removes disk file + associated chunk files. Returns true if found and deleted, false if not found.
56 57 58 59 60 61 62 63 |
# File 'lib/clacky/session_manager.rb', line 56 def delete(session_id) session = all_sessions.find { |s| s[:session_id].to_s.start_with?(session_id.to_s) } return false unless session filepath = File.join(@sessions_dir, generate_filename(session[:session_id], session[:created_at])) delete_session_with_chunks(filepath) true end |
#delete_session_with_chunks(json_filepath) ⇒ Object
Delete a session JSON file and all its associated chunk MD files.
128 129 130 131 132 |
# File 'lib/clacky/session_manager.rb', line 128 def delete_session_with_chunks(json_filepath) File.delete(json_filepath) if File.exist?(json_filepath) base = File.basename(json_filepath, ".json") Dir.glob(File.join(@sessions_dir, "#{base}-chunk-*.md")).each { |f| File.delete(f) } end |
#ensure_sessions_dir ⇒ Object
117 118 119 |
# File 'lib/clacky/session_manager.rb', line 117 def ensure_sessions_dir FileUtils.mkdir_p(@sessions_dir) unless Dir.exist?(@sessions_dir) end |
#generate_filename(session_id, created_at) ⇒ Object
121 122 123 124 125 |
# File 'lib/clacky/session_manager.rb', line 121 def generate_filename(session_id, created_at) datetime = Time.parse(created_at).strftime("%Y-%m-%d-%H-%M-%S") short_id = session_id[0..7] "#{datetime}-#{short_id}.json" end |
#last_saved_path ⇒ Object
Path of the last saved session file.
45 46 47 |
# File 'lib/clacky/session_manager.rb', line 45 def last_saved_path @last_saved_path end |
#latest_for_directory(working_dir) ⇒ Object
Return the most recent session for a given working directory, or nil.
84 85 86 |
# File 'lib/clacky/session_manager.rb', line 84 def latest_for_directory(working_dir) all_sessions(current_dir: working_dir).first end |
#load(session_id) ⇒ Object
Load a specific session by ID. Returns nil if not found.
50 51 52 |
# File 'lib/clacky/session_manager.rb', line 50 def load(session_id) all_sessions.find { |s| s[:session_id].to_s.start_with?(session_id.to_s) } end |
#load_session_file(filepath) ⇒ Object
134 135 136 137 138 |
# File 'lib/clacky/session_manager.rb', line 134 def load_session_file(filepath) JSON.parse(File.read(filepath), symbolize_names: true) rescue JSON::ParserError, Errno::ENOENT nil end |
#save(session_data) ⇒ Object
Save a session. Returns the file path.
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
# File 'lib/clacky/session_manager.rb', line 25 def save(session_data) filename = generate_filename(session_data[:session_id], session_data[:created_at]) filepath = File.join(@sessions_dir, filename) File.write(filepath, JSON.pretty_generate(session_data)) FileUtils.chmod(0o600, filepath) @last_saved_path = filepath # Keep only the most recent 200 sessions (best-effort, never block save) begin cleanup_by_count(keep: 200) rescue Exception # rubocop:disable Lint/RescueException # Cleanup is non-critical; swallow all errors (including AgentInterrupted) end filepath end |