Class: Kreator::SessionManager
- Inherits:
-
Object
- Object
- Kreator::SessionManager
- Defined in:
- lib/kreator/session_manager.rb
Constant Summary collapse
- DEFAULT_SESSION_DIR =
File.("~/.kreator/sessions")
Instance Attribute Summary collapse
-
#session_dir ⇒ Object
readonly
Returns the value of attribute session_dir.
Instance Method Summary collapse
- #branches(parent_id:) ⇒ Object
- #cleanup(cwd: nil, empty: false, failed: false) ⇒ Object
- #continue_recent(cwd:) ⇒ Object
- #create(cwd:, parent_id: nil, parent_path: nil, forked_entry_index: nil) ⇒ Object
- #export(path:, format: "json") ⇒ Object
- #fork(path:, entry_index: nil) ⇒ Object
-
#initialize(session_dir: DEFAULT_SESSION_DIR) ⇒ SessionManager
constructor
A new instance of SessionManager.
- #label(path:, label:) ⇒ Object
- #list(cwd:) ⇒ Object
- #open(path:) ⇒ Object
- #search(query:, cwd: nil) ⇒ Object
- #transcript(path:, format: "markdown") ⇒ Object
Constructor Details
#initialize(session_dir: DEFAULT_SESSION_DIR) ⇒ SessionManager
Returns a new instance of SessionManager.
14 15 16 |
# File 'lib/kreator/session_manager.rb', line 14 def initialize(session_dir: DEFAULT_SESSION_DIR) @session_dir = File.(session_dir) end |
Instance Attribute Details
#session_dir ⇒ Object (readonly)
Returns the value of attribute session_dir.
12 13 14 |
# File 'lib/kreator/session_manager.rb', line 12 def session_dir @session_dir end |
Instance Method Details
#branches(parent_id:) ⇒ Object
81 82 83 84 85 86 87 |
# File 'lib/kreator/session_manager.rb', line 81 def branches(parent_id:) matching_branches = Dir.glob(File.join(session_dir, "*", "*.jsonl")).filter_map do |path| summary = session_summary(path) summary if summary && summary["parent_id"] == parent_id end matching_branches.sort_by { |summary| summary.fetch("timestamp") }.reverse end |
#cleanup(cwd: nil, empty: false, failed: false) ⇒ Object
145 146 147 148 149 150 151 152 153 154 155 156 157 |
# File 'lib/kreator/session_manager.rb', line 145 def cleanup(cwd: nil, empty: false, failed: false) raise ArgumentError, "cleanup requires empty: true or failed: true" unless empty || failed deleted = [] summaries_in(cleanup_pattern(cwd)).each do |summary| session = self.open(path: summary.fetch("path")) next unless cleanup_session?(session, empty: empty, failed: failed) FileUtils.rm_f(session.path) deleted << summary end deleted end |
#continue_recent(cwd:) ⇒ Object
49 50 51 52 53 54 |
# File 'lib/kreator/session_manager.rb', line 49 def continue_recent(cwd:) sessions = list(cwd: cwd) raise ArgumentError, "no sessions found for #{File.(cwd)}" if sessions.empty? self.open(path: sessions.first.fetch("path")) end |
#create(cwd:, parent_id: nil, parent_path: nil, forked_entry_index: nil) ⇒ Object
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
# File 'lib/kreator/session_manager.rb', line 18 def create(cwd:, parent_id: nil, parent_path: nil, forked_entry_index: nil) cwd = File.(cwd) id = SecureRandom.uuid = Time.now.utc.iso8601(6) directory = directory_for(cwd) FileUtils.mkdir_p(directory) path = File.join(directory, "#{.tr(':', '-')}_#{id}.jsonl") header = { "type" => "session_header", "version" => Session::VERSION, "id" => id, "timestamp" => , "cwd" => cwd }.compact header["parent_id"] = parent_id if parent_id header["parent_path"] = parent_path if parent_path header["forked_entry_index"] = forked_entry_index unless forked_entry_index.nil? File.write(path, "#{JSON.generate(header)}\n") Session.new(path: path, header: header) end |
#export(path:, format: "json") ⇒ Object
112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 |
# File 'lib/kreator/session_manager.rb', line 112 def export(path:, format: "json") session = self.open(path: path) case format.to_s when "json" JSON.pretty_generate( "header" => session.header, "entries" => session.entries ) when "jsonl" File.read(session.path) when "markdown", "md" transcript(path: session.path, format: "markdown") when "plain", "text" transcript(path: session.path, format: "plain") else raise ArgumentError, "unknown export format: #{format}" end end |
#fork(path:, entry_index: nil) ⇒ Object
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 |
# File 'lib/kreator/session_manager.rb', line 63 def fork(path:, entry_index: nil) source = self.open(path: path) source_entries = source.entries resolved_index = entry_index.nil? ? source_entries.length - 1 : Integer(entry_index) raise ArgumentError, "cannot fork an empty session" if resolved_index.negative? raise ArgumentError, "entry index out of range: #{resolved_index}" if resolved_index >= source_entries.length forked = create( cwd: source.cwd, parent_id: source.id, parent_path: source.path, forked_entry_index: resolved_index ) forked.append_parent_id(parent_id: source.id, parent_path: source.path, forked_entry_index: resolved_index) forked.append_entries(source_entries.first(resolved_index + 1)) forked end |
#label(path:, label:) ⇒ Object
89 90 91 92 93 |
# File 'lib/kreator/session_manager.rb', line 89 def label(path:, label:) session = self.open(path: path) session.append_label(label) session end |
#list(cwd:) ⇒ Object
56 57 58 59 60 61 |
# File 'lib/kreator/session_manager.rb', line 56 def list(cwd:) directory = directory_for(File.(cwd)) return [] unless Dir.exist?(directory) summaries_in(File.join(directory, "*.jsonl")) end |
#open(path:) ⇒ Object
39 40 41 42 43 44 45 46 47 |
# File 'lib/kreator/session_manager.rb', line 39 def open(path:) resolved = resolve_path(path) raise ArgumentError, "session not found: #{path}" unless resolved && File.file?(resolved) header = JSON.parse(File.open(resolved, &:readline)) raise ArgumentError, "invalid session header in #{resolved}" unless header.fetch("type") == "session_header" Session.new(path: resolved, header: header) end |
#search(query:, cwd: nil) ⇒ Object
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
# File 'lib/kreator/session_manager.rb', line 95 def search(query:, cwd: nil) query = query.to_s.downcase pattern = cwd ? File.join(directory_for(File.(cwd)), "*.jsonl") : File.join(session_dir, "*", "*.jsonl") summaries_in(pattern).select do |summary| searchable = [ summary["id"], summary["cwd"], summary["timestamp"], summary["provider"], summary["model"], *Array(summary["labels"]), transcript(path: summary.fetch("path"), format: "plain") ].compact.join("\n").downcase searchable.include?(query) end end |
#transcript(path:, format: "markdown") ⇒ Object
131 132 133 134 135 136 137 138 139 140 141 142 143 |
# File 'lib/kreator/session_manager.rb', line 131 def transcript(path:, format: "markdown") session = self.open(path: path) session..map do || case format.to_s when "markdown", "md" transcript_markdown() when "plain", "text" transcript_plain() else raise ArgumentError, "unknown transcript format: #{format}" end end.join("\n\n") end |