console_agent 0.10.0 → 0.11.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.
@@ -8,9 +8,10 @@ module ConsoleAgent
8
8
  # Tools that should never be cached (side effects or user interaction)
9
9
  NO_CACHE = %w[ask_user save_memory delete_memory execute_plan].freeze
10
10
 
11
- def initialize(executor: nil, mode: :default)
11
+ def initialize(executor: nil, mode: :default, channel: nil)
12
12
  @executor = executor
13
13
  @mode = mode
14
+ @channel = channel
14
15
  @definitions = []
15
16
  @handlers = {}
16
17
  @cache = {}
@@ -302,8 +303,12 @@ module ConsoleAgent
302
303
  # Ask for plan approval (unless auto-execute)
303
304
  skip_confirmations = auto
304
305
  unless auto
305
- $stdout.print "\e[33m Accept plan? [y/N/a(uto)] \e[0m"
306
- answer = $stdin.gets.to_s.strip.downcase
306
+ if @channel
307
+ answer = @channel.confirm(" Accept plan? [y/N/a(uto)] ")
308
+ else
309
+ $stdout.print "\e[33m Accept plan? [y/N/a(uto)] \e[0m"
310
+ answer = $stdin.gets.to_s.strip.downcase
311
+ end
307
312
  case answer
308
313
  when 'a', 'auto'
309
314
  skip_confirmations = true
@@ -326,8 +331,12 @@ module ConsoleAgent
326
331
 
327
332
  # Per-step confirmation (unless auto-execute or plan-level auto)
328
333
  unless skip_confirmations
329
- $stdout.print "\e[33m Run? [y/N/edit] \e[0m"
330
- step_answer = $stdin.gets.to_s.strip.downcase
334
+ if @channel
335
+ step_answer = @channel.confirm(" Run? [y/N/edit] ")
336
+ else
337
+ $stdout.print "\e[33m Run? [y/N/edit] \e[0m"
338
+ step_answer = $stdin.gets.to_s.strip.downcase
339
+ end
331
340
 
332
341
  case step_answer
333
342
  when 'e', 'edit'
@@ -335,8 +344,12 @@ module ConsoleAgent
335
344
  if edited && edited != step['code']
336
345
  $stdout.puts "\e[33m # Edited code:\e[0m"
337
346
  $stdout.puts highlight_plan_code(edited)
338
- $stdout.print "\e[33m Run edited code? [y/N] \e[0m"
339
- confirm = $stdin.gets.to_s.strip.downcase
347
+ if @channel
348
+ confirm = @channel.confirm(" Run edited code? [y/N] ")
349
+ else
350
+ $stdout.print "\e[33m Run edited code? [y/N] \e[0m"
351
+ confirm = $stdin.gets.to_s.strip.downcase
352
+ end
340
353
  unless confirm == 'y' || confirm == 'yes'
341
354
  feedback = ask_feedback("What would you like changed?")
342
355
  results << "Step #{i + 1}: User declined after edit. Feedback: #{feedback}"
@@ -354,6 +367,17 @@ module ConsoleAgent
354
367
  end
355
368
 
356
369
  exec_result = @executor.execute(step['code'])
370
+
371
+ # On safety error, offer to re-run with guards disabled (console only)
372
+ if @executor.last_safety_error
373
+ if @channel && !@channel.supports_danger?
374
+ results << "Step #{i + 1} (#{step['description']}):\nBLOCKED by safety guard: #{@executor.last_error}. Write operations are not permitted in this channel."
375
+ break
376
+ else
377
+ exec_result = @executor.offer_danger_retry(step['code'])
378
+ end
379
+ end
380
+
357
381
  # Make result available as step1, step2, etc. for subsequent steps
358
382
  @executor.binding_context.local_variable_set(:"step#{i + 1}", exec_result)
359
383
  output = @executor.last_output
@@ -407,18 +431,26 @@ module ConsoleAgent
407
431
  end
408
432
 
409
433
  def ask_feedback(prompt)
410
- $stdout.print "\e[36m #{prompt} > \e[0m"
411
- feedback = $stdin.gets
412
- return '(no feedback provided)' if feedback.nil?
413
- feedback.strip.empty? ? '(no feedback provided)' : feedback.strip
434
+ if @channel
435
+ @channel.prompt(" #{prompt} > ")
436
+ else
437
+ $stdout.print "\e[36m #{prompt} > \e[0m"
438
+ feedback = $stdin.gets
439
+ return '(no feedback provided)' if feedback.nil?
440
+ feedback.strip.empty? ? '(no feedback provided)' : feedback.strip
441
+ end
414
442
  end
415
443
 
416
444
  def ask_user(question)
417
- $stdout.puts "\e[36m ? #{question}\e[0m"
418
- $stdout.print "\e[36m > \e[0m"
419
- answer = $stdin.gets
420
- return '(no answer provided)' if answer.nil?
421
- answer.strip.empty? ? '(no answer provided)' : answer.strip
445
+ if @channel
446
+ @channel.prompt(" ? #{question}\n > ")
447
+ else
448
+ $stdout.puts "\e[36m ? #{question}\e[0m"
449
+ $stdout.print "\e[36m > \e[0m"
450
+ answer = $stdin.gets
451
+ return '(no answer provided)' if answer.nil?
452
+ answer.strip.empty? ? '(no answer provided)' : answer.strip
453
+ end
422
454
  end
423
455
 
424
456
  def register(name:, description:, parameters:, handler:)
@@ -1,3 +1,3 @@
1
1
  module ConsoleAgent
2
- VERSION = '0.10.0'.freeze
2
+ VERSION = '0.11.0'.freeze
3
3
  end
data/lib/console_agent.rb CHANGED
@@ -58,8 +58,8 @@ module ConsoleAgent
58
58
  def status
59
59
  c = configuration
60
60
  key = c.resolved_api_key
61
- masked_key = if key.nil? || key.empty?
62
- "\e[31m(not set)\e[0m"
61
+ masked_key = if key.nil? || key.empty? || key == 'no-key'
62
+ c.provider == :local ? "\e[32m(not required)\e[0m" : "\e[31m(not set)\e[0m"
63
63
  else
64
64
  key[0..6] + '...' + key[-4..-1]
65
65
  end
@@ -69,11 +69,19 @@ module ConsoleAgent
69
69
  lines << " Provider: #{c.provider}"
70
70
  lines << " Model: #{c.resolved_model}"
71
71
  lines << " API key: #{masked_key}"
72
- lines << " Max tokens: #{c.max_tokens}"
72
+ lines << " Local URL: #{c.local_url}" if c.provider == :local
73
+ lines << " Max tokens: #{c.max_tokens || '(auto)'}"
73
74
  lines << " Temperature: #{c.temperature}"
74
75
  lines << " Timeout: #{c.timeout}s"
75
76
  lines << " Max tool rounds:#{c.max_tool_rounds}"
76
77
  lines << " Auto-execute: #{c.auto_execute}"
78
+ guards = c.safety_guards
79
+ if guards.empty?
80
+ lines << " Safe mode: \e[33m(no guards configured)\e[0m"
81
+ else
82
+ status = guards.enabled? ? "\e[32mON\e[0m" : "\e[31mOFF\e[0m"
83
+ lines << " Safe mode: #{status} (#{guards.names.join(', ')})"
84
+ end
77
85
  lines << " Memories: #{c.memories_enabled}"
78
86
  lines << " Session logging:#{session_table_status}"
79
87
  lines << " Debug: #{c.debug}"
@@ -134,6 +142,12 @@ module ConsoleAgent
134
142
  migrations << 'name'
135
143
  end
136
144
 
145
+ unless conn.column_exists?(table, :slack_thread_ts)
146
+ conn.add_column(table, :slack_thread_ts, :string, limit: 255)
147
+ conn.add_index(table, :slack_thread_ts) unless conn.index_exists?(table, :slack_thread_ts)
148
+ migrations << 'slack_thread_ts'
149
+ end
150
+
137
151
  if migrations.empty?
138
152
  $stdout.puts "\e[32mConsoleAgent: #{table} is up to date.\e[0m"
139
153
  else
@@ -1,5 +1,5 @@
1
1
  ConsoleAgent.configure do |config|
2
- # LLM provider: :anthropic or :openai
2
+ # LLM provider: :anthropic, :openai, or :local
3
3
  config.provider = :anthropic
4
4
 
5
5
  # API key (or set ANTHROPIC_API_KEY / OPENAI_API_KEY env var)
@@ -23,6 +23,12 @@ ConsoleAgent.configure do |config|
23
23
  # HTTP timeout in seconds
24
24
  config.timeout = 30
25
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
+
26
32
  # Debug mode: prints full API requests/responses and tool calls to stderr
27
33
  # config.debug = true
28
34
 
@@ -38,4 +44,27 @@ ConsoleAgent.configure do |config|
38
44
  # When nil, all requests are denied. Set credentials or use config.authenticate.
39
45
  # config.admin_username = 'admin'
40
46
  # config.admin_password = 'changeme'
47
+
48
+ # Safety guards: prevent side effects (DB writes, HTTP calls, etc.) during code execution.
49
+ # When enabled, code runs in safe mode by default. Users can toggle with /danger in the REPL.
50
+ #
51
+ # Built-in guard for database writes (works on Rails 5+, all adapters):
52
+ # config.use_builtin_safety_guard :database_writes
53
+ #
54
+ # Built-in guard for HTTP mutations — blocks POST/PUT/PATCH/DELETE via Net::HTTP.
55
+ # Covers most Ruby HTTP libraries (HTTParty, RestClient, Faraday) since they use Net::HTTP:
56
+ # config.use_builtin_safety_guard :http_mutations
57
+ #
58
+ # Allowlist specific hosts or tables so they pass through without blocking:
59
+ # config.use_builtin_safety_guard :http_mutations,
60
+ # allow: [/s3\.amazonaws\.com/, /googleapis\.com/]
61
+ # config.use_builtin_safety_guard :database_writes,
62
+ # allow: ['console_agent_sessions']
63
+ #
64
+ # Built-in guard for mailers — disables ActionMailer delivery:
65
+ # config.use_builtin_safety_guard :mailers
66
+ #
67
+ # config.safety_guard :jobs do |&execute|
68
+ # Sidekiq::Testing.fake! { execute.call }
69
+ # end
41
70
  end
@@ -0,0 +1,7 @@
1
+ namespace :console_agent do
2
+ desc "Start the ConsoleAgent Slack bot (Socket Mode)"
3
+ task slack: :environment do
4
+ require 'console_agent/slack_bot'
5
+ ConsoleAgent::SlackBot.new.start
6
+ end
7
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: console_agent
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.10.0
4
+ version: 0.11.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Cortfr
@@ -98,17 +98,24 @@ files:
98
98
  - app/views/layouts/console_agent/application.html.erb
99
99
  - config/routes.rb
100
100
  - lib/console_agent.rb
101
+ - lib/console_agent/channel/base.rb
102
+ - lib/console_agent/channel/console.rb
103
+ - lib/console_agent/channel/slack.rb
101
104
  - lib/console_agent/configuration.rb
102
105
  - lib/console_agent/console_methods.rb
103
106
  - lib/console_agent/context_builder.rb
107
+ - lib/console_agent/conversation_engine.rb
104
108
  - lib/console_agent/engine.rb
105
109
  - lib/console_agent/executor.rb
106
110
  - lib/console_agent/providers/anthropic.rb
107
111
  - lib/console_agent/providers/base.rb
112
+ - lib/console_agent/providers/local.rb
108
113
  - lib/console_agent/providers/openai.rb
109
114
  - lib/console_agent/railtie.rb
110
115
  - lib/console_agent/repl.rb
116
+ - lib/console_agent/safety_guards.rb
111
117
  - lib/console_agent/session_logger.rb
118
+ - lib/console_agent/slack_bot.rb
112
119
  - lib/console_agent/storage/base.rb
113
120
  - lib/console_agent/storage/file_storage.rb
114
121
  - lib/console_agent/tools/code_tools.rb
@@ -119,6 +126,7 @@ files:
119
126
  - lib/console_agent/version.rb
120
127
  - lib/generators/console_agent/install_generator.rb
121
128
  - lib/generators/console_agent/templates/initializer.rb
129
+ - lib/tasks/console_agent.rake
122
130
  homepage: https://github.com/cortfr/console_agent
123
131
  licenses:
124
132
  - MIT