rails_console_ai 0.22.0 → 0.24.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 +4 -4
- data/CHANGELOG.md +30 -0
- data/lib/generators/rails_console_ai/templates/initializer.rb +8 -4
- data/lib/rails_console_ai/channel/base.rb +2 -1
- data/lib/rails_console_ai/channel/console.rb +5 -1
- data/lib/rails_console_ai/channel/slack.rb +16 -20
- data/lib/rails_console_ai/configuration.rb +23 -0
- data/lib/rails_console_ai/context_builder.rb +16 -8
- data/lib/rails_console_ai/conversation_engine.rb +340 -111
- data/lib/rails_console_ai/executor.rb +35 -13
- data/lib/rails_console_ai/providers/bedrock.rb +4 -2
- data/lib/rails_console_ai/repl.rb +2 -2
- data/lib/rails_console_ai/skill_loader.rb +49 -0
- data/lib/rails_console_ai/slack_bot.rb +22 -18
- data/lib/rails_console_ai/tools/memory_tools.rb +22 -5
- data/lib/rails_console_ai/tools/model_tools.rb +28 -0
- data/lib/rails_console_ai/tools/registry.rb +56 -9
- data/lib/rails_console_ai/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 41b94c2b3a01cba1210242c6c8752510fc1976bf9b7195272f4a109dceadcdab
|
|
4
|
+
data.tar.gz: 6c813abfeeda804b115dfd2a385bc67e1796b0af80cc438e5f41d66886fa519e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 52281835764610528b039d12ac786ec7056d035e9055d5574bee3a3143c9833e8fa5943a5932980c7ee28ae77351a178186dc15b3afb2f0e9acb7c71b1104c5f
|
|
7
|
+
data.tar.gz: d1f56cd511ff3411b6e2783c0790bbc3d012a420971fe2cd400f7f573ffc168f5b6bca5c692618bf5c4ef2eaa9d0d0283958afcf1b7ac71d426dd4f2f4377425
|
data/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,36 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## [0.24.0]
|
|
6
|
+
|
|
7
|
+
- Refactor thinking text display and include in Slack with more technical detail
|
|
8
|
+
- Add `a` command to trigger auto-accept mode
|
|
9
|
+
- Include code output in Slack server logs
|
|
10
|
+
- Fix Bedrock issue after declining code execution
|
|
11
|
+
- Fix `allow_code_execution` configuration
|
|
12
|
+
|
|
13
|
+
## [0.23.0]
|
|
14
|
+
|
|
15
|
+
- Add `save_skill` tool
|
|
16
|
+
- Add targeted single-memory recall to avoid extraneous results
|
|
17
|
+
- Summarize memory recall output
|
|
18
|
+
- Fix Bedrock blank content handling
|
|
19
|
+
- Improve debug output and fix `trim_outputs` in Bedrock provider
|
|
20
|
+
- Preserve activated skills in conversation without truncating
|
|
21
|
+
- Show executed code in Slack log
|
|
22
|
+
- Include columns in `describe_model` to reduce tool calls
|
|
23
|
+
- Show less error detail in Slack channel
|
|
24
|
+
- Show thinking text before `execute_code` prompt in console
|
|
25
|
+
- Allow code execution without safety guards
|
|
26
|
+
- Add Slack configuration option to prevent all users from executing code
|
|
27
|
+
- Detect LLM tool loops and break out
|
|
28
|
+
- Refactor output truncation to fix LLM not seeing all needed outputs
|
|
29
|
+
- Show cache usage in `display_usage`
|
|
30
|
+
- Fix `recall_output` forcing expansion in later turns
|
|
31
|
+
- Fix conversation debug to show "tool_result" instead of "user"
|
|
32
|
+
- Make `/context` and `!context` show the same as debug output
|
|
33
|
+
- Improve `!context` handling in Slack
|
|
34
|
+
|
|
5
35
|
## [0.22.0]
|
|
6
36
|
|
|
7
37
|
- Fix blank content block handling in Bedrock provider
|
|
@@ -29,9 +29,8 @@ RailsConsoleAi.configure do |config|
|
|
|
29
29
|
# config.local_model = 'qwen2.5:7b'
|
|
30
30
|
# config.local_api_key = nil
|
|
31
31
|
|
|
32
|
-
# Slack: which users the bot responds to (
|
|
33
|
-
# config.slack_allowed_usernames = ['alice', 'bob']
|
|
34
|
-
# config.slack_allowed_usernames = 'ALL' # everyone
|
|
32
|
+
# Slack: which users the bot responds to (legacy — prefer channels config below)
|
|
33
|
+
# config.slack_allowed_usernames = ['alice', 'bob']
|
|
35
34
|
|
|
36
35
|
# AWS Bedrock provider (uses AWS credential chain — no API key needed):
|
|
37
36
|
# config.provider = :bedrock
|
|
@@ -85,7 +84,12 @@ RailsConsoleAi.configure do |config|
|
|
|
85
84
|
|
|
86
85
|
# Per-channel settings (channel mode keys: 'slack', 'console'):
|
|
87
86
|
# config.channels = {
|
|
88
|
-
# 'slack'
|
|
87
|
+
# 'slack' => {
|
|
88
|
+
# 'allowed_usernames' => ['alice', 'bob'], # who can use the bot (or 'ALL')
|
|
89
|
+
# 'allow_code_execution' => ['alice'], # who can run code directly via ``` (nil = everyone)
|
|
90
|
+
# 'pinned_memory_tags' => ['sharding'],
|
|
91
|
+
# 'bypass_guards_for_methods' => ['ChangeApproval#approve_by!']
|
|
92
|
+
# },
|
|
89
93
|
# 'console' => { 'pinned_memory_tags' => [] }
|
|
90
94
|
# }
|
|
91
95
|
end
|
|
@@ -2,7 +2,8 @@ module RailsConsoleAi
|
|
|
2
2
|
module Channel
|
|
3
3
|
class Base
|
|
4
4
|
def display(text); raise NotImplementedError; end
|
|
5
|
-
def
|
|
5
|
+
def display_thinking(text); raise NotImplementedError; end
|
|
6
|
+
def display_status(text); raise NotImplementedError; end
|
|
6
7
|
def display_warning(text); raise NotImplementedError; end
|
|
7
8
|
def display_error(text); raise NotImplementedError; end
|
|
8
9
|
def display_code(code); raise NotImplementedError; end
|
|
@@ -28,23 +28,21 @@ module RailsConsoleAi
|
|
|
28
28
|
post(strip_ansi(text))
|
|
29
29
|
end
|
|
30
30
|
|
|
31
|
-
def
|
|
32
|
-
|
|
33
|
-
|
|
31
|
+
def display_thinking(text)
|
|
32
|
+
stripped = strip_ansi(text).strip
|
|
33
|
+
return if stripped.empty?
|
|
34
|
+
post(stripped)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def display_status(text)
|
|
38
|
+
stripped = strip_ansi(text).strip
|
|
39
|
+
return if stripped.empty?
|
|
34
40
|
|
|
35
41
|
if stripped =~ /\AThinking\.\.\.|\AAttempting to fix|\ACancelled|\A_session:/
|
|
36
42
|
post(stripped)
|
|
37
|
-
elsif stripped =~ /\ACalling LLM/
|
|
38
|
-
# Technical LLM round status — suppress in Slack
|
|
39
|
-
@output_log.write("#{stripped}\n")
|
|
40
|
-
STDOUT.puts "#{@log_prefix} (dim) #{stripped}"
|
|
41
|
-
elsif raw =~ /\A {2,4}\S/ && stripped.length > 10
|
|
42
|
-
# LLM thinking text (2-space indent from conversation engine) — show as status
|
|
43
|
-
post(stripped)
|
|
44
43
|
else
|
|
45
|
-
# Tool result previews (5+ space indent) and other technical noise — log only
|
|
46
44
|
@output_log.write("#{stripped}\n")
|
|
47
|
-
STDOUT.puts "#{@log_prefix} (
|
|
45
|
+
STDOUT.puts "#{@log_prefix} (status) #{stripped}"
|
|
48
46
|
end
|
|
49
47
|
end
|
|
50
48
|
|
|
@@ -65,7 +63,8 @@ module RailsConsoleAi
|
|
|
65
63
|
# Don't post raw code/plan steps to Slack — non-technical users don't need to see Ruby
|
|
66
64
|
# But do log to STDOUT so server logs show what was generated/executed
|
|
67
65
|
@output_log.write("# Generated code:\n#{code}\n")
|
|
68
|
-
STDOUT.puts "#{@log_prefix} (code)
|
|
66
|
+
STDOUT.puts "#{@log_prefix} (code)"
|
|
67
|
+
code.each_line { |line| STDOUT.puts "#{@log_prefix} (code) #{line.rstrip}" }
|
|
69
68
|
end
|
|
70
69
|
|
|
71
70
|
def display_result_output(output)
|
|
@@ -111,9 +110,9 @@ module RailsConsoleAi
|
|
|
111
110
|
|
|
112
111
|
def system_instructions
|
|
113
112
|
<<~INSTRUCTIONS.strip
|
|
114
|
-
##
|
|
113
|
+
## Slack Channel
|
|
115
114
|
|
|
116
|
-
You are responding
|
|
115
|
+
You are responding in a Slack thread.
|
|
117
116
|
|
|
118
117
|
## Code Execution
|
|
119
118
|
- ALWAYS use the `execute_code` tool to run Ruby code. Do NOT put code in markdown
|
|
@@ -131,11 +130,8 @@ module RailsConsoleAi
|
|
|
131
130
|
123 John Smith john@example.com
|
|
132
131
|
456 Jane Doe jane@example.com
|
|
133
132
|
```
|
|
134
|
-
- Use `puts` with formatted output instead of returning arrays or hashes
|
|
135
|
-
-
|
|
136
|
-
- Do NOT show technical details like SQL queries, token counts, or class names
|
|
137
|
-
- Keep explanations simple and jargon-free
|
|
138
|
-
- Never return raw Ruby objects — always present data in a human-readable way
|
|
133
|
+
- Use `puts` with formatted output instead of returning arrays or hashes.
|
|
134
|
+
- Never return raw Ruby objects — always present data in a human-readable way.
|
|
139
135
|
- The output of `puts` in your code is automatically shown to the user. Do NOT
|
|
140
136
|
repeat or re-display data that your code already printed via `puts`.
|
|
141
137
|
Just add a brief summary after (e.g. "10 events found" or "Let me know if you need more detail").
|
|
@@ -71,6 +71,29 @@ module RailsConsoleAi
|
|
|
71
71
|
@user_extra_info[username.to_s.downcase]
|
|
72
72
|
end
|
|
73
73
|
|
|
74
|
+
# Look up a per-channel setting with backward compatibility.
|
|
75
|
+
# Falls back to top-level slack_* config when channels hash doesn't have the key.
|
|
76
|
+
def channel_setting(mode, key)
|
|
77
|
+
channel_cfg = @channels[mode.to_s] || {}
|
|
78
|
+
value = channel_cfg[key.to_s]
|
|
79
|
+
|
|
80
|
+
# Backward compatibility: slack_allowed_usernames → channels.slack.allowed_usernames
|
|
81
|
+
if value.nil? && mode.to_s == 'slack' && key.to_s == 'allowed_usernames'
|
|
82
|
+
value = @slack_allowed_usernames
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
value
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
# Check if a username is permitted by a channel setting.
|
|
89
|
+
# Returns true when the setting is nil (not configured = no restriction).
|
|
90
|
+
def username_allowed?(mode, key, username)
|
|
91
|
+
list = channel_setting(mode, key)
|
|
92
|
+
return true if list.nil?
|
|
93
|
+
normalized = Array(list).map(&:to_s).map(&:downcase)
|
|
94
|
+
normalized.include?('all') || normalized.include?(username.to_s.downcase)
|
|
95
|
+
end
|
|
96
|
+
|
|
74
97
|
def safety_guards
|
|
75
98
|
@safety_guards ||= begin
|
|
76
99
|
require 'rails_console_ai/safety_guards'
|
|
@@ -55,8 +55,9 @@ module RailsConsoleAi
|
|
|
55
55
|
You help them query data, debug issues, and understand their application.
|
|
56
56
|
|
|
57
57
|
You have tools available to introspect the app's database schema, models, and source code.
|
|
58
|
-
Use them as needed to write accurate queries. For example, call
|
|
59
|
-
|
|
58
|
+
Use them as needed to write accurate queries. For example, call list_models to see what
|
|
59
|
+
models exist, then describe_model to get columns, associations, and validations.
|
|
60
|
+
Use describe_table only for tables that have no corresponding model.
|
|
60
61
|
|
|
61
62
|
You also have an ask_user tool to ask the console user clarifying questions. Use it when
|
|
62
63
|
you need specific information to write accurate code — such as which user they are, which
|
|
@@ -66,7 +67,10 @@ module RailsConsoleAi
|
|
|
66
67
|
- save_memory: persist facts or procedures you learn about this codebase.
|
|
67
68
|
If a memory with the same name already exists, it will be updated in place.
|
|
68
69
|
- delete_memory: remove a memory by name
|
|
69
|
-
-
|
|
70
|
+
- recall_memory: retrieve a specific memory by name. Use when you see a relevant memory
|
|
71
|
+
in the Memories section and want its full details.
|
|
72
|
+
- recall_memories: search memories by keyword or tag. Use when you're not sure which
|
|
73
|
+
memory you need.
|
|
70
74
|
|
|
71
75
|
IMPORTANT: Check the Memories section below BEFORE answering. If a memory is relevant,
|
|
72
76
|
use recall_memories to get full details and apply that knowledge to your answer.
|
|
@@ -82,15 +86,19 @@ module RailsConsoleAi
|
|
|
82
86
|
(e.g. `api = SalesforceApi.new(step1)`).
|
|
83
87
|
- If the user asks you to provide code for them to run later (not execute now), put it
|
|
84
88
|
in a ```ruby code block in your text response.
|
|
85
|
-
You have skills —
|
|
86
|
-
|
|
87
|
-
|
|
89
|
+
You have skills — reusable procedures for specific operations:
|
|
90
|
+
- When a user's request matches an existing skill, call activate_skill to load the recipe
|
|
91
|
+
and enable its guard bypasses, then follow the recipe.
|
|
92
|
+
- When a user asks you to "create a skill" or "make a runbook", use save_skill to create
|
|
93
|
+
a new skill with a step-by-step recipe. Skills are procedures (how to do X); memories
|
|
94
|
+
are facts (what you learned about X). Do NOT use save_memory when asked to create a skill.
|
|
88
95
|
|
|
89
96
|
RULES:
|
|
90
97
|
- Give ONE concise answer. Do not offer multiple alternatives or variations.
|
|
91
98
|
- For multi-step tasks, use execute_plan to break the work into small, clear steps.
|
|
92
99
|
- For simple queries, use the execute_code tool.
|
|
93
|
-
-
|
|
100
|
+
- Before calling tools, briefly state what you're about to do (e.g., "Let me check the
|
|
101
|
+
user's migration status." or "I'll look up the table structure."). Keep it to one sentence.
|
|
94
102
|
- Use the app's actual model names, associations, and schema.
|
|
95
103
|
- Prefer ActiveRecord query interface over raw SQL.
|
|
96
104
|
- For destructive operations, add a comment warning.
|
|
@@ -176,7 +184,7 @@ module RailsConsoleAi
|
|
|
176
184
|
lines = ["## Memories"]
|
|
177
185
|
lines.concat(summaries)
|
|
178
186
|
lines << ""
|
|
179
|
-
lines << "Call recall_memories to get details before answering. Do NOT guess from the name alone."
|
|
187
|
+
lines << "Call recall_memory (by name) or recall_memories (by keyword) to get details before answering. Do NOT guess from the name alone."
|
|
180
188
|
lines.join("\n")
|
|
181
189
|
rescue => e
|
|
182
190
|
RailsConsoleAi.logger.debug("RailsConsoleAi: memory context failed: #{e.message}")
|