Class: Rubino::CLI::Chat::SessionResolver
- Inherits:
-
Object
- Object
- Rubino::CLI::Chat::SessionResolver
- Defined in:
- lib/rubino/cli/chat/session_resolver.rb
Overview
Resolves which session a chat invocation runs against (–session / –resume / –continue / bare-chat auto-resume) and replays a resumed session’s history through the UI, extracted from ChatCommand (#17). Also owns the resume-facing one-liners (the auto-resume notice and the exit-time resume hint).
Instance Attribute Summary collapse
-
#auto_resumed_session ⇒ Object
readonly
The session a bare-‘chat` auto-resume / –continue picked, when one was found.
Instance Method Summary collapse
-
#initialize(options) ⇒ SessionResolver
constructor
A new instance of SessionResolver.
-
#print_auto_resume_line(ui, session) ⇒ Object
One-liner shown when a bare ‘chat` auto-resumed the last session (#99), so the continuation is never silent and the user knows how to opt out.
-
#print_resume_hint(ui, session) ⇒ Object
On exit, hand the user back the exact command to return to this chat.
-
#print_session_history(ui, session_id) ⇒ Object
— Session history replay (resume / continue) —.
-
#resolve_session_id(auto_resume: false) ⇒ Object
Resolves which session this invocation should run against.
-
#resuming_session? ⇒ Boolean
True when the chat was started against an existing session (–resume / –continue / explicit –session / bare-chat auto-resume): show its history rather than the first-run welcome panel.
Constructor Details
#initialize(options) ⇒ SessionResolver
Returns a new instance of SessionResolver.
15 16 17 |
# File 'lib/rubino/cli/chat/session_resolver.rb', line 15 def initialize() @options = end |
Instance Attribute Details
#auto_resumed_session ⇒ Object (readonly)
The session a bare-‘chat` auto-resume / –continue picked, when one was found. run_interactive gates the auto-resume notice on this.
21 22 23 |
# File 'lib/rubino/cli/chat/session_resolver.rb', line 21 def auto_resumed_session @auto_resumed_session end |
Instance Method Details
#print_auto_resume_line(ui, session) ⇒ Object
One-liner shown when a bare ‘chat` auto-resumed the last session (#99), so the continuation is never silent and the user knows how to opt out.
74 75 76 77 78 79 80 |
# File 'lib/rubino/cli/chat/session_resolver.rb', line 74 def print_auto_resume_line(ui, session) return unless session title = session[:title].to_s.strip label = title.empty? ? session[:id][0..7] : %("#{title}") ui.status("▸ resuming #{label} (#{session[:id][0..7]}) — /new for a fresh session") end |
#print_resume_hint(ui, session) ⇒ Object
On exit, hand the user back the exact command to return to this chat. Claude Code prints no equivalent hint; without this, the session id is buried in ~/.claude state and the user has to guess at –resume or scroll back through history. Prefer the human-friendly title when one is set; fall back to the id otherwise.
87 88 89 90 91 92 93 94 95 96 |
# File 'lib/rubino/cli/chat/session_resolver.rb', line 87 def print_resume_hint(ui, session) return unless session id = session[:id] title = session[:title] handle = title && !title.to_s.strip.empty? ? %("#{title}") : id return unless handle ui.info("Resume with: rubino chat --resume #{handle}") end |
#print_session_history(ui, session_id) ⇒ Object
— Session history replay (resume / continue) —
PromptAssembler feeds the past turns to the model on every request, but the inline REPL never printed them. On –resume the terminal looked empty even though the model had full context. Replay user, assistant and tool messages through the existing UI methods so the scrolled-back transcript matches what the user originally saw.
105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 |
# File 'lib/rubino/cli/chat/session_resolver.rb', line 105 def print_session_history(ui, session_id) return unless session_id = ::Rubino::Session::Store.new.for_session(session_id) return if .empty? ui.status("Loaded #{.size} prior message#{"s" if .size != 1}") ui.separator .each do |msg| at = (msg.created_at) case msg.role.to_s when "user" # A `!` bang command persisted its <bash-input>/<bash-stdout> # context messages as user rows; replay them as the `! <cmd>` # echo + dim output block, never the raw tags. next if BangShell.replay(ui, msg.content, at: at) ui.replay_user_input(msg.content, at: at) when "assistant" next if msg.content.nil? || msg.content.to_s.empty? # Render the prior assistant turn as markdown, same as a live reply — # not the old box (which the M2 redesign repurposed into a "● running" # tool-style row, so resume showed assistant turns as fake tool runs # with raw markdown). ui.assistant_text(msg.content) when "tool" name = msg.tool_name || "tool" arguments = msg..is_a?(Hash) ? msg.[:arguments] : nil ui.tool_started(name, arguments: arguments, at: at) ui.tool_finished( name, result: ::Rubino::Tools::Result.success( name: name, call_id: msg.tool_call_id, output: msg.content.to_s ) ) end end ui.separator end |
#resolve_session_id(auto_resume: false) ⇒ Object
Resolves which session this invocation should run against. auto_resume enables the bare-‘chat` auto-resume (#99) — only the interactive REPL opts in; one-shot (`-q`/scripted) keeps the old “fresh unless asked” behaviour so automation isn’t silently hijacked onto a past session.
27 28 29 30 31 32 33 34 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 |
# File 'lib/rubino/cli/chat/session_resolver.rb', line 27 def resolve_session_id(auto_resume: false) # Reap sessions orphaned by a hard kill (SIGKILL) or a closed terminal # whose SIGHUP never landed (#11): end any "active" row whose owning # process is gone before we resolve a resume target, so --continue / # auto-resume never treats a dead session as live. Session::Repository.new.reap_orphaned_active! id = opt(:session) return id if id resume = opt(:resume) || opt(:r) return resume if resume if opt(:continue) || opt(:c) # Explicit --continue/-c resumes the same session a bare `chat` # auto-resume would (#43): the latest RESUMABLE session (any status, # message_count > 0), not just an "active" one — otherwise a cleanly # ended prior session is invisible and -c silently forks a fresh one, # losing context. When there genuinely is none, tell the user instead # of silently starting over. @auto_resumed_session = Session::Repository.new.latest_resumable return @auto_resumed_session[:id] if @auto_resumed_session warn pastel.yellow("No previous session to continue — starting a new one.") return nil end # --new forces a brand-new session; otherwise a BARE interactive `chat` # auto-resumes the most recent resumable session so a user who closed # the terminal continues where they left off. nil ⇒ no prior session # (true first run) ⇒ fresh session + welcome panel. return nil if opt(:new) || !auto_resume @auto_resumed_session = Session::Repository.new.latest_resumable @auto_resumed_session&.dig(:id) end |
#resuming_session? ⇒ Boolean
True when the chat was started against an existing session (–resume / –continue / explicit –session / bare-chat auto-resume): show its history rather than the first-run welcome panel.
67 68 69 70 |
# File 'lib/rubino/cli/chat/session_resolver.rb', line 67 def resuming_session? !!(opt(:session) || opt(:resume) || opt(:r) || opt(:continue) || opt(:c) || @auto_resumed_session) end |