rails_console_ai 0.13.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 +95 -0
- data/LICENSE +21 -0
- data/README.md +328 -0
- data/app/controllers/rails_console_ai/application_controller.rb +28 -0
- data/app/controllers/rails_console_ai/sessions_controller.rb +16 -0
- data/app/helpers/rails_console_ai/sessions_helper.rb +56 -0
- data/app/models/rails_console_ai/session.rb +23 -0
- data/app/views/layouts/rails_console_ai/application.html.erb +84 -0
- data/app/views/rails_console_ai/sessions/index.html.erb +57 -0
- data/app/views/rails_console_ai/sessions/show.html.erb +66 -0
- data/config/routes.rb +4 -0
- data/lib/generators/rails_console_ai/install_generator.rb +26 -0
- data/lib/generators/rails_console_ai/templates/initializer.rb +79 -0
- data/lib/rails_console_ai/channel/base.rb +23 -0
- data/lib/rails_console_ai/channel/console.rb +457 -0
- data/lib/rails_console_ai/channel/slack.rb +182 -0
- data/lib/rails_console_ai/configuration.rb +185 -0
- data/lib/rails_console_ai/console_methods.rb +277 -0
- data/lib/rails_console_ai/context_builder.rb +120 -0
- data/lib/rails_console_ai/conversation_engine.rb +1142 -0
- data/lib/rails_console_ai/engine.rb +5 -0
- data/lib/rails_console_ai/executor.rb +461 -0
- data/lib/rails_console_ai/providers/anthropic.rb +122 -0
- data/lib/rails_console_ai/providers/base.rb +118 -0
- data/lib/rails_console_ai/providers/bedrock.rb +171 -0
- data/lib/rails_console_ai/providers/local.rb +112 -0
- data/lib/rails_console_ai/providers/openai.rb +114 -0
- data/lib/rails_console_ai/railtie.rb +34 -0
- data/lib/rails_console_ai/repl.rb +65 -0
- data/lib/rails_console_ai/safety_guards.rb +207 -0
- data/lib/rails_console_ai/session_logger.rb +90 -0
- data/lib/rails_console_ai/slack_bot.rb +473 -0
- data/lib/rails_console_ai/storage/base.rb +27 -0
- data/lib/rails_console_ai/storage/file_storage.rb +63 -0
- data/lib/rails_console_ai/tools/code_tools.rb +126 -0
- data/lib/rails_console_ai/tools/memory_tools.rb +136 -0
- data/lib/rails_console_ai/tools/model_tools.rb +95 -0
- data/lib/rails_console_ai/tools/registry.rb +478 -0
- data/lib/rails_console_ai/tools/schema_tools.rb +60 -0
- data/lib/rails_console_ai/version.rb +3 -0
- data/lib/rails_console_ai.rb +214 -0
- data/lib/tasks/rails_console_ai.rake +7 -0
- metadata +152 -0
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 16px;">
|
|
2
|
+
<h2 style="font-size: 20px;">Sessions</h2>
|
|
3
|
+
<span class="text-muted" style="font-size: 14px;"><%= @total %> total</span>
|
|
4
|
+
</div>
|
|
5
|
+
|
|
6
|
+
<% if @sessions.empty? %>
|
|
7
|
+
<div class="meta-card">
|
|
8
|
+
<p class="text-muted">No sessions recorded yet.</p>
|
|
9
|
+
</div>
|
|
10
|
+
<% else %>
|
|
11
|
+
<table>
|
|
12
|
+
<thead>
|
|
13
|
+
<tr>
|
|
14
|
+
<th>Time</th>
|
|
15
|
+
<th>User</th>
|
|
16
|
+
<th>Name</th>
|
|
17
|
+
<th style="max-width: 400px;">Query</th>
|
|
18
|
+
<th>Mode</th>
|
|
19
|
+
<th>Tokens</th>
|
|
20
|
+
<th>Cost</th>
|
|
21
|
+
<th>Duration</th>
|
|
22
|
+
</tr>
|
|
23
|
+
</thead>
|
|
24
|
+
<tbody>
|
|
25
|
+
<% @sessions.each do |session| %>
|
|
26
|
+
<tr>
|
|
27
|
+
<td class="mono"><%= session.created_at.strftime('%Y-%m-%d %H:%M') %></td>
|
|
28
|
+
<td><%= session.user_name %></td>
|
|
29
|
+
<td><%= session.name.present? ? session.name : '-' %></td>
|
|
30
|
+
<td class="query-cell"><a href="<%= rails_console_ai.session_path(session) %>" title="<%= h session.query.truncate(200) %>"><%= truncate(session.query.gsub(/\s+/, ' ').strip, length: 80) %></a></td>
|
|
31
|
+
<td><span class="badge badge-<%= session.mode %>"><%= session.mode %></span></td>
|
|
32
|
+
<td class="mono"><%= session.input_tokens + session.output_tokens %></td>
|
|
33
|
+
<td class="mono"><%= format_cost(session) %></td>
|
|
34
|
+
<td class="mono"><%= session.duration_ms ? "#{session.duration_ms}ms" : '-' %></td>
|
|
35
|
+
</tr>
|
|
36
|
+
<% end %>
|
|
37
|
+
</tbody>
|
|
38
|
+
</table>
|
|
39
|
+
|
|
40
|
+
<% if @total_pages > 1 %>
|
|
41
|
+
<div class="pagination">
|
|
42
|
+
<% if @page > 1 %>
|
|
43
|
+
<a href="<%= rails_console_ai.sessions_path(page: @page - 1) %>">← Newer</a>
|
|
44
|
+
<% else %>
|
|
45
|
+
<span class="disabled">← Newer</span>
|
|
46
|
+
<% end %>
|
|
47
|
+
|
|
48
|
+
<span class="page-info">Page <%= @page %> of <%= @total_pages %></span>
|
|
49
|
+
|
|
50
|
+
<% if @page < @total_pages %>
|
|
51
|
+
<a href="<%= rails_console_ai.sessions_path(page: @page + 1) %>">Older →</a>
|
|
52
|
+
<% else %>
|
|
53
|
+
<span class="disabled">Older →</span>
|
|
54
|
+
<% end %>
|
|
55
|
+
</div>
|
|
56
|
+
<% end %>
|
|
57
|
+
<% end %>
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
<a href="<%= rails_console_ai.sessions_path %>" class="back-link">← Back to sessions</a>
|
|
2
|
+
|
|
3
|
+
<div class="meta-card">
|
|
4
|
+
<div class="meta-grid">
|
|
5
|
+
<div class="meta-item" style="grid-column: 1 / -1;">
|
|
6
|
+
<label>Query</label>
|
|
7
|
+
<% if @session.query.length > 300 %>
|
|
8
|
+
<div class="query-preview">
|
|
9
|
+
<span><%= truncate(@session.query, length: 300) %></span>
|
|
10
|
+
<details style="margin-top: 4px;">
|
|
11
|
+
<summary style="cursor: pointer; font-size: 12px; color: #4a6fa5;">Show full query</summary>
|
|
12
|
+
<pre style="white-space: pre-wrap; word-wrap: break-word; font-size: 13px; margin-top: 8px; padding: 12px; background: #f8f9fa; border-radius: 4px; max-height: 400px; overflow-y: auto;"><%= @session.query %></pre>
|
|
13
|
+
</details>
|
|
14
|
+
</div>
|
|
15
|
+
<% else %>
|
|
16
|
+
<span><%= @session.query %></span>
|
|
17
|
+
<% end %>
|
|
18
|
+
</div>
|
|
19
|
+
<% if @session.name.present? %>
|
|
20
|
+
<div class="meta-item">
|
|
21
|
+
<label>Name</label>
|
|
22
|
+
<span><%= @session.name %></span>
|
|
23
|
+
</div>
|
|
24
|
+
<% end %>
|
|
25
|
+
<div class="meta-item">
|
|
26
|
+
<label>Mode</label>
|
|
27
|
+
<span class="badge badge-<%= @session.mode %>"><%= @session.mode %></span>
|
|
28
|
+
</div>
|
|
29
|
+
<div class="meta-item">
|
|
30
|
+
<label>User</label>
|
|
31
|
+
<span><%= @session.user_name || '-' %></span>
|
|
32
|
+
</div>
|
|
33
|
+
<div class="meta-item">
|
|
34
|
+
<label>Provider / Model</label>
|
|
35
|
+
<span><%= @session.provider %> / <%= @session.model %></span>
|
|
36
|
+
</div>
|
|
37
|
+
<div class="meta-item">
|
|
38
|
+
<label>Tokens (in / out)</label>
|
|
39
|
+
<span class="mono"><%= @session.input_tokens %> / <%= @session.output_tokens %></span>
|
|
40
|
+
</div>
|
|
41
|
+
<div class="meta-item">
|
|
42
|
+
<label>Est. Cost</label>
|
|
43
|
+
<span class="mono"><%= format_cost(@session) %></span>
|
|
44
|
+
</div>
|
|
45
|
+
<div class="meta-item">
|
|
46
|
+
<label>Duration</label>
|
|
47
|
+
<span class="mono"><%= @session.duration_ms ? "#{@session.duration_ms}ms" : '-' %></span>
|
|
48
|
+
</div>
|
|
49
|
+
<div class="meta-item">
|
|
50
|
+
<label>Time</label>
|
|
51
|
+
<span><%= @session.created_at.strftime('%Y-%m-%d %H:%M:%S') %></span>
|
|
52
|
+
</div>
|
|
53
|
+
</div>
|
|
54
|
+
</div>
|
|
55
|
+
|
|
56
|
+
<h3 style="font-size: 16px; margin-bottom: 12px;">Console Output</h3>
|
|
57
|
+
|
|
58
|
+
<% if @session.console_output.present? %>
|
|
59
|
+
<div class="terminal">
|
|
60
|
+
<pre><%= ansi_to_html(@session.console_output) %></pre>
|
|
61
|
+
</div>
|
|
62
|
+
<% else %>
|
|
63
|
+
<div class="meta-card">
|
|
64
|
+
<p class="text-muted">No console output recorded for this session.</p>
|
|
65
|
+
</div>
|
|
66
|
+
<% end %>
|
data/config/routes.rb
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
require 'rails/generators'
|
|
2
|
+
|
|
3
|
+
module RailsConsoleAI
|
|
4
|
+
module Generators
|
|
5
|
+
class InstallGenerator < Rails::Generators::Base
|
|
6
|
+
source_root File.expand_path('templates', __dir__)
|
|
7
|
+
desc 'Creates a RailsConsoleAI initializer in config/initializers/'
|
|
8
|
+
|
|
9
|
+
def copy_initializer
|
|
10
|
+
template 'initializer.rb', 'config/initializers/rails_console_ai.rb'
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def show_readme
|
|
14
|
+
say ''
|
|
15
|
+
say 'RailsConsoleAI installed!', :green
|
|
16
|
+
say ''
|
|
17
|
+
say 'Next steps:'
|
|
18
|
+
say ' 1. Set your API key: export ANTHROPIC_API_KEY=sk-...'
|
|
19
|
+
say ' 2. Edit config/initializers/rails_console_ai.rb if needed'
|
|
20
|
+
say ' 3. Run: rails console'
|
|
21
|
+
say ' 4. Try: ai "show me all tables"'
|
|
22
|
+
say ''
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
RailsConsoleAI.configure do |config|
|
|
2
|
+
# LLM provider: :anthropic, :openai, or :local
|
|
3
|
+
config.provider = :anthropic
|
|
4
|
+
|
|
5
|
+
# API key (or set ANTHROPIC_API_KEY / OPENAI_API_KEY env var)
|
|
6
|
+
# config.api_key = 'sk-...'
|
|
7
|
+
|
|
8
|
+
# Model override (defaults: claude-opus-4-6 for Anthropic, gpt-5.3-codex for OpenAI)
|
|
9
|
+
# config.model = 'claude-opus-4-6'
|
|
10
|
+
|
|
11
|
+
# Max tokens for LLM response
|
|
12
|
+
config.max_tokens = 4096
|
|
13
|
+
|
|
14
|
+
# Temperature (0.0 - 1.0)
|
|
15
|
+
config.temperature = 0.2
|
|
16
|
+
|
|
17
|
+
# Auto-execute generated code without confirmation (use with caution!)
|
|
18
|
+
config.auto_execute = false
|
|
19
|
+
|
|
20
|
+
# Max tool-use rounds per query (safety cap)
|
|
21
|
+
config.max_tool_rounds = 10
|
|
22
|
+
|
|
23
|
+
# HTTP timeout in seconds
|
|
24
|
+
config.timeout = 30
|
|
25
|
+
|
|
26
|
+
# Local model provider (Ollama, vLLM, or any OpenAI-compatible server):
|
|
27
|
+
# config.provider = :local
|
|
28
|
+
# config.local_url = 'http://localhost:11434'
|
|
29
|
+
# config.local_model = 'qwen2.5:7b'
|
|
30
|
+
# config.local_api_key = nil
|
|
31
|
+
|
|
32
|
+
# Slack: which users the bot responds to (required for Slack mode)
|
|
33
|
+
# config.slack_allowed_usernames = ['alice', 'bob'] # specific users
|
|
34
|
+
# config.slack_allowed_usernames = 'ALL' # everyone
|
|
35
|
+
|
|
36
|
+
# AWS Bedrock provider (uses AWS credential chain — no API key needed):
|
|
37
|
+
# config.provider = :bedrock
|
|
38
|
+
# config.bedrock_region = 'us-east-1'
|
|
39
|
+
# config.model = 'us.anthropic.claude-sonnet-4-6'
|
|
40
|
+
|
|
41
|
+
# Debug mode: prints full API requests/responses and tool calls to stderr
|
|
42
|
+
# config.debug = true
|
|
43
|
+
|
|
44
|
+
# Session logging: persist AI sessions to the database
|
|
45
|
+
# Run RailsConsoleAI.setup! in the Rails console to create the table
|
|
46
|
+
config.session_logging = true
|
|
47
|
+
|
|
48
|
+
# Database connection for RailsConsoleAI tables (default: ActiveRecord::Base)
|
|
49
|
+
# Set to a class that responds to .connection if tables live on a different DB
|
|
50
|
+
# config.connection_class = Sharding::CentralizedModel
|
|
51
|
+
|
|
52
|
+
# Admin UI credentials (mount RailsConsoleAI::Engine => '/rails_console_ai' in routes.rb)
|
|
53
|
+
# When nil, all requests are denied. Set credentials or use config.authenticate.
|
|
54
|
+
# config.admin_username = 'admin'
|
|
55
|
+
# config.admin_password = 'changeme'
|
|
56
|
+
|
|
57
|
+
# Safety guards: prevent side effects (DB writes, HTTP calls, etc.) during code execution.
|
|
58
|
+
# When enabled, code runs in safe mode by default. Users can toggle with /danger in the REPL.
|
|
59
|
+
#
|
|
60
|
+
# Built-in guard for database writes (works on Rails 5+, all adapters):
|
|
61
|
+
# config.use_builtin_safety_guard :database_writes
|
|
62
|
+
#
|
|
63
|
+
# Built-in guard for HTTP mutations — blocks POST/PUT/PATCH/DELETE via Net::HTTP.
|
|
64
|
+
# Covers most Ruby HTTP libraries (HTTParty, RestClient, Faraday) since they use Net::HTTP:
|
|
65
|
+
# config.use_builtin_safety_guard :http_mutations
|
|
66
|
+
#
|
|
67
|
+
# Allowlist specific hosts or tables so they pass through without blocking:
|
|
68
|
+
# config.use_builtin_safety_guard :http_mutations,
|
|
69
|
+
# allow: [/s3\.amazonaws\.com/, /googleapis\.com/]
|
|
70
|
+
# config.use_builtin_safety_guard :database_writes,
|
|
71
|
+
# allow: ['rails_console_ai_sessions']
|
|
72
|
+
#
|
|
73
|
+
# Built-in guard for mailers — disables ActionMailer delivery:
|
|
74
|
+
# config.use_builtin_safety_guard :mailers
|
|
75
|
+
#
|
|
76
|
+
# config.safety_guard :jobs do |&execute|
|
|
77
|
+
# Sidekiq::Testing.fake! { execute.call }
|
|
78
|
+
# end
|
|
79
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
module RailsConsoleAI
|
|
2
|
+
module Channel
|
|
3
|
+
class Base
|
|
4
|
+
def display(text); raise NotImplementedError; end
|
|
5
|
+
def display_dim(text); raise NotImplementedError; end
|
|
6
|
+
def display_warning(text); raise NotImplementedError; end
|
|
7
|
+
def display_error(text); raise NotImplementedError; end
|
|
8
|
+
def display_code(code); raise NotImplementedError; end
|
|
9
|
+
def display_result(text); raise NotImplementedError; end
|
|
10
|
+
def display_result_output(text); end # stdout output from code execution
|
|
11
|
+
def prompt(text); raise NotImplementedError; end
|
|
12
|
+
def confirm(text); raise NotImplementedError; end
|
|
13
|
+
def user_identity; raise NotImplementedError; end
|
|
14
|
+
def mode; raise NotImplementedError; end
|
|
15
|
+
def cancelled?; false; end
|
|
16
|
+
def supports_danger?; true; end
|
|
17
|
+
def supports_editing?; false; end
|
|
18
|
+
def edit_code(code); code; end
|
|
19
|
+
def wrap_llm_call(&block); yield; end
|
|
20
|
+
def system_instructions; nil; end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|