Class: RailsConsoleAi::Channel::Slack
- Defined in:
- lib/rails_console_ai/channel/slack.rb
Constant Summary collapse
- ANSI_REGEX =
/\e\[[0-9;]*m/
Instance Method Summary collapse
- #cancel! ⇒ Object
- #cancelled? ⇒ Boolean
- #confirm(_text) ⇒ Object
- #console_capture_string ⇒ Object
- #display(text) ⇒ Object
- #display_code(code) ⇒ Object
- #display_dim(text) ⇒ Object
- #display_error(text) ⇒ Object
- #display_result(_result) ⇒ Object
- #display_result_output(output) ⇒ Object
- #display_tool_call(text) ⇒ Object
- #display_warning(text) ⇒ Object
-
#initialize(slack_bot:, channel_id:, thread_ts:, user_name: nil) ⇒ Slack
constructor
A new instance of Slack.
- #log_input(text) ⇒ Object
- #mode ⇒ Object
- #prompt(text) ⇒ Object
-
#receive_reply(text) ⇒ Object
Called by SlackBot when a thread reply arrives.
- #supports_danger? ⇒ Boolean
- #supports_editing? ⇒ Boolean
- #system_instructions ⇒ Object
- #user_identity ⇒ Object
- #wrap_llm_call(&block) ⇒ Object
Methods inherited from Base
Constructor Details
#initialize(slack_bot:, channel_id:, thread_ts:, user_name: nil) ⇒ Slack
Returns a new instance of Slack.
8 9 10 11 12 13 14 15 16 17 |
# File 'lib/rails_console_ai/channel/slack.rb', line 8 def initialize(slack_bot:, channel_id:, thread_ts:, user_name: nil) @slack_bot = slack_bot @channel_id = channel_id @thread_ts = thread_ts @user_name = user_name @reply_queue = Queue.new @cancelled = false @log_prefix = "[#{@channel_id}/#{@thread_ts}] @#{@user_name}" @output_log = StringIO.new end |
Instance Method Details
#cancel! ⇒ Object
19 20 21 |
# File 'lib/rails_console_ai/channel/slack.rb', line 19 def cancel! @cancelled = true end |
#cancelled? ⇒ Boolean
23 24 25 |
# File 'lib/rails_console_ai/channel/slack.rb', line 23 def cancelled? @cancelled end |
#confirm(_text) ⇒ Object
88 89 90 |
# File 'lib/rails_console_ai/channel/slack.rb', line 88 def confirm(_text) 'y' end |
#console_capture_string ⇒ Object
159 160 161 |
# File 'lib/rails_console_ai/channel/slack.rb', line 159 def console_capture_string @output_log.string end |
#display(text) ⇒ Object
27 28 29 |
# File 'lib/rails_console_ai/channel/slack.rb', line 27 def display(text) post(strip_ansi(text)) end |
#display_code(code) ⇒ Object
64 65 66 67 68 69 |
# File 'lib/rails_console_ai/channel/slack.rb', line 64 def display_code(code) # Don't post raw code/plan steps to Slack — non-technical users don't need to see Ruby # But do log to STDOUT so server logs show what was generated/executed @output_log.write("# Generated code:\n#{code}\n") STDOUT.puts "#{@log_prefix} (code)\n# Generated code:\n#{code}" end |
#display_dim(text) ⇒ Object
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
# File 'lib/rails_console_ai/channel/slack.rb', line 31 def display_dim(text) raw = strip_ansi(text) stripped = raw.strip if stripped =~ /\AThinking\.\.\.|\AAttempting to fix|\ACancelled|\A_session:/ post(stripped) elsif stripped =~ /\ACalling LLM/ # Technical LLM round status — suppress in Slack @output_log.write("#{stripped}\n") STDOUT.puts "#{@log_prefix} (dim) #{stripped}" elsif raw =~ /\A {2,4}\S/ && stripped.length > 10 # LLM thinking text (2-space indent from conversation engine) — show as status post(stripped) else # Tool result previews (5+ space indent) and other technical noise — log only @output_log.write("#{stripped}\n") STDOUT.puts "#{@log_prefix} (dim) #{stripped}" end end |
#display_error(text) ⇒ Object
55 56 57 |
# File 'lib/rails_console_ai/channel/slack.rb', line 55 def display_error(text) post(":x: #{strip_ansi(text)}") end |
#display_result(_result) ⇒ Object
78 79 80 81 |
# File 'lib/rails_console_ai/channel/slack.rb', line 78 def display_result(_result) # Don't post raw return values to Slack — the LLM formats output via puts nil end |
#display_result_output(output) ⇒ Object
71 72 73 74 75 76 |
# File 'lib/rails_console_ai/channel/slack.rb', line 71 def display_result_output(output) text = strip_ansi(output).strip return if text.empty? text = text[0, 3000] + "\n... (truncated)" if text.length > 3000 post("```#{text}```") end |
#display_tool_call(text) ⇒ Object
59 60 61 62 |
# File 'lib/rails_console_ai/channel/slack.rb', line 59 def display_tool_call(text) @output_log.write("-> #{text}\n") STDOUT.puts "#{@log_prefix} -> #{text}" end |
#display_warning(text) ⇒ Object
51 52 53 |
# File 'lib/rails_console_ai/channel/slack.rb', line 51 def display_warning(text) post(":warning: #{strip_ansi(text)}") end |
#log_input(text) ⇒ Object
149 150 151 |
# File 'lib/rails_console_ai/channel/slack.rb', line 149 def log_input(text) @output_log.write("@#{@user_name}: #{text}\n") end |
#mode ⇒ Object
96 97 98 |
# File 'lib/rails_console_ai/channel/slack.rb', line 96 def mode 'slack' end |
#prompt(text) ⇒ Object
83 84 85 86 |
# File 'lib/rails_console_ai/channel/slack.rb', line 83 def prompt(text) post(strip_ansi(text)) @reply_queue.pop end |
#receive_reply(text) ⇒ Object
Called by SlackBot when a thread reply arrives
154 155 156 157 |
# File 'lib/rails_console_ai/channel/slack.rb', line 154 def receive_reply(text) @output_log.write("@#{@user_name}: #{text}\n") @reply_queue.push(text) end |
#supports_danger? ⇒ Boolean
100 101 102 |
# File 'lib/rails_console_ai/channel/slack.rb', line 100 def supports_danger? false end |
#supports_editing? ⇒ Boolean
104 105 106 |
# File 'lib/rails_console_ai/channel/slack.rb', line 104 def supports_editing? false end |
#system_instructions ⇒ Object
112 113 114 115 116 117 118 119 120 121 122 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 |
# File 'lib/rails_console_ai/channel/slack.rb', line 112 def system_instructions <<~INSTRUCTIONS.strip ## Response Formatting (Slack Channel) You are responding to non-technical users in Slack. Follow these rules: ## Code Execution - ALWAYS use the `execute_code` tool to run Ruby code. Do NOT put code in markdown code fences expecting it to be executed — code fences are display-only in Slack. - Use `execute_code` for simple queries, and `execute_plan` for multi-step operations. - If the user asks you to provide code they can run later, put it in a code fence in your text response (it will be displayed but not executed). ## Formatting - Slack does NOT support markdown tables. For tabular data, use `puts` to print a plain-text table inside a code block. Use fixed-width columns with padding so columns align. Example format: ``` ID Name Email 123 John Smith john@example.com 456 Jane Doe jane@example.com ``` - Use `puts` with formatted output instead of returning arrays or hashes - Summarize findings in plain, simple language - Do NOT show technical details like SQL queries, token counts, or class names - Keep explanations simple and jargon-free - Never return raw Ruby objects — always present data in a human-readable way - The output of `puts` in your code is automatically shown to the user. Do NOT repeat or re-display data that your code already printed via `puts`. Just add a brief summary after (e.g. "10 events found" or "Let me know if you need more detail"). - Do not offer to make changes or take actions on behalf of the user. Only report findings. - This is a live production database — other processes, users, and background jobs are constantly changing data. Never assume results will be the same as a previous query. Always re-run queries when asked, even if you just ran the same one. INSTRUCTIONS end |
#user_identity ⇒ Object
92 93 94 |
# File 'lib/rails_console_ai/channel/slack.rb', line 92 def user_identity @user_name end |
#wrap_llm_call(&block) ⇒ Object
108 109 110 |
# File 'lib/rails_console_ai/channel/slack.rb', line 108 def wrap_llm_call(&block) yield end |