Class: PromptObjects::CLI::ExploreCommand

Inherits:
Object
  • Object
show all
Defined in:
lib/prompt_objects/cli/explore_command.rb

Overview

explore command: open the Thread Explorer visualizer in a browser.

Instance Method Summary collapse

Instance Method Details

#helpObject



94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
# File 'lib/prompt_objects/cli/explore_command.rb', line 94

def help
  prog = Helpers.program_name
  puts <<~HELP
    Usage: #{prog} explore [env] [options]

    Open the Thread Explorer to visualize conversation threads.

    Arguments:
      env                  Environment name or path (optional)

    Options:
      --session ID         Open a specific thread by session ID
      --help, -h           Show this help message

    Examples:
      #{prog} explore                          # Open empty explorer
      #{prog} explore my-env                   # Open most recent thread
      #{prog} explore my-env --session abc123  # Open specific thread
  HELP
end

#run(args) ⇒ Object



9
10
11
12
13
14
15
16
17
18
19
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
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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/prompt_objects/cli/explore_command.rb', line 9

def run(args)
  options = { session_id: nil }
  positional = []
  skip_next = false

  args.each_with_index do |arg, i|
    if skip_next
      skip_next = false
      next
    end

    case arg
    when "--session"
      options[:session_id] = args[i + 1]
      skip_next = true
    when "--help", "-h"
      help
      exit 0
    else
      positional << arg
    end
  end

  explorer_html = File.expand_path("../../../tools/thread-explorer.html", __dir__)

  # No args: just open the empty visualizer
  unless positional[0]
    Helpers.open_in_browser("file://#{explorer_html}")
    puts "Opened Thread Explorer in browser"
    exit 0
  end

  env_path = Helpers.resolve_environment(positional[0])
  unless env_path
    $stderr.puts "Error: environment '#{positional[0]}' not found"
    exit 1
  end

  db_path = File.join(env_path, "sessions.db")
  unless File.exist?(db_path)
    $stderr.puts "No session data found (sessions.db not found)"
    $stderr.puts "Opening empty Thread Explorer..."
    Helpers.open_in_browser("file://#{explorer_html}")
    exit 0
  end

  store = PromptObjects::Session::Store.new(db_path)

  if options[:session_id]
    # Export a specific thread
    export_and_open(store, options[:session_id], explorer_html)
  else
    # List sessions and let user choose, or export the most recent root thread
    # Query root sessions directly (list_sessions requires po_name)
    rows = store.instance_variable_get(:@db).execute(<<~SQL)
      SELECT * FROM sessions
      WHERE thread_type IS NULL OR thread_type = 'root'
      ORDER BY created_at ASC
    SQL
    root_sessions = rows.map { |r| { id: r["id"], po_name: r["po_name"], name: r["name"], thread_type: r["thread_type"], created_at: r["created_at"] } }

    if root_sessions.empty?
      $stderr.puts "No root sessions found"
      Helpers.open_in_browser("file://#{explorer_html}")
      exit 0
    end

    # Show available sessions
    puts "Root threads:"
    root_sessions.last(10).each_with_index do |s, i|
      name = s[:name] || "(unnamed)"
      po = s[:po_name] || "?"
      time = s[:created_at]
      time_str = time.is_a?(Time) ? time.strftime("%Y-%m-%d %H:%M") : time.to_s[0, 16]
      puts "  #{i + 1}. [#{po}] #{name}  (#{time_str})  #{s[:id]}"
    end

    puts
    puts "Opening most recent thread..."
    export_and_open(store, root_sessions.last[:id], explorer_html)
  end

  store.close
end