Class: Rubino::CLI::SessionCommand

Inherits:
Thor
  • Object
show all
Defined in:
lib/rubino/cli/session_command.rb

Overview

Subcommands for managing chat sessions

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.destroy_with_confirm(session, repo:, ui:, force: false) ⇒ Object

ONE confirm-and-destroy flow for both surfaces (#183): the CLI verb above and the in-chat ‘/sessions delete <id>`.



93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/rubino/cli/session_command.rb', line 93

def self.destroy_with_confirm(session, repo:, ui:, force: false)
  unless force
    confirmed = ui.confirm_destructive(
      "Delete session #{session[:id][0..7]} '#{session[:title] || "(untitled)"}'? " \
      "This will also remove its messages, events, and tool calls."
    )
    unless confirmed
      ui.info("Aborted.")
      return
    end
  end

  repo.destroy!(session[:id])
  ui.success("Deleted session #{session[:id][0..7]}.")
end

.exit_on_failure?Boolean

Returns:

  • (Boolean)


12
13
14
# File 'lib/rubino/cli/session_command.rb', line 12

def self.exit_on_failure?
  true
end

.render(session, ui:) ⇒ Object

ONE session-details rendering for both surfaces (#183): the CLI verb above and the in-chat ‘/sessions show <id>` (Commands::Executor).



62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/rubino/cli/session_command.rb', line 62

def self.render(session, ui:)
  ui.info("Session: #{session[:id]}")
  ui.info("Title: #{session[:title] || "(untitled)"}")
  ui.info("Status: #{session[:status]}")
  ui.info("Model: #{session[:model]}")
  ui.info("Messages: #{session[:message_count]}")
  ui.info("Tokens: #{session[:token_count]}")
  ui.info("Created: #{session[:created_at]}")
  ui.info("Updated: #{session[:updated_at]}")

  return unless session[:parent_session_id]

  ui.info("Parent: #{session[:parent_session_id]}")
end

Instance Method Details

#compact(id) ⇒ Object

Raises:

  • (Thor::Error)


110
111
112
113
114
115
116
117
118
119
120
121
122
# File 'lib/rubino/cli/session_command.rb', line 110

def compact(id)
  Rubino.ensure_database_ready!
  repo = Session::Repository.new
  session = repo.find(id)

  # Single-styled not-found error (#20), as in #show above.
  raise Thor::Error, "session not found: #{id}" if session.nil?

  Rubino.ui.info("Compacting session #{id}...")
  compressor = Context::Compressor.new(session_id: id)
  result = compressor.compact!
  Rubino.ui.compression_finished(result)
end

#delete(id) ⇒ Object

Raises:

  • (Thor::Error)


80
81
82
83
84
85
86
87
88
89
# File 'lib/rubino/cli/session_command.rb', line 80

def delete(id)
  Rubino.ensure_database_ready!
  repo = Session::Repository.new
  session = repo.find(id)

  # Single-styled not-found error (#20), as in #show above.
  raise Thor::Error, "session not found: #{id}" if session.nil?

  self.class.destroy_with_confirm(session, repo: repo, ui: Rubino.ui, force: options[:force])
end

#listObject



20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# File 'lib/rubino/cli/session_command.rb', line 20

def list
  Rubino.ensure_database_ready!
  repo = Session::Repository.new
  # Reap sessions left "active" by a process that died without ending them
  # (hard terminal kill / SIGKILL, #11) so the list never shows a stale
  # "active" for a window that is actually gone.
  repo.reap_orphaned_active!
  sessions = repo.list(limit: options[:limit], status: options[:status],
                       search: options[:search])

  if sessions.empty?
    Rubino.ui.info("No sessions found.")
    return
  end

  rows = sessions.map do |s|
    [s[:id][0..7], s[:title] || "(untitled)", s[:status],
     s[:message_count].to_s, s[:created_at]]
  end

  Rubino.ui.table(
    headers: %w[ID Title Status Messages Created],
    rows: rows
  )
end

#show(id) ⇒ Object

Raises:

  • (Thor::Error)


47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/rubino/cli/session_command.rb', line 47

def show(id)
  Rubino.ensure_database_ready!
  repo = Session::Repository.new
  session = repo.find(id)

  # One error, one style (#20): Thor already prints the Thor::Error message
  # to stderr and exits non-zero (exit_on_failure?), so the extra styled
  # ui.error line was the same failure repeated in a second format.
  raise Thor::Error, "session not found: #{id}" if session.nil?

  self.class.render(session, ui: Rubino.ui)
end