Class: Ask::CodingProviders::ZCode::ZCodeDB
- Inherits:
-
Object
- Object
- Ask::CodingProviders::ZCode::ZCodeDB
- Defined in:
- lib/ask/coding_providers/zcode/zcode_db.rb
Overview
Wraps the ZCode SQLite database, centralizing all session/project queries.
Usage:
db = ZCodeDB.new
projects = db.list_projects
sessions = db.find_sessions(directory: "/path")
All methods return nil or empty arrays on error (never raise). This makes it safe to use from any context without wrapping every call.
Instance Method Summary collapse
- #available? ⇒ Boolean
-
#find_recent_session ⇒ Object
Find the single most recent session across all projects.
-
#find_recent_tui_session(workspace_path) ⇒ Object
Find the most recent TUI session in a workspace path.
-
#find_sessions(directory:, limit: 20) ⇒ Object
Find sessions in a given directory (exact or prefix match).
-
#initialize(db_path = nil) ⇒ ZCodeDB
constructor
A new instance of ZCodeDB.
-
#list_projects ⇒ Object
List all projects with session counts, ordered by most recently updated.
-
#recent_sessions ⇒ Object
List recent sessions across all projects.
-
#session_directory(session_id) ⇒ Object
Look up a session's workspace directory by its ID.
-
#session_history(session_id, limit: 100) ⇒ Object
Load the last N text parts from a session, newest first.
Constructor Details
#initialize(db_path = nil) ⇒ ZCodeDB
Returns a new instance of ZCodeDB.
18 19 20 |
# File 'lib/ask/coding_providers/zcode/zcode_db.rb', line 18 def initialize(db_path = nil) @db_path = db_path || File.("~/.zcode/cli/db/db.sqlite") end |
Instance Method Details
#available? ⇒ Boolean
22 23 24 |
# File 'lib/ask/coding_providers/zcode/zcode_db.rb', line 22 def available? File.exist?(@db_path) end |
#find_recent_session ⇒ Object
Find the single most recent session across all projects. Returns directory: or nil.
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
# File 'lib/ask/coding_providers/zcode/zcode_db.rb', line 70 def find_recent_session return nil unless available? db = open_db row = db.get_first_row(<<~SQL) SELECT id, directory FROM session WHERE time_archived IS NULL AND task_type = 'interactive' ORDER BY time_updated DESC LIMIT 1 SQL row ? { session_id: row["id"], directory: row["directory"] } : nil rescue => e nil ensure db&.close end |
#find_recent_tui_session(workspace_path) ⇒ Object
Find the most recent TUI session in a workspace path. Returns title:, directory: or nil.
88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 |
# File 'lib/ask/coding_providers/zcode/zcode_db.rb', line 88 def find_recent_tui_session(workspace_path) return nil unless available? db = open_db row = db.get_first_row(<<~SQL, [workspace_path, workspace_path]) SELECT id, title, directory FROM session WHERE (directory = ? OR ? LIKE directory || '/%') AND time_archived IS NULL AND task_type = 'interactive' ORDER BY time_updated DESC LIMIT 1 SQL row ? { session_id: row["id"], title: row["title"], directory: row["directory"] } : nil rescue => e nil ensure db&.close end |
#find_sessions(directory:, limit: 20) ⇒ Object
Find sessions in a given directory (exact or prefix match). Returns [title:, updated:] or [].
49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
# File 'lib/ask/coding_providers/zcode/zcode_db.rb', line 49 def find_sessions(directory:, limit: 20) return [] unless available? db = open_db rows = db.execute(<<~SQL, [directory, directory, limit]) SELECT id, title, time_updated FROM session WHERE (directory = ? OR ? LIKE directory || '/%') AND time_archived IS NULL AND task_type = 'interactive' ORDER BY time_updated DESC LIMIT ? SQL rows.map { |r| { session_id: r["id"], title: r["title"], updated: r["time_updated"] } } rescue => e [] ensure db&.close end |
#list_projects ⇒ Object
List all projects with session counts, ordered by most recently updated. Returns [directory:, session_count:] or [].
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
# File 'lib/ask/coding_providers/zcode/zcode_db.rb', line 28 def list_projects return [] unless available? db = open_db rows = db.execute(<<~SQL) SELECT project_id, directory, count(*) as session_count FROM session WHERE task_type = 'interactive' AND time_archived IS NULL GROUP BY project_id ORDER BY MAX(time_updated) DESC LIMIT 10 SQL rows.map { |r| { project_id: r["project_id"], directory: r["directory"], session_count: r["session_count"].to_i } } rescue => e nil ensure db&.close end |
#recent_sessions ⇒ Object
List recent sessions across all projects. Returns [title:, updated:, msg_count:] or [].
157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 |
# File 'lib/ask/coding_providers/zcode/zcode_db.rb', line 157 def recent_sessions return [] unless available? db = open_db rows = db.execute(<<~SQL) SELECT s.id AS session_id, s.title AS title, s.time_updated AS updated, (SELECT count(*) FROM message m WHERE m.session_id = s.id) AS msg_count FROM session s WHERE s.task_type = 'interactive' AND s.time_archived IS NULL ORDER BY s.time_updated DESC LIMIT 20 SQL rows.map do |r| { session_id: r["session_id"], title: r["title"], updated: r["updated"], msg_count: r["msg_count"].to_i } end rescue => e [] ensure db&.close end |
#session_directory(session_id) ⇒ Object
Look up a session's workspace directory by its ID. Returns the directory string, or nil.
109 110 111 112 113 114 115 116 117 118 119 |
# File 'lib/ask/coding_providers/zcode/zcode_db.rb', line 109 def session_directory(session_id) return nil unless available? db = open_db row = db.get_first_row("SELECT directory FROM session WHERE id = ?", [session_id]) row&.dig("directory") rescue => e nil ensure db&.close end |
#session_history(session_id, limit: 100) ⇒ Object
Load the last N text parts from a session, newest first. Returns [role:, origin:] or [].
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 149 150 151 152 153 |
# File 'lib/ask/coding_providers/zcode/zcode_db.rb', line 123 def session_history(session_id, limit: 100) return [] unless available? db = open_db rows = db.execute(<<~SQL, [session_id, limit]) SELECT p.data, m.data as msg_data FROM part p JOIN message m ON p.message_id = m.id WHERE p.session_id = ? AND p.data LIKE '%"type":"text"%' ORDER BY p.time_created DESC LIMIT ? SQL rows.filter_map do |r| part = JSON.parse(r["data"]) rescue next content = part["text"] || "" next if content.empty? msg_data = JSON.parse(r["msg_data"]) rescue {} role = msg_data["role"] == "user" ? "You" : "Agent" origin = msg_data.dig("semantics", "origin") rescue nil # Skip system-generated messages masquerading as user next if role == "You" && origin != "real_user" && origin != nil { text: content, role: role, origin: origin } end rescue => e [] ensure db&.close end |