console_agent 0.5.0 → 0.6.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 35e4cf8ecceb5241ce1b18f2cac6d8a235b3185f7839b2143eca6233390375d5
4
- data.tar.gz: 7ebfc01003d9995ce65645a1f15955747cd59197c891e294d2152f3101fd583c
3
+ metadata.gz: d1d37fc84ac3f2d29832d282e6db1fd394308de2b967843c3a0c9748560a7025
4
+ data.tar.gz: 28bd6c25529dbedfa12d2353a1648304517bab933f0a4f25e91285ccaaf08e10
5
5
  SHA512:
6
- metadata.gz: 1bfdf0d1b5a6278101d7cda640ac710a1aef589e5a1adc4194876404d897a53bcfa27cd423029abc76a117eb6ab2ba13a14e605c4447c1452ab78d0f7b98b960
7
- data.tar.gz: 7589590b8dcbfd4268070ce59da381741ca1643152b2689829d741a6cc325e7d9130576629a3155ba0267fb0ea86623a584f9a6e6c2956143e043da43e551501
6
+ metadata.gz: 6451c8b62eba1159e0233be04dabbc86bcb3b6f1dcbd6cd658c8d5517a27f1ad6a20884d30d87fabcbe75d8a51d12a6dfa2d4a59ed0adb648ce56d3b81765636
7
+ data.tar.gz: 3448b25930e4613a4599698d98ec1c5a2d84b113a3221d98239dc0f09351455be817882b308910bfd8bf01eab00d01670c11256624bb7cd7a30745538095c2ea
data/README.md CHANGED
@@ -59,6 +59,7 @@ The AI calls tools behind the scenes to learn your app — schema, models, assoc
59
59
  | `ai "query"` | One-shot: ask, review code, confirm |
60
60
  | `ai! "query"` | Interactive: ask and keep chatting |
61
61
  | `ai? "query"` | Explain only, never executes |
62
+ | `ai_init` | Generate/update app guide for better context |
62
63
 
63
64
  ### Multi-Step Plans
64
65
 
@@ -112,6 +113,30 @@ ai> how does sharding work?
112
113
 
113
114
  Next time, it already knows — no re-reading files, fewer tokens.
114
115
 
116
+ ### Application Guide
117
+
118
+ Run `ai_init` to have the AI explore your app and generate a guide that gets loaded into every future conversation:
119
+
120
+ ```
121
+ irb> ai_init
122
+ No existing guide. Exploring the app...
123
+ Thinking...
124
+ -> list_models
125
+ 240 models
126
+ -> describe_model("User")
127
+ 119 associations, 6 validations
128
+ -> describe_model("Account")
129
+ 25 associations
130
+ -> search_code("Sharding", dir: "config")
131
+ Found 36 matches
132
+ ...
133
+ Guide saved to .console_agent/console_agent.md (3204 chars)
134
+ ```
135
+
136
+ The guide is a markdown file covering your app's models, relationships, data architecture, and gotchas. Unlike memories (which require a tool call to recall), the guide is injected directly into the system prompt — so the AI starts every session already knowing your app.
137
+
138
+ Run `ai_init` again anytime to update it.
139
+
115
140
  ### Interactive Mode
116
141
 
117
142
  ```
@@ -130,12 +130,26 @@ module ConsoleAgent
130
130
  nil
131
131
  end
132
132
 
133
+ def ai_init
134
+ require 'console_agent/context_builder'
135
+ require 'console_agent/providers/base'
136
+ require 'console_agent/executor'
137
+ require 'console_agent/repl'
138
+
139
+ repl = Repl.new(__console_agent_binding)
140
+ repl.init_guide
141
+ rescue => e
142
+ $stderr.puts "\e[31mConsoleAgent error: #{e.message}\e[0m"
143
+ nil
144
+ end
145
+
133
146
  def ai(query = nil)
134
147
  if query.nil?
135
148
  $stderr.puts "\e[33mUsage: ai \"your question here\"\e[0m"
136
149
  $stderr.puts "\e[33m ai \"query\" - ask + confirm execution\e[0m"
137
150
  $stderr.puts "\e[33m ai! \"query\" - enter interactive mode (or ai! with no args)\e[0m"
138
151
  $stderr.puts "\e[33m ai? \"query\" - explain only, no execution\e[0m"
152
+ $stderr.puts "\e[33m ai_init - generate/update app guide for better AI context\e[0m"
139
153
  $stderr.puts "\e[33m ai_sessions - list recent sessions\e[0m"
140
154
  $stderr.puts "\e[33m ai_resume - resume a session by name or id\e[0m"
141
155
  $stderr.puts "\e[33m ai_name - name a session: ai_name 42, \"my_label\"\e[0m"
@@ -15,10 +15,32 @@ module ConsoleAgent
15
15
  parts = []
16
16
  parts << smart_system_instructions
17
17
  parts << environment_context
18
+ parts << guide_context
18
19
  parts << memory_context
19
20
  parts.compact.join("\n\n")
20
21
  end
21
22
 
23
+ def environment_context
24
+ lines = ["## Environment"]
25
+ lines << "- Ruby #{RUBY_VERSION}"
26
+ lines << "- Rails #{Rails.version}" if defined?(Rails) && Rails.respond_to?(:version)
27
+
28
+ if defined?(ActiveRecord::Base) && ActiveRecord::Base.connected?
29
+ adapter = ActiveRecord::Base.connection.adapter_name rescue 'unknown'
30
+ lines << "- Database adapter: #{adapter}"
31
+ end
32
+
33
+ if defined?(Bundler)
34
+ key_gems = %w[devise cancancan pundit sidekiq delayed_job resque
35
+ paperclip carrierwave activestorage shrine
36
+ pg mysql2 sqlite3 mongoid]
37
+ loaded = key_gems.select { |g| Gem.loaded_specs.key?(g) }
38
+ lines << "- Key gems: #{loaded.join(', ')}" unless loaded.empty?
39
+ end
40
+
41
+ lines.join("\n")
42
+ end
43
+
22
44
  private
23
45
 
24
46
  def smart_system_instructions
@@ -67,25 +89,14 @@ module ConsoleAgent
67
89
  PROMPT
68
90
  end
69
91
 
70
- def environment_context
71
- lines = ["## Environment"]
72
- lines << "- Ruby #{RUBY_VERSION}"
73
- lines << "- Rails #{Rails.version}" if defined?(Rails) && Rails.respond_to?(:version)
74
-
75
- if defined?(ActiveRecord::Base) && ActiveRecord::Base.connected?
76
- adapter = ActiveRecord::Base.connection.adapter_name rescue 'unknown'
77
- lines << "- Database adapter: #{adapter}"
78
- end
79
-
80
- if defined?(Bundler)
81
- key_gems = %w[devise cancancan pundit sidekiq delayed_job resque
82
- paperclip carrierwave activestorage shrine
83
- pg mysql2 sqlite3 mongoid]
84
- loaded = key_gems.select { |g| Gem.loaded_specs.key?(g) }
85
- lines << "- Key gems: #{loaded.join(', ')}" unless loaded.empty?
86
- end
92
+ def guide_context
93
+ content = ConsoleAgent.storage.read(ConsoleAgent::GUIDE_KEY)
94
+ return nil if content.nil? || content.strip.empty?
87
95
 
88
- lines.join("\n")
96
+ "## Application Guide\n\n#{content.strip}"
97
+ rescue => e
98
+ ConsoleAgent.logger.debug("ConsoleAgent: guide context failed: #{e.message}")
99
+ nil
89
100
  end
90
101
 
91
102
  def memory_context
@@ -15,7 +15,7 @@ module ConsoleAgent
15
15
 
16
16
  # Welcome message
17
17
  if $stdout.respond_to?(:tty?) && $stdout.tty?
18
- $stdout.puts "\e[36m[ConsoleAgent] AI assistant loaded. Try: ai \"show me all tables\"\e[0m"
18
+ $stdout.puts "\e[36m[ConsoleAgent v#{ConsoleAgent::VERSION}] AI assistant loaded. Try: ai \"show me all tables\"\e[0m"
19
19
  end
20
20
 
21
21
  # Pre-build context in background
@@ -90,6 +90,62 @@ module ConsoleAgent
90
90
  nil
91
91
  end
92
92
 
93
+ def init_guide
94
+ storage = ConsoleAgent.storage
95
+ existing_guide = begin
96
+ content = storage.read(ConsoleAgent::GUIDE_KEY)
97
+ (content && !content.strip.empty?) ? content.strip : nil
98
+ rescue
99
+ nil
100
+ end
101
+
102
+ if existing_guide
103
+ $stdout.puts "\e[36m Existing guide found (#{existing_guide.length} chars). Will update.\e[0m"
104
+ else
105
+ $stdout.puts "\e[36m No existing guide. Exploring the app...\e[0m"
106
+ end
107
+
108
+ require 'console_agent/tools/registry'
109
+ init_tools = Tools::Registry.new(mode: :init)
110
+ sys_prompt = init_system_prompt(existing_guide)
111
+ messages = [{ role: :user, content: "Explore this Rails application and generate the application guide." }]
112
+
113
+ # Temporarily increase timeout — init conversations are large
114
+ original_timeout = ConsoleAgent.configuration.timeout
115
+ ConsoleAgent.configuration.timeout = [original_timeout, 120].max
116
+
117
+ result, _ = send_query_with_tools(messages, system_prompt: sys_prompt, tools_override: init_tools)
118
+
119
+ guide_text = result.text.to_s.strip
120
+ # Strip markdown code fences if the LLM wrapped the response
121
+ guide_text = guide_text.sub(/\A```(?:markdown)?\s*\n?/, '').sub(/\n?```\s*\z/, '')
122
+ # Strip LLM preamble/thinking before the actual guide content
123
+ guide_text = guide_text.sub(/\A.*?(?=^#\s)/m, '') if guide_text =~ /^#\s/m
124
+
125
+ if guide_text.empty?
126
+ $stdout.puts "\e[33m No guide content generated.\e[0m"
127
+ return nil
128
+ end
129
+
130
+ storage.write(ConsoleAgent::GUIDE_KEY, guide_text)
131
+
132
+ path = storage.respond_to?(:root_path) ? File.join(storage.root_path, ConsoleAgent::GUIDE_KEY) : ConsoleAgent::GUIDE_KEY
133
+ $stdout.puts "\e[32m Guide saved to #{path} (#{guide_text.length} chars)\e[0m"
134
+ display_usage(result)
135
+ nil
136
+ rescue Interrupt
137
+ $stdout.puts "\n\e[33m Interrupted.\e[0m"
138
+ nil
139
+ rescue Providers::ProviderError => e
140
+ $stderr.puts "\e[31mConsoleAgent Error: #{e.message}\e[0m"
141
+ nil
142
+ rescue => e
143
+ $stderr.puts "\e[31mConsoleAgent Error: #{e.class}: #{e.message}\e[0m"
144
+ nil
145
+ ensure
146
+ ConsoleAgent.configuration.timeout = original_timeout if original_timeout
147
+ end
148
+
93
149
  def interactive
94
150
  init_interactive_state
95
151
  interactive_loop
@@ -330,6 +386,50 @@ module ConsoleAgent
330
386
  @context ||= context_builder.build
331
387
  end
332
388
 
389
+ def init_system_prompt(existing_guide)
390
+ env = context_builder.environment_context
391
+
392
+ prompt = <<~PROMPT
393
+ You are a Rails application analyst. Your job is to explore this Rails app using the
394
+ available tools and produce a concise markdown guide that will be injected into future
395
+ AI assistant sessions.
396
+
397
+ #{env}
398
+
399
+ EXPLORATION STRATEGY — be efficient to avoid timeouts:
400
+ 1. Start with list_models to see all models and their associations
401
+ 2. Pick the 5-8 CORE models and call describe_model on those only
402
+ 3. Call describe_table on only 3-5 key tables (skip tables whose models already told you enough)
403
+ 4. Use search_code sparingly — only for specific patterns you suspect (sharding, STI, concerns)
404
+ 5. Use read_file only when you need to understand a specific pattern (read small sections, not whole files)
405
+ 6. Do NOT exhaustively describe every table or model — focus on what's important
406
+
407
+ IMPORTANT: Keep your total tool calls under 20. Prioritize breadth over depth.
408
+
409
+ Produce a markdown document with these sections:
410
+ - **Application Overview**: What the app does, key domain concepts
411
+ - **Key Models & Relationships**: Core models and how they relate
412
+ - **Data Architecture**: Important tables, notable columns, any partitioning/sharding
413
+ - **Important Patterns**: Custom concerns, service objects, key abstractions
414
+ - **Common Maintenance Tasks**: Typical console operations for this app
415
+ - **Gotchas**: Non-obvious behaviors, tricky associations, known quirks
416
+
417
+ Keep it concise — aim for 1-2 pages. Focus on what a console user needs to know.
418
+ Do NOT wrap the output in markdown code fences.
419
+ PROMPT
420
+
421
+ if existing_guide
422
+ prompt += <<~UPDATE
423
+
424
+ Here is the existing guide. Update and merge with any new findings:
425
+
426
+ #{existing_guide}
427
+ UPDATE
428
+ end
429
+
430
+ prompt.strip
431
+ end
432
+
333
433
  def send_query(query, conversation: nil)
334
434
  ConsoleAgent.configuration.validate!
335
435
 
@@ -342,45 +442,43 @@ module ConsoleAgent
342
442
  send_query_with_tools(messages)
343
443
  end
344
444
 
345
- def send_query_with_tools(messages)
445
+ def send_query_with_tools(messages, system_prompt: nil, tools_override: nil)
346
446
  require 'console_agent/tools/registry'
347
- tools = Tools::Registry.new(executor: @executor)
447
+ tools = tools_override || Tools::Registry.new(executor: @executor)
448
+ active_system_prompt = system_prompt || context
348
449
  max_rounds = ConsoleAgent.configuration.max_tool_rounds
349
450
  total_input = 0
350
451
  total_output = 0
351
452
  result = nil
352
453
  new_messages = [] # Track messages added during tool use
454
+ last_thinking = nil
455
+ last_tool_names = []
353
456
 
354
457
  exhausted = false
355
458
 
356
459
  max_rounds.times do |round|
357
460
  if round == 0
358
461
  $stdout.puts "\e[2m Thinking...\e[0m"
462
+ else
463
+ # Show buffered thinking text before the "Calling LLM" line
464
+ if last_thinking
465
+ last_thinking.split("\n").each do |line|
466
+ $stdout.puts "\e[2m #{line}\e[0m"
467
+ end
468
+ end
469
+ $stdout.puts "\e[2m #{llm_status(round, messages, total_input, last_thinking, last_tool_names)}\e[0m"
359
470
  end
360
471
 
361
- begin
362
- result = with_escape_monitoring do
363
- provider.chat_with_tools(messages, tools: tools, system_prompt: context)
364
- end
365
- rescue Interrupt
366
- redirect = prompt_for_redirect
367
- if redirect
368
- messages << { role: :user, content: redirect }
369
- new_messages << messages.last
370
- next
371
- else
372
- raise
373
- end
472
+ result = with_escape_monitoring do
473
+ provider.chat_with_tools(messages, tools: tools, system_prompt: active_system_prompt)
374
474
  end
375
475
  total_input += result.input_tokens || 0
376
476
  total_output += result.output_tokens || 0
377
477
 
378
478
  break unless result.tool_use?
379
479
 
380
- # Show what the LLM is thinking (if it returned text alongside tool calls)
381
- if result.text && !result.text.strip.empty?
382
- $stdout.puts "\e[2m #{result.text.strip}\e[0m"
383
- end
480
+ # Buffer thinking text for display before next LLM call
481
+ last_thinking = (result.text && !result.text.strip.empty?) ? result.text.strip : nil
384
482
 
385
483
  # Add assistant message with tool calls to conversation
386
484
  assistant_msg = provider.format_assistant_message(result)
@@ -388,6 +486,7 @@ module ConsoleAgent
388
486
  new_messages << assistant_msg
389
487
 
390
488
  # Execute each tool and show progress
489
+ last_tool_names = result.tool_calls.map { |tc| tc[:name] }
391
490
  result.tool_calls.each do |tc|
392
491
  # ask_user and execute_plan handle their own display
393
492
  if tc[:name] == 'ask_user' || tc[:name] == 'execute_plan'
@@ -419,7 +518,7 @@ module ConsoleAgent
419
518
  if exhausted
420
519
  $stdout.puts "\e[33m Hit tool round limit (#{max_rounds}). Forcing final answer. Increase with: ConsoleAgent.configure { |c| c.max_tool_rounds = 200 }\e[0m"
421
520
  messages << { role: :user, content: "You've used all available tool rounds. Please provide your best answer now based on what you've learned so far." }
422
- result = provider.chat(messages, system_prompt: context)
521
+ result = provider.chat(messages, system_prompt: active_system_prompt)
423
522
  total_input += result.input_tokens || 0
424
523
  total_output += result.output_tokens || 0
425
524
  end
@@ -477,13 +576,29 @@ module ConsoleAgent
477
576
  end
478
577
  end
479
578
 
480
- def prompt_for_redirect
481
- $stdout.puts "\n\e[33m Interrupted. What should the AI do differently?\e[0m"
482
- $stdout.puts "\e[2m (Press Enter with no input to abort entirely)\e[0m"
483
- $stdout.print "\e[33m redirect> \e[0m"
484
- input = $stdin.gets
485
- return nil if input.nil? || input.strip.empty?
486
- input.strip
579
+
580
+ def llm_status(round, messages, tokens_so_far, last_thinking = nil, last_tool_names = [])
581
+ status = "Calling LLM (round #{round + 1}, #{messages.length} msgs"
582
+ status += ", ~#{format_tokens(tokens_so_far)} ctx" if tokens_so_far > 0
583
+ status += ")"
584
+ if !last_thinking && last_tool_names.any?
585
+ # Summarize tools when there's no thinking text
586
+ counts = last_tool_names.tally
587
+ summary = counts.map { |name, n| n > 1 ? "#{name} x#{n}" : name }.join(", ")
588
+ status += " after #{summary}"
589
+ end
590
+ status += "..."
591
+ status
592
+ end
593
+
594
+ def format_tokens(count)
595
+ if count >= 1_000_000
596
+ "#{(count / 1_000_000.0).round(1)}M"
597
+ elsif count >= 1_000
598
+ "#{(count / 1_000.0).round(1)}K"
599
+ else
600
+ count.to_s
601
+ end
487
602
  end
488
603
 
489
604
  def format_tool_args(name, args)
@@ -547,8 +662,12 @@ module ConsoleAgent
547
662
  lines = result.split("\n")
548
663
  "#{lines.length} files"
549
664
  when 'read_file'
550
- lines = result.split("\n")
551
- "#{lines.length} lines"
665
+ if result =~ /^Lines (\d+)-(\d+) of (\d+):/
666
+ "lines #{$1}-#{$2} of #{$3}"
667
+ else
668
+ lines = result.split("\n")
669
+ "#{lines.length} lines"
670
+ end
552
671
  when 'search_code'
553
672
  if result.start_with?('Found')
554
673
  result.split("\n").first
@@ -1,7 +1,7 @@
1
1
  module ConsoleAgent
2
2
  module Tools
3
3
  class CodeTools
4
- MAX_FILE_LINES = 200
4
+ MAX_FILE_LINES = 500
5
5
  MAX_LIST_ENTRIES = 100
6
6
  MAX_SEARCH_RESULTS = 50
7
7
 
@@ -28,7 +28,7 @@ module ConsoleAgent
28
28
  "Error listing files: #{e.message}"
29
29
  end
30
30
 
31
- def read_file(path)
31
+ def read_file(path, start_line: nil, end_line: nil)
32
32
  return "Error: path is required." if path.nil? || path.strip.empty?
33
33
 
34
34
  root = rails_root
@@ -45,12 +45,24 @@ module ConsoleAgent
45
45
  return "File '#{path}' not found." unless File.exist?(full_path)
46
46
  return "Error: '#{path}' is a directory, not a file." if File.directory?(full_path)
47
47
 
48
- lines = File.readlines(full_path)
49
- if lines.length > MAX_FILE_LINES
50
- numbered = lines.first(MAX_FILE_LINES).each_with_index.map { |line, i| "#{i + 1}: #{line}" }
51
- numbered.join + "\n... truncated (#{lines.length} total lines, showing first #{MAX_FILE_LINES})"
48
+ all_lines = File.readlines(full_path)
49
+ total = all_lines.length
50
+
51
+ # Apply line range if specified (1-based, inclusive)
52
+ if start_line || end_line
53
+ s = [(start_line || 1).to_i, 1].max
54
+ e = [(end_line || total).to_i, total].min
55
+ return "Error: start_line (#{s}) is beyond end of file (#{total} lines)." if s > total
56
+ lines = all_lines[(s - 1)..(e - 1)] || []
57
+ offset = s - 1
58
+ numbered = lines.each_with_index.map { |line, i| "#{offset + i + 1}: #{line}" }
59
+ header = "Lines #{s}-#{[e, s + lines.length - 1].min} of #{total}:\n"
60
+ header + numbered.join
61
+ elsif total > MAX_FILE_LINES
62
+ numbered = all_lines.first(MAX_FILE_LINES).each_with_index.map { |line, i| "#{i + 1}: #{line}" }
63
+ numbered.join + "\n... truncated (#{total} total lines, showing first #{MAX_FILE_LINES}). Use start_line/end_line to read specific sections."
52
64
  else
53
- lines.each_with_index.map { |line, i| "#{i + 1}: #{line}" }.join
65
+ all_lines.each_with_index.map { |line, i| "#{i + 1}: #{line}" }.join
54
66
  end
55
67
  rescue => e
56
68
  "Error reading file '#{path}': #{e.message}"
@@ -8,8 +8,9 @@ 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)
11
+ def initialize(executor: nil, mode: :default)
12
12
  @executor = executor
13
+ @mode = mode
13
14
  @definitions = []
14
15
  @handlers = {}
15
16
  @cache = {}
@@ -142,15 +143,17 @@ module ConsoleAgent
142
143
 
143
144
  register(
144
145
  name: 'read_file',
145
- description: 'Read the contents of a file in this Rails app. Capped at 200 lines.',
146
+ description: 'Read the contents of a file in this Rails app. Returns up to 500 lines by default. Use start_line/end_line to read specific sections of large files.',
146
147
  parameters: {
147
148
  'type' => 'object',
148
149
  'properties' => {
149
- 'path' => { 'type' => 'string', 'description' => 'Relative file path (e.g. "app/models/user.rb")' }
150
+ 'path' => { 'type' => 'string', 'description' => 'Relative file path (e.g. "app/models/user.rb")' },
151
+ 'start_line' => { 'type' => 'integer', 'description' => 'First line to read (1-based). Optional — omit to start from beginning.' },
152
+ 'end_line' => { 'type' => 'integer', 'description' => 'Last line to read (1-based, inclusive). Optional — omit to read to end.' }
150
153
  },
151
154
  'required' => ['path']
152
155
  },
153
- handler: ->(args) { code.read_file(args['path']) }
156
+ handler: ->(args) { code.read_file(args['path'], start_line: args['start_line'], end_line: args['end_line']) }
154
157
  )
155
158
 
156
159
  register(
@@ -167,21 +170,23 @@ module ConsoleAgent
167
170
  handler: ->(args) { code.search_code(args['query'], args['directory']) }
168
171
  )
169
172
 
170
- register(
171
- name: 'ask_user',
172
- description: 'Ask the console user a clarifying question. Use this when you need specific information to write accurate code (e.g. which user they are, which record to target, what value to use). Do NOT generate placeholder values like YOUR_USER_ID — ask instead.',
173
- parameters: {
174
- 'type' => 'object',
175
- 'properties' => {
176
- 'question' => { 'type' => 'string', 'description' => 'The question to ask the user' }
173
+ unless @mode == :init
174
+ register(
175
+ name: 'ask_user',
176
+ description: 'Ask the console user a clarifying question. Use this when you need specific information to write accurate code (e.g. which user they are, which record to target, what value to use). Do NOT generate placeholder values like YOUR_USER_ID — ask instead.',
177
+ parameters: {
178
+ 'type' => 'object',
179
+ 'properties' => {
180
+ 'question' => { 'type' => 'string', 'description' => 'The question to ask the user' }
181
+ },
182
+ 'required' => ['question']
177
183
  },
178
- 'required' => ['question']
179
- },
180
- handler: ->(args) { ask_user(args['question']) }
181
- )
184
+ handler: ->(args) { ask_user(args['question']) }
185
+ )
182
186
 
183
- register_memory_tools
184
- register_execute_plan
187
+ register_memory_tools
188
+ register_execute_plan
189
+ end
185
190
  end
186
191
 
187
192
  def register_memory_tools
@@ -1,3 +1,3 @@
1
1
  module ConsoleAgent
2
- VERSION = '0.5.0'.freeze
2
+ VERSION = '0.6.0'.freeze
3
3
  end
data/lib/console_agent.rb CHANGED
@@ -2,6 +2,8 @@ require 'console_agent/version'
2
2
  require 'console_agent/configuration'
3
3
 
4
4
  module ConsoleAgent
5
+ GUIDE_KEY = 'console_agent.md'.freeze
6
+
5
7
  class << self
6
8
  def configuration
7
9
  @configuration ||= Configuration.new
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.5.0
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Cortfr