rails_agent_console 0.1.0
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/CHANGELOG.md +80 -0
- data/LICENSE.txt +21 -0
- data/README.md +414 -0
- data/exe/rails-agent +7 -0
- data/lib/generators/rails_agent_console/install_generator.rb +17 -0
- data/lib/generators/rails_agent_console/templates/rails_agent_console.rb +21 -0
- data/lib/rails_agent_console/agent.rb +277 -0
- data/lib/rails_agent_console/cli.rb +114 -0
- data/lib/rails_agent_console/configuration.rb +170 -0
- data/lib/rails_agent_console/console_installer.rb +49 -0
- data/lib/rails_agent_console/console_methods.rb +54 -0
- data/lib/rails_agent_console/console_session.rb +41 -0
- data/lib/rails_agent_console/credentials.rb +66 -0
- data/lib/rails_agent_console/diagnosis/extra.rb +72 -0
- data/lib/rails_agent_console/diagnosis.rb +149 -0
- data/lib/rails_agent_console/errors.rb +20 -0
- data/lib/rails_agent_console/executor.rb +190 -0
- data/lib/rails_agent_console/history.rb +65 -0
- data/lib/rails_agent_console/model_picker.rb +166 -0
- data/lib/rails_agent_console/prompt/dates.rb +34 -0
- data/lib/rails_agent_console/prompt/follow_up.rb +38 -0
- data/lib/rails_agent_console/prompt.rb +122 -0
- data/lib/rails_agent_console/proposal.rb +208 -0
- data/lib/rails_agent_console/providers/anthropic.rb +48 -0
- data/lib/rails_agent_console/providers/base.rb +114 -0
- data/lib/rails_agent_console/providers/callable.rb +28 -0
- data/lib/rails_agent_console/providers/gemini.rb +45 -0
- data/lib/rails_agent_console/providers/ollama.rb +84 -0
- data/lib/rails_agent_console/providers/openai.rb +51 -0
- data/lib/rails_agent_console/providers.rb +28 -0
- data/lib/rails_agent_console/query_validator/model_suggestion.rb +35 -0
- data/lib/rails_agent_console/query_validator/parse_error.rb +23 -0
- data/lib/rails_agent_console/query_validator/result.rb +55 -0
- data/lib/rails_agent_console/query_validator/rules.rb +108 -0
- data/lib/rails_agent_console/query_validator/sensitive_columns.rb +22 -0
- data/lib/rails_agent_console/query_validator.rb +305 -0
- data/lib/rails_agent_console/railtie.rb +26 -0
- data/lib/rails_agent_console/rewriter/arguments.rb +192 -0
- data/lib/rails_agent_console/rewriter/chain.rb +126 -0
- data/lib/rails_agent_console/rewriter/date_ranges.rb +21 -0
- data/lib/rails_agent_console/rewriter/distinct.rb +41 -0
- data/lib/rails_agent_console/rewriter/joined.rb +42 -0
- data/lib/rails_agent_console/rewriter/qualifier.rb +116 -0
- data/lib/rails_agent_console/rewriter/quotes.rb +29 -0
- data/lib/rails_agent_console/rewriter/sql_repair.rb +114 -0
- data/lib/rails_agent_console/rewriter.rb +183 -0
- data/lib/rails_agent_console/schema.rb +275 -0
- data/lib/rails_agent_console/setup.rb +40 -0
- data/lib/rails_agent_console/ui.rb +125 -0
- data/lib/rails_agent_console/value_check.rb +85 -0
- data/lib/rails_agent_console/version.rb +5 -0
- data/lib/rails_agent_console/wizard.rb +235 -0
- data/lib/rails_agent_console.rb +58 -0
- metadata +145 -0
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RailsAgentConsole
|
|
4
|
+
class Wizard
|
|
5
|
+
PLACES = [
|
|
6
|
+
[:local, "On this machine, with Ollama. Nothing leaves your laptop, no key needed."],
|
|
7
|
+
[:hosted, "A hosted API: OpenAI, Anthropic or Gemini."],
|
|
8
|
+
[:custom, "My own OpenAI-compatible endpoint: OpenRouter, LM Studio, vLLM, a company gateway."]
|
|
9
|
+
].freeze
|
|
10
|
+
HOSTED = %i[openai anthropic gemini].freeze
|
|
11
|
+
LISTED = 15
|
|
12
|
+
|
|
13
|
+
def self.run(config: RailsAgentConsole.configuration, ui: UI.new(config))
|
|
14
|
+
new(config, ui).run
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def initialize(config, ui)
|
|
18
|
+
@config = config
|
|
19
|
+
@ui = ui
|
|
20
|
+
@before = config.snapshot
|
|
21
|
+
@typed_key = nil
|
|
22
|
+
@step = 0
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def run
|
|
26
|
+
place = choose_place
|
|
27
|
+
provider = place == :hosted ? choose_hosted : { local: :ollama, custom: :openai }[place]
|
|
28
|
+
return abandon("Unknown choice.") if provider.nil?
|
|
29
|
+
|
|
30
|
+
use(provider)
|
|
31
|
+
choose_base_url(place)
|
|
32
|
+
return abandon("No key entered, nothing changed.") unless key_ready?
|
|
33
|
+
|
|
34
|
+
@config.model = choose_model
|
|
35
|
+
return abandon("Nothing changed.") unless answers?
|
|
36
|
+
|
|
37
|
+
RailsAgentConsole.agent.reset_provider!
|
|
38
|
+
@ui.success "Now using #{label}."
|
|
39
|
+
offer_to_save
|
|
40
|
+
true
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
private
|
|
44
|
+
|
|
45
|
+
def step(title)
|
|
46
|
+
@step += 1
|
|
47
|
+
@ui.blank
|
|
48
|
+
@ui.say @ui.bold("#{@step}. #{title}")
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def choose_place
|
|
52
|
+
step "Where should the model run?"
|
|
53
|
+
current = current_place
|
|
54
|
+
PLACES.each_with_index do |(name, text), index|
|
|
55
|
+
@ui.say " #{index + 1}. #{text}#{@ui.dim(" (now)") if name == current}"
|
|
56
|
+
end
|
|
57
|
+
answer = @ui.ask(">", default: (PLACES.index { |name, _| name == current } + 1).to_s)
|
|
58
|
+
PLACES.dig(answer.to_i - 1, 0) || PLACES.find { |name, _| name.to_s == answer.downcase }&.first
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def current_place
|
|
62
|
+
return :local if @config.provider == :ollama
|
|
63
|
+
return :custom if @config.provider == :openai && @config.api_base && @config.api_base != default_base(:openai)
|
|
64
|
+
|
|
65
|
+
:hosted
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def choose_hosted
|
|
69
|
+
step "Which provider?"
|
|
70
|
+
HOSTED.each_with_index do |name, index|
|
|
71
|
+
@ui.say " #{index + 1}. #{Setup::PROVIDER_LABELS[name].ljust(10)} #{@ui.dim(key_source(name))}"
|
|
72
|
+
end
|
|
73
|
+
default = HOSTED.index(@config.provider) || 0
|
|
74
|
+
answer = @ui.ask(">", default: (default + 1).to_s)
|
|
75
|
+
return HOSTED[answer.to_i - 1] if answer.to_i.between?(1, HOSTED.size)
|
|
76
|
+
|
|
77
|
+
HOSTED.find { |name| name.to_s == answer.downcase }
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def use(provider)
|
|
81
|
+
same = provider == @before[:provider]
|
|
82
|
+
@config.provider = provider
|
|
83
|
+
@config.api_key = @before[:api_key] if same && @before[:api_key]
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def choose_base_url(place)
|
|
87
|
+
step "Base URL"
|
|
88
|
+
stored = Credentials.read.dig(@config.provider.to_s, "base_url")
|
|
89
|
+
default = place == :custom ? stored : stored || default_base(@config.provider)
|
|
90
|
+
@ui.note " Where the requests go. Enter keeps it." unless default.to_s.empty?
|
|
91
|
+
@ui.note " The part before /chat/completions, e.g. https://openrouter.ai/api/v1" if place == :custom
|
|
92
|
+
answer = @ui.ask(default.to_s.empty? ? "Base URL:" : "Base URL [#{default}]:", default: default).to_s
|
|
93
|
+
@config.api_base = answer.chomp("/") == default_base(@config.provider) ? nil : answer.chomp("/")
|
|
94
|
+
check_ollama if @config.provider == :ollama
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def check_ollama
|
|
98
|
+
found = provider.models
|
|
99
|
+
if found.any?
|
|
100
|
+
return @ui.success "Ollama answers on #{base}, #{found.size} #{found.one? ? "model" : "models"} installed."
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
@ui.warn "Nothing answered on #{base}. Start Ollama with `ollama serve`, then carry on."
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def key_ready?
|
|
107
|
+
return true if @config.provider == :ollama
|
|
108
|
+
|
|
109
|
+
step "API key"
|
|
110
|
+
source = existing_key
|
|
111
|
+
@ui.success "Using #{source}." if source
|
|
112
|
+
source ? true : typed_key?
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def existing_key
|
|
116
|
+
env = Configuration::ENV_KEYS[@config.provider]
|
|
117
|
+
return env_key_choice(env) if env_key? && @config.api_base.nil?
|
|
118
|
+
|
|
119
|
+
"the key already set for #{@config.provider}" if @config.api_key && !replace_key?
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def env_key_choice(env)
|
|
123
|
+
@ui.say " Found a key in #{env}."
|
|
124
|
+
return "the key from #{env}" if @ui.yes?("Use it?", default: true)
|
|
125
|
+
|
|
126
|
+
@ui.note " The key you type is used from now on in this console. #{env} is still set, so a new " \
|
|
127
|
+
"session goes back to it unless you unset it or change it where it is defined (.env, shell profile)."
|
|
128
|
+
nil
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def replace_key?
|
|
132
|
+
@ui.yes?("A key is already set for #{@config.provider}. Type a different one?", default: false)
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def typed_key?
|
|
136
|
+
skip = env_key? ? "" : " Set #{Configuration::ENV_KEYS[@config.provider]} to skip this step."
|
|
137
|
+
@ui.note " Not echoed, and never written into the application.#{skip}"
|
|
138
|
+
key = @ui.secret("#{Setup::PROVIDER_LABELS[@config.provider]} API key:")
|
|
139
|
+
return false if key.empty?
|
|
140
|
+
|
|
141
|
+
@typed_key = @config.api_key = key
|
|
142
|
+
true
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
def choose_model
|
|
146
|
+
step "Model"
|
|
147
|
+
found = provider.models
|
|
148
|
+
default = default_model(found)
|
|
149
|
+
return ask_any_model(default) if found.empty?
|
|
150
|
+
|
|
151
|
+
shown = (([default] & found) + (found - [default])).first(LISTED)
|
|
152
|
+
shown.each_with_index { |name, index| @ui.say " #{index + 1}. #{name}" }
|
|
153
|
+
@ui.note " ...and #{found.size - LISTED} more; type any name." if found.size > LISTED
|
|
154
|
+
numbered(shown, @ui.ask("Number or name [#{default}]:", default: default))
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def numbered(shown, answer)
|
|
158
|
+
answer.match?(/\A\d+\z/) && answer.to_i.between?(1, shown.size) ? shown[answer.to_i - 1] : answer
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
def ask_any_model(default)
|
|
162
|
+
@ui.note " Could not list the models here, so type the name the API expects."
|
|
163
|
+
@ui.note " For Ollama, get one first with `ollama pull #{default}`." if @config.provider == :ollama
|
|
164
|
+
@ui.ask("Model [#{default}]:", default: default)
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
def default_model(found)
|
|
168
|
+
current = @before[:provider] == @config.provider ? @before[:model] : nil
|
|
169
|
+
preferred = [current, Credentials.read.dig(@config.provider.to_s, "model"),
|
|
170
|
+
Configuration::DEFAULT_MODELS[@config.provider]].compact
|
|
171
|
+
return preferred.first if found.empty?
|
|
172
|
+
|
|
173
|
+
preferred.find { |name| found.include?(name) } ||
|
|
174
|
+
found.find { |name| name.start_with?(Providers::Ollama::RECOMMENDED) } ||
|
|
175
|
+
found.find { |name| name.include?("coder") } || found.first
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
def answers?
|
|
179
|
+
@ui.blank
|
|
180
|
+
@ui.say "Checking #{label}..."
|
|
181
|
+
started = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
182
|
+
provider.chat(system: "You are a health check. Answer with the single word: ok",
|
|
183
|
+
messages: [{ role: "user", content: "ping" }])
|
|
184
|
+
@ui.success format("It answered in %.1fs.", Process.clock_gettime(Process::CLOCK_MONOTONIC) - started)
|
|
185
|
+
true
|
|
186
|
+
rescue Error => e
|
|
187
|
+
@ui.failure e.message
|
|
188
|
+
@ui.yes?("Keep #{label} anyway?", default: false)
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
def offer_to_save
|
|
192
|
+
return unless @ui.yes?("Make it the default in #{Credentials.path}?", default: true)
|
|
193
|
+
|
|
194
|
+
path = Credentials.store(provider: @config.provider, api_key: @typed_key, model: @config.model,
|
|
195
|
+
base_url: @config.api_base.to_s)
|
|
196
|
+
@ui.success "Saved to #{path} (chmod 600)."
|
|
197
|
+
rescue StandardError => e
|
|
198
|
+
@ui.failure "Could not write #{Credentials.path}: #{e.message}"
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
def abandon(message)
|
|
202
|
+
@config.restore(@before)
|
|
203
|
+
@ui.failure(@config.api_key? ? "#{message} Still on #{label}." : message)
|
|
204
|
+
nil
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
def provider
|
|
208
|
+
Providers::REGISTRY.fetch(@config.provider).new(@config)
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
def default_base(name)
|
|
212
|
+
Providers::REGISTRY.fetch(name)::DEFAULT_BASE
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
def base
|
|
216
|
+
@config.api_base || default_base(@config.provider)
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
def env_key?
|
|
220
|
+
!ENV.fetch(Configuration::ENV_KEYS[@config.provider], "").strip.empty?
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
def key_source(name)
|
|
224
|
+
env = Configuration::ENV_KEYS[name]
|
|
225
|
+
return "key from #{env}" unless ENV.fetch(env, "").strip.empty?
|
|
226
|
+
return "key stored in #{Credentials.path}" if Credentials.read.dig(name.to_s, "api_key").to_s.strip != ""
|
|
227
|
+
|
|
228
|
+
"no key yet"
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
def label
|
|
232
|
+
"#{@config.provider}/#{@config.model}"
|
|
233
|
+
end
|
|
234
|
+
end
|
|
235
|
+
end
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "rails_agent_console/version"
|
|
4
|
+
require_relative "rails_agent_console/errors"
|
|
5
|
+
require_relative "rails_agent_console/configuration"
|
|
6
|
+
require_relative "rails_agent_console/credentials"
|
|
7
|
+
require_relative "rails_agent_console/ui"
|
|
8
|
+
require_relative "rails_agent_console/schema"
|
|
9
|
+
require_relative "rails_agent_console/prompt"
|
|
10
|
+
require_relative "rails_agent_console/query_validator"
|
|
11
|
+
require_relative "rails_agent_console/executor"
|
|
12
|
+
require_relative "rails_agent_console/value_check"
|
|
13
|
+
require_relative "rails_agent_console/diagnosis"
|
|
14
|
+
require_relative "rails_agent_console/history"
|
|
15
|
+
require_relative "rails_agent_console/rewriter"
|
|
16
|
+
require_relative "rails_agent_console/proposal"
|
|
17
|
+
require_relative "rails_agent_console/providers"
|
|
18
|
+
require_relative "rails_agent_console/agent"
|
|
19
|
+
require_relative "rails_agent_console/wizard"
|
|
20
|
+
require_relative "rails_agent_console/setup"
|
|
21
|
+
require_relative "rails_agent_console/model_picker"
|
|
22
|
+
require_relative "rails_agent_console/console_methods"
|
|
23
|
+
|
|
24
|
+
# Usage:
|
|
25
|
+
# ai "How many users registered this month?" # propose + confirm + run
|
|
26
|
+
# ask "Why is User.includes(:orders) faster?" # explain only, never runs
|
|
27
|
+
# explain User.where(active: true) # explain an existing query
|
|
28
|
+
module RailsAgentConsole
|
|
29
|
+
class << self
|
|
30
|
+
def configuration
|
|
31
|
+
@configuration ||= Configuration.new
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def configure
|
|
35
|
+
yield configuration if block_given?
|
|
36
|
+
configuration
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
alias config configuration
|
|
40
|
+
|
|
41
|
+
def agent
|
|
42
|
+
@agent ||= Agent.new
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def history
|
|
46
|
+
agent.history
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def reset!
|
|
50
|
+
@configuration = nil
|
|
51
|
+
@agent = nil
|
|
52
|
+
Schema.reset!
|
|
53
|
+
self
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
require_relative "rails_agent_console/railtie" if defined?(Rails::Railtie)
|
metadata
ADDED
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: rails_agent_console
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Ivan Blažević
|
|
8
|
+
bindir: exe
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 2026-09-29 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: activerecord
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - ">="
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '7.0'
|
|
19
|
+
- - "<"
|
|
20
|
+
- !ruby/object:Gem::Version
|
|
21
|
+
version: '9'
|
|
22
|
+
type: :runtime
|
|
23
|
+
prerelease: false
|
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
25
|
+
requirements:
|
|
26
|
+
- - ">="
|
|
27
|
+
- !ruby/object:Gem::Version
|
|
28
|
+
version: '7.0'
|
|
29
|
+
- - "<"
|
|
30
|
+
- !ruby/object:Gem::Version
|
|
31
|
+
version: '9'
|
|
32
|
+
- !ruby/object:Gem::Dependency
|
|
33
|
+
name: railties
|
|
34
|
+
requirement: !ruby/object:Gem::Requirement
|
|
35
|
+
requirements:
|
|
36
|
+
- - ">="
|
|
37
|
+
- !ruby/object:Gem::Version
|
|
38
|
+
version: '7.0'
|
|
39
|
+
- - "<"
|
|
40
|
+
- !ruby/object:Gem::Version
|
|
41
|
+
version: '9'
|
|
42
|
+
type: :runtime
|
|
43
|
+
prerelease: false
|
|
44
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
45
|
+
requirements:
|
|
46
|
+
- - ">="
|
|
47
|
+
- !ruby/object:Gem::Version
|
|
48
|
+
version: '7.0'
|
|
49
|
+
- - "<"
|
|
50
|
+
- !ruby/object:Gem::Version
|
|
51
|
+
version: '9'
|
|
52
|
+
description: |
|
|
53
|
+
rails_agent_console adds `ai`, `ai!`, `ask` and `explain` to the Rails console you already use.
|
|
54
|
+
It describes your real schema (models, columns, associations) to an LLM, gets back one
|
|
55
|
+
ActiveRecord query, checks it call by call against a read-only allowlist, fixes the model's
|
|
56
|
+
common mistakes in code, and runs it only after you confirm. Works with OpenAI, Anthropic,
|
|
57
|
+
Gemini, Ollama or any OpenAI-compatible endpoint, at about 1,700 tokens per question.
|
|
58
|
+
email:
|
|
59
|
+
- ivan.blazevic@rubycode.co
|
|
60
|
+
executables:
|
|
61
|
+
- rails-agent
|
|
62
|
+
extensions: []
|
|
63
|
+
extra_rdoc_files: []
|
|
64
|
+
files:
|
|
65
|
+
- CHANGELOG.md
|
|
66
|
+
- LICENSE.txt
|
|
67
|
+
- README.md
|
|
68
|
+
- exe/rails-agent
|
|
69
|
+
- lib/generators/rails_agent_console/install_generator.rb
|
|
70
|
+
- lib/generators/rails_agent_console/templates/rails_agent_console.rb
|
|
71
|
+
- lib/rails_agent_console.rb
|
|
72
|
+
- lib/rails_agent_console/agent.rb
|
|
73
|
+
- lib/rails_agent_console/cli.rb
|
|
74
|
+
- lib/rails_agent_console/configuration.rb
|
|
75
|
+
- lib/rails_agent_console/console_installer.rb
|
|
76
|
+
- lib/rails_agent_console/console_methods.rb
|
|
77
|
+
- lib/rails_agent_console/console_session.rb
|
|
78
|
+
- lib/rails_agent_console/credentials.rb
|
|
79
|
+
- lib/rails_agent_console/diagnosis.rb
|
|
80
|
+
- lib/rails_agent_console/diagnosis/extra.rb
|
|
81
|
+
- lib/rails_agent_console/errors.rb
|
|
82
|
+
- lib/rails_agent_console/executor.rb
|
|
83
|
+
- lib/rails_agent_console/history.rb
|
|
84
|
+
- lib/rails_agent_console/model_picker.rb
|
|
85
|
+
- lib/rails_agent_console/prompt.rb
|
|
86
|
+
- lib/rails_agent_console/prompt/dates.rb
|
|
87
|
+
- lib/rails_agent_console/prompt/follow_up.rb
|
|
88
|
+
- lib/rails_agent_console/proposal.rb
|
|
89
|
+
- lib/rails_agent_console/providers.rb
|
|
90
|
+
- lib/rails_agent_console/providers/anthropic.rb
|
|
91
|
+
- lib/rails_agent_console/providers/base.rb
|
|
92
|
+
- lib/rails_agent_console/providers/callable.rb
|
|
93
|
+
- lib/rails_agent_console/providers/gemini.rb
|
|
94
|
+
- lib/rails_agent_console/providers/ollama.rb
|
|
95
|
+
- lib/rails_agent_console/providers/openai.rb
|
|
96
|
+
- lib/rails_agent_console/query_validator.rb
|
|
97
|
+
- lib/rails_agent_console/query_validator/model_suggestion.rb
|
|
98
|
+
- lib/rails_agent_console/query_validator/parse_error.rb
|
|
99
|
+
- lib/rails_agent_console/query_validator/result.rb
|
|
100
|
+
- lib/rails_agent_console/query_validator/rules.rb
|
|
101
|
+
- lib/rails_agent_console/query_validator/sensitive_columns.rb
|
|
102
|
+
- lib/rails_agent_console/railtie.rb
|
|
103
|
+
- lib/rails_agent_console/rewriter.rb
|
|
104
|
+
- lib/rails_agent_console/rewriter/arguments.rb
|
|
105
|
+
- lib/rails_agent_console/rewriter/chain.rb
|
|
106
|
+
- lib/rails_agent_console/rewriter/date_ranges.rb
|
|
107
|
+
- lib/rails_agent_console/rewriter/distinct.rb
|
|
108
|
+
- lib/rails_agent_console/rewriter/joined.rb
|
|
109
|
+
- lib/rails_agent_console/rewriter/qualifier.rb
|
|
110
|
+
- lib/rails_agent_console/rewriter/quotes.rb
|
|
111
|
+
- lib/rails_agent_console/rewriter/sql_repair.rb
|
|
112
|
+
- lib/rails_agent_console/schema.rb
|
|
113
|
+
- lib/rails_agent_console/setup.rb
|
|
114
|
+
- lib/rails_agent_console/ui.rb
|
|
115
|
+
- lib/rails_agent_console/value_check.rb
|
|
116
|
+
- lib/rails_agent_console/version.rb
|
|
117
|
+
- lib/rails_agent_console/wizard.rb
|
|
118
|
+
homepage: https://github.com/blaz1988/rails-agent-console
|
|
119
|
+
licenses:
|
|
120
|
+
- MIT
|
|
121
|
+
metadata:
|
|
122
|
+
source_code_uri: https://github.com/blaz1988/rails-agent-console
|
|
123
|
+
documentation_uri: https://github.com/blaz1988/rails-agent-console#readme
|
|
124
|
+
changelog_uri: https://github.com/blaz1988/rails-agent-console/blob/main/CHANGELOG.md
|
|
125
|
+
bug_tracker_uri: https://github.com/blaz1988/rails-agent-console/issues
|
|
126
|
+
rubygems_mfa_required: 'true'
|
|
127
|
+
rdoc_options: []
|
|
128
|
+
require_paths:
|
|
129
|
+
- lib
|
|
130
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
131
|
+
requirements:
|
|
132
|
+
- - ">="
|
|
133
|
+
- !ruby/object:Gem::Version
|
|
134
|
+
version: 3.1.0
|
|
135
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
136
|
+
requirements:
|
|
137
|
+
- - ">="
|
|
138
|
+
- !ruby/object:Gem::Version
|
|
139
|
+
version: '0'
|
|
140
|
+
requirements: []
|
|
141
|
+
rubygems_version: 3.6.4
|
|
142
|
+
specification_version: 4
|
|
143
|
+
summary: Plain-English questions in rails console, answered with ActiveRecord you
|
|
144
|
+
read before it runs.
|
|
145
|
+
test_files: []
|