ragdoll-cli 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/README.md +296 -0
- data/Rakefile +21 -0
- data/bin/ragdoll +7 -0
- data/lib/ragdoll/cli/commands/config.rb +152 -0
- data/lib/ragdoll/cli/commands/delete.rb +37 -0
- data/lib/ragdoll/cli/commands/health.rb +22 -0
- data/lib/ragdoll/cli/commands/list.rb +57 -0
- data/lib/ragdoll/cli/commands/search.rb +88 -0
- data/lib/ragdoll/cli/commands/stats.rb +44 -0
- data/lib/ragdoll/cli/commands/status.rb +35 -0
- data/lib/ragdoll/cli/commands/update.rb +33 -0
- data/lib/ragdoll/cli/configuration_loader.rb +144 -0
- data/lib/ragdoll/cli/standalone_client.rb +69 -0
- data/lib/ragdoll/cli/version.rb +8 -0
- data/lib/ragdoll/cli.rb +380 -0
- data/lib/tasks/annotate.rake +126 -0
- data/lib/tasks/db.rake +338 -0
- metadata +62 -0
data/lib/tasks/db.rake
ADDED
@@ -0,0 +1,338 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rake"
|
4
|
+
|
5
|
+
namespace :db do
|
6
|
+
desc "Create the database"
|
7
|
+
task :create do
|
8
|
+
require_relative "../ragdoll-core"
|
9
|
+
|
10
|
+
config = Ragdoll::Core.configuration
|
11
|
+
puts "Creating database with config: #{config.database_config.inspect}"
|
12
|
+
|
13
|
+
case config.database_config[:adapter]
|
14
|
+
when "postgresql"
|
15
|
+
puts "PostgreSQL database setup - running as superuser to create database and role..."
|
16
|
+
|
17
|
+
# Connect as superuser to create database and role
|
18
|
+
ActiveRecord::Base.establish_connection(
|
19
|
+
adapter: 'postgresql',
|
20
|
+
database: 'postgres', # Connect to postgres database initially
|
21
|
+
username: ENV['POSTGRES_SUPERUSER'] || 'postgres',
|
22
|
+
password: ENV['POSTGRES_SUPERUSER_PASSWORD'],
|
23
|
+
host: config.database_config[:host] || 'localhost',
|
24
|
+
port: config.database_config[:port] || 5432
|
25
|
+
)
|
26
|
+
|
27
|
+
# Run individual SQL commands to avoid transaction block issues
|
28
|
+
begin
|
29
|
+
ActiveRecord::Base.connection.execute("DROP DATABASE IF EXISTS ragdoll_development")
|
30
|
+
rescue => e
|
31
|
+
puts "Note: #{e.message}" if e.message.include?("does not exist")
|
32
|
+
end
|
33
|
+
|
34
|
+
begin
|
35
|
+
ActiveRecord::Base.connection.execute("DROP ROLE IF EXISTS ragdoll")
|
36
|
+
rescue => e
|
37
|
+
puts "Note: #{e.message}" if e.message.include?("does not exist")
|
38
|
+
end
|
39
|
+
|
40
|
+
begin
|
41
|
+
ActiveRecord::Base.connection.execute("CREATE ROLE ragdoll WITH LOGIN CREATEDB")
|
42
|
+
rescue => e
|
43
|
+
puts "Note: Role already exists, continuing..." if e.message.include?("already exists")
|
44
|
+
end
|
45
|
+
|
46
|
+
begin
|
47
|
+
ActiveRecord::Base.connection.execute <<-SQL
|
48
|
+
CREATE DATABASE ragdoll_development
|
49
|
+
WITH OWNER = ragdoll
|
50
|
+
ENCODING = 'UTF8'
|
51
|
+
CONNECTION LIMIT = -1
|
52
|
+
SQL
|
53
|
+
rescue => e
|
54
|
+
puts "Note: Database already exists, continuing..." if e.message.include?("already exists")
|
55
|
+
end
|
56
|
+
|
57
|
+
ActiveRecord::Base.connection.execute("GRANT ALL PRIVILEGES ON DATABASE ragdoll_development TO ragdoll")
|
58
|
+
|
59
|
+
# Connect to the new database to set schema privileges
|
60
|
+
ActiveRecord::Base.establish_connection(
|
61
|
+
adapter: 'postgresql',
|
62
|
+
database: 'ragdoll_development',
|
63
|
+
username: ENV['POSTGRES_SUPERUSER'] || 'postgres',
|
64
|
+
password: ENV['POSTGRES_SUPERUSER_PASSWORD'],
|
65
|
+
host: config.database_config[:host] || 'localhost',
|
66
|
+
port: config.database_config[:port] || 5432
|
67
|
+
)
|
68
|
+
|
69
|
+
ActiveRecord::Base.connection.execute <<-SQL
|
70
|
+
-- Grant schema privileges (must be done while connected to the database)
|
71
|
+
GRANT ALL PRIVILEGES ON SCHEMA public TO ragdoll;
|
72
|
+
GRANT CREATE ON SCHEMA public TO ragdoll;
|
73
|
+
|
74
|
+
-- Set default privileges for future objects
|
75
|
+
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON TABLES TO ragdoll;
|
76
|
+
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON SEQUENCES TO ragdoll;
|
77
|
+
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON FUNCTIONS TO ragdoll;
|
78
|
+
|
79
|
+
-- Enable pgvector extension
|
80
|
+
CREATE EXTENSION IF NOT EXISTS vector;
|
81
|
+
SQL
|
82
|
+
|
83
|
+
puts "Database and role created successfully"
|
84
|
+
when "mysql2"
|
85
|
+
# For MySQL, we'd typically create the database here
|
86
|
+
puts "MySQL database creation - ensure the database exists on your server"
|
87
|
+
end
|
88
|
+
|
89
|
+
puts "Database creation completed"
|
90
|
+
end
|
91
|
+
|
92
|
+
desc "Drop the database"
|
93
|
+
task :drop do
|
94
|
+
require_relative "../ragdoll-core"
|
95
|
+
|
96
|
+
config = Ragdoll::Core.configuration
|
97
|
+
puts "Dropping database with config: #{config.database_config.inspect}"
|
98
|
+
|
99
|
+
case config.database_config[:adapter]
|
100
|
+
when "postgresql", "mysql2"
|
101
|
+
puts "For #{config.database_config[:adapter]}, please drop the database manually on your server"
|
102
|
+
end
|
103
|
+
|
104
|
+
puts "Database drop completed"
|
105
|
+
end
|
106
|
+
|
107
|
+
desc "Setup the database (create and migrate)"
|
108
|
+
task setup: %i[create migrate]
|
109
|
+
|
110
|
+
desc "Reset the database (drop, create, and migrate)"
|
111
|
+
task reset: %i[drop create migrate]
|
112
|
+
|
113
|
+
desc "Run pending migrations"
|
114
|
+
task :migrate do
|
115
|
+
require_relative "../ragdoll-core"
|
116
|
+
|
117
|
+
puts "Running migrations..."
|
118
|
+
Ragdoll::Core::Database.setup({
|
119
|
+
auto_migrate: false
|
120
|
+
})
|
121
|
+
|
122
|
+
Ragdoll::Core::Database.migrate!
|
123
|
+
puts "Migrations completed"
|
124
|
+
end
|
125
|
+
|
126
|
+
desc "Rollback the database by one migration"
|
127
|
+
task :rollback do
|
128
|
+
require_relative "../ragdoll-core"
|
129
|
+
|
130
|
+
puts "Rolling back migrations..."
|
131
|
+
# For now, we'll implement a simple reset since our manual migration doesn't support rollback
|
132
|
+
puts "Note: Rollback not yet implemented, use db:reset to start over"
|
133
|
+
end
|
134
|
+
|
135
|
+
desc "Show migration status"
|
136
|
+
task :migrate_status do
|
137
|
+
require_relative "../ragdoll-core"
|
138
|
+
|
139
|
+
Ragdoll::Core::Database.setup({
|
140
|
+
auto_migrate: false
|
141
|
+
})
|
142
|
+
|
143
|
+
puts "\nMigration Status:"
|
144
|
+
puts "=================="
|
145
|
+
|
146
|
+
# Get migration files
|
147
|
+
migration_paths = [File.join(File.dirname(__FILE__), "..", "..", "db", "migrate")]
|
148
|
+
migration_files = Dir[File.join(migration_paths.first, "*.rb")].sort
|
149
|
+
|
150
|
+
# Get applied migrations
|
151
|
+
applied_versions = []
|
152
|
+
if ActiveRecord::Base.connection.table_exists?("schema_migrations")
|
153
|
+
applied_versions = ActiveRecord::Base.connection.select_values(
|
154
|
+
"SELECT version FROM schema_migrations ORDER BY version"
|
155
|
+
)
|
156
|
+
end
|
157
|
+
|
158
|
+
puts format("%-8s %-20s %s", "Status", "Migration ID", "Migration Name")
|
159
|
+
puts "-" * 60
|
160
|
+
|
161
|
+
migration_files.each do |migration_file|
|
162
|
+
version = File.basename(migration_file, ".rb").split("_").first
|
163
|
+
name = File.basename(migration_file, ".rb").split("_")[1..].join("_")
|
164
|
+
status = applied_versions.include?(version) ? "up" : "down"
|
165
|
+
|
166
|
+
puts format("%-8s %-20s %s", status, version, name)
|
167
|
+
end
|
168
|
+
|
169
|
+
puts "\nTotal migrations: #{migration_files.length}"
|
170
|
+
puts "Applied migrations: #{applied_versions.length}"
|
171
|
+
puts "Pending migrations: #{migration_files.length - applied_versions.length}"
|
172
|
+
end
|
173
|
+
|
174
|
+
desc "Show database schema information"
|
175
|
+
task :schema do
|
176
|
+
require_relative "../ragdoll-core"
|
177
|
+
|
178
|
+
Ragdoll::Core::Database.setup({
|
179
|
+
auto_migrate: false
|
180
|
+
})
|
181
|
+
|
182
|
+
puts "\nDatabase Schema:"
|
183
|
+
puts "================"
|
184
|
+
puts "Adapter: #{ActiveRecord::Base.connection.adapter_name}"
|
185
|
+
|
186
|
+
if ActiveRecord::Base.connection.tables.any?
|
187
|
+
ActiveRecord::Base.connection.tables.sort.each do |table|
|
188
|
+
puts "\nTable: #{table}"
|
189
|
+
columns = ActiveRecord::Base.connection.columns(table)
|
190
|
+
columns.each do |column|
|
191
|
+
puts " #{column.name}: #{column.type} (#{column.sql_type})#{unless column.null
|
192
|
+
' NOT NULL'
|
193
|
+
end}#{if column.default
|
194
|
+
" DEFAULT #{column.default.inspect}"
|
195
|
+
end}"
|
196
|
+
end
|
197
|
+
|
198
|
+
# Show indexes
|
199
|
+
indexes = ActiveRecord::Base.connection.indexes(table)
|
200
|
+
next unless indexes.any?
|
201
|
+
|
202
|
+
puts " Indexes:"
|
203
|
+
indexes.each do |index|
|
204
|
+
unique_text = index.unique ? " (unique)" : ""
|
205
|
+
puts " #{index.name}: [#{index.columns.join(', ')}]#{unique_text}"
|
206
|
+
end
|
207
|
+
end
|
208
|
+
else
|
209
|
+
puts "No tables found. Run 'rake db:migrate' to create tables."
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
desc "Open database console"
|
214
|
+
task :console do
|
215
|
+
require_relative "../ragdoll-core"
|
216
|
+
|
217
|
+
config = Ragdoll::Core.configuration
|
218
|
+
|
219
|
+
case config.database_config[:adapter]
|
220
|
+
when "postgresql"
|
221
|
+
db_config = config.database_config
|
222
|
+
psql_cmd = "psql"
|
223
|
+
psql_cmd += " -h #{db_config[:host]}" if db_config[:host]
|
224
|
+
psql_cmd += " -p #{db_config[:port]}" if db_config[:port]
|
225
|
+
psql_cmd += " -U #{db_config[:username]}" if db_config[:username]
|
226
|
+
psql_cmd += " #{db_config[:database]}"
|
227
|
+
puts "Opening PostgreSQL console..."
|
228
|
+
system(psql_cmd)
|
229
|
+
when "mysql2"
|
230
|
+
db_config = config.database_config
|
231
|
+
mysql_cmd = "mysql"
|
232
|
+
mysql_cmd += " -h #{db_config[:host]}" if db_config[:host]
|
233
|
+
mysql_cmd += " -P #{db_config[:port]}" if db_config[:port]
|
234
|
+
mysql_cmd += " -u #{db_config[:username]}" if db_config[:username]
|
235
|
+
mysql_cmd += " -p" if db_config[:password]
|
236
|
+
mysql_cmd += " #{db_config[:database]}"
|
237
|
+
puts "Opening MySQL console..."
|
238
|
+
system(mysql_cmd)
|
239
|
+
else
|
240
|
+
puts "Console not supported for adapter: #{config.database_config[:adapter]}"
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
244
|
+
desc "Show database statistics"
|
245
|
+
task :stats do
|
246
|
+
require_relative "../ragdoll-core"
|
247
|
+
|
248
|
+
Ragdoll::Core::Database.setup({
|
249
|
+
auto_migrate: false
|
250
|
+
})
|
251
|
+
|
252
|
+
puts "\nDatabase Statistics:"
|
253
|
+
puts "==================="
|
254
|
+
|
255
|
+
if ActiveRecord::Base.connection.table_exists?("ragdoll_documents")
|
256
|
+
doc_count = ActiveRecord::Base.connection.select_value("SELECT COUNT(*) FROM ragdoll_documents")
|
257
|
+
puts "Documents: #{doc_count}"
|
258
|
+
|
259
|
+
if doc_count.positive?
|
260
|
+
doc_types = ActiveRecord::Base.connection.select_rows(
|
261
|
+
"SELECT document_type, COUNT(*) FROM ragdoll_documents GROUP BY document_type"
|
262
|
+
)
|
263
|
+
puts "Document types:"
|
264
|
+
doc_types.each { |type, count| puts " #{type}: #{count}" }
|
265
|
+
|
266
|
+
statuses = ActiveRecord::Base.connection.select_rows(
|
267
|
+
"SELECT status, COUNT(*) FROM ragdoll_documents GROUP BY status"
|
268
|
+
)
|
269
|
+
puts "Document statuses:"
|
270
|
+
statuses.each { |status, count| puts " #{status}: #{count}" }
|
271
|
+
end
|
272
|
+
else
|
273
|
+
puts "Documents table does not exist"
|
274
|
+
end
|
275
|
+
|
276
|
+
if ActiveRecord::Base.connection.table_exists?("ragdoll_embeddings")
|
277
|
+
embedding_count = ActiveRecord::Base.connection.select_value("SELECT COUNT(*) FROM ragdoll_embeddings")
|
278
|
+
puts "Embeddings: #{embedding_count}"
|
279
|
+
|
280
|
+
if embedding_count.positive?
|
281
|
+
models = ActiveRecord::Base.connection.select_rows(
|
282
|
+
"SELECT model_name, COUNT(*) FROM ragdoll_embeddings GROUP BY model_name"
|
283
|
+
)
|
284
|
+
puts "Embedding models:"
|
285
|
+
models.each { |model, count| puts " #{model}: #{count}" }
|
286
|
+
|
287
|
+
usage_stats = ActiveRecord::Base.connection.select_one(
|
288
|
+
"SELECT AVG(usage_count) as avg_usage, MAX(usage_count) as max_usage FROM ragdoll_embeddings"
|
289
|
+
)
|
290
|
+
puts "Usage statistics:"
|
291
|
+
puts " Average usage: #{usage_stats['avg_usage'].to_f.round(2)}"
|
292
|
+
puts " Max usage: #{usage_stats['max_usage']}"
|
293
|
+
end
|
294
|
+
else
|
295
|
+
puts "Embeddings table does not exist"
|
296
|
+
end
|
297
|
+
end
|
298
|
+
|
299
|
+
desc "Truncate all tables (remove all data but keep structure)"
|
300
|
+
task :truncate do
|
301
|
+
require_relative "../ragdoll-core"
|
302
|
+
|
303
|
+
Ragdoll::Core::Database.setup({
|
304
|
+
auto_migrate: false
|
305
|
+
})
|
306
|
+
|
307
|
+
puts "Truncating all tables..."
|
308
|
+
|
309
|
+
# Disable foreign key checks temporarily
|
310
|
+
case ActiveRecord::Base.connection.adapter_name.downcase
|
311
|
+
when "postgresql"
|
312
|
+
ActiveRecord::Base.connection.execute("SET session_replication_role = 'replica'")
|
313
|
+
when "mysql"
|
314
|
+
ActiveRecord::Base.connection.execute("SET FOREIGN_KEY_CHECKS = 0")
|
315
|
+
end
|
316
|
+
|
317
|
+
# Truncate tables in correct order (dependent tables first)
|
318
|
+
%w[ragdoll_embeddings ragdoll_documents].each do |table|
|
319
|
+
if ActiveRecord::Base.connection.table_exists?(table)
|
320
|
+
ActiveRecord::Base.connection.execute("DELETE FROM #{table}")
|
321
|
+
puts "Truncated #{table}"
|
322
|
+
end
|
323
|
+
end
|
324
|
+
|
325
|
+
# Re-enable foreign key checks
|
326
|
+
case ActiveRecord::Base.connection.adapter_name.downcase
|
327
|
+
when "postgresql"
|
328
|
+
ActiveRecord::Base.connection.execute("SET session_replication_role = 'origin'")
|
329
|
+
when "mysql"
|
330
|
+
ActiveRecord::Base.connection.execute("SET FOREIGN_KEY_CHECKS = 1")
|
331
|
+
end
|
332
|
+
|
333
|
+
puts "All tables truncated"
|
334
|
+
end
|
335
|
+
end
|
336
|
+
|
337
|
+
# Make db tasks available as top-level commands
|
338
|
+
task db: "db:migrate_status"
|
metadata
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ragdoll-cli
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Dewayne VanHoozer
|
8
|
+
bindir: bin
|
9
|
+
cert_chain: []
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
11
|
+
dependencies: []
|
12
|
+
description: Under development. Contributors welcome.
|
13
|
+
email:
|
14
|
+
- dvanhoozer@gmail.com
|
15
|
+
executables:
|
16
|
+
- ragdoll
|
17
|
+
extensions: []
|
18
|
+
extra_rdoc_files: []
|
19
|
+
files:
|
20
|
+
- README.md
|
21
|
+
- Rakefile
|
22
|
+
- bin/ragdoll
|
23
|
+
- lib/ragdoll/cli.rb
|
24
|
+
- lib/ragdoll/cli/commands/config.rb
|
25
|
+
- lib/ragdoll/cli/commands/delete.rb
|
26
|
+
- lib/ragdoll/cli/commands/health.rb
|
27
|
+
- lib/ragdoll/cli/commands/list.rb
|
28
|
+
- lib/ragdoll/cli/commands/search.rb
|
29
|
+
- lib/ragdoll/cli/commands/stats.rb
|
30
|
+
- lib/ragdoll/cli/commands/status.rb
|
31
|
+
- lib/ragdoll/cli/commands/update.rb
|
32
|
+
- lib/ragdoll/cli/configuration_loader.rb
|
33
|
+
- lib/ragdoll/cli/standalone_client.rb
|
34
|
+
- lib/ragdoll/cli/version.rb
|
35
|
+
- lib/tasks/annotate.rake
|
36
|
+
- lib/tasks/db.rake
|
37
|
+
homepage: https://github.com/MadBomber/ragdoll-cli
|
38
|
+
licenses:
|
39
|
+
- MIT
|
40
|
+
metadata:
|
41
|
+
allowed_push_host: https://rubygems.org
|
42
|
+
homepage_uri: https://github.com/MadBomber/ragdoll-cli
|
43
|
+
source_code_uri: https://github.com/MadBomber/ragdoll-cli/blob/main
|
44
|
+
changelog_uri: https://github.com/MadBomber/ragdoll-cli/blob/main/CHANGELOG.md
|
45
|
+
rdoc_options: []
|
46
|
+
require_paths:
|
47
|
+
- lib
|
48
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
49
|
+
requirements:
|
50
|
+
- - ">="
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: 3.2.0
|
53
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
54
|
+
requirements:
|
55
|
+
- - ">="
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
version: '0'
|
58
|
+
requirements: []
|
59
|
+
rubygems_version: 3.7.1
|
60
|
+
specification_version: 4
|
61
|
+
summary: Multi-Modal Retrieval Augmented Generation for the CLI
|
62
|
+
test_files: []
|