rubycode 0.1.2 → 0.1.3

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.
Files changed (66) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +4 -0
  3. data/README.md +33 -4
  4. data/config/locales/en.yml +87 -0
  5. data/config/system_prompt.md +54 -0
  6. data/config/tools/done.json +2 -2
  7. data/config/tools/update.json +25 -0
  8. data/config/tools/write.json +21 -0
  9. data/docs/images/demo.png +0 -0
  10. data/lib/rubycode/adapters/ollama.rb +76 -3
  11. data/lib/rubycode/agent_loop.rb +41 -16
  12. data/lib/rubycode/client/approval_handler.rb +70 -0
  13. data/lib/rubycode/client/display_formatter.rb +32 -12
  14. data/lib/rubycode/client/response_handler.rb +20 -12
  15. data/lib/rubycode/client.rb +25 -36
  16. data/lib/rubycode/configuration.rb +8 -1
  17. data/lib/rubycode/database.rb +50 -0
  18. data/lib/rubycode/errors.rb +12 -0
  19. data/lib/rubycode/models/base.rb +68 -0
  20. data/lib/rubycode/models/memory.rb +57 -0
  21. data/lib/rubycode/models.rb +4 -0
  22. data/lib/rubycode/tools/base.rb +1 -10
  23. data/lib/rubycode/tools/bash.rb +10 -7
  24. data/lib/rubycode/tools/read.rb +3 -0
  25. data/lib/rubycode/tools/update.rb +80 -0
  26. data/lib/rubycode/tools/write.rb +57 -0
  27. data/lib/rubycode/tools.rb +4 -0
  28. data/lib/rubycode/version.rb +1 -1
  29. data/lib/rubycode/views/agent_loop/adapter_error.rb +14 -0
  30. data/lib/rubycode/views/agent_loop/iteration_footer.rb +17 -0
  31. data/lib/rubycode/views/agent_loop/iteration_header.rb +24 -0
  32. data/lib/rubycode/views/agent_loop/response_received.rb +17 -0
  33. data/lib/rubycode/views/agent_loop/retry_status.rb +14 -0
  34. data/lib/rubycode/views/agent_loop/thinking_status.rb +17 -0
  35. data/lib/rubycode/views/agent_loop/tool_error.rb +14 -0
  36. data/lib/rubycode/views/agent_loop.rb +8 -0
  37. data/lib/rubycode/views/bash_approval.rb +28 -0
  38. data/lib/rubycode/views/cli/configuration_table.rb +28 -0
  39. data/lib/rubycode/views/cli/error_display.rb +19 -0
  40. data/lib/rubycode/views/cli/error_message.rb +17 -0
  41. data/lib/rubycode/views/cli/exit_message.rb +17 -0
  42. data/lib/rubycode/views/cli/interrupt_message.rb +17 -0
  43. data/lib/rubycode/views/cli/memory_cleared_message.rb +17 -0
  44. data/lib/rubycode/views/cli/ready_message.rb +17 -0
  45. data/lib/rubycode/views/cli/response_box.rb +29 -0
  46. data/lib/rubycode/views/cli.rb +11 -0
  47. data/lib/rubycode/views/formatter/debug_tool_info.rb +17 -0
  48. data/lib/rubycode/views/formatter/info_message.rb +17 -0
  49. data/lib/rubycode/views/formatter/minimal_tool_info.rb +26 -0
  50. data/lib/rubycode/views/formatter/tool_result.rb +20 -0
  51. data/lib/rubycode/views/formatter.rb +7 -0
  52. data/lib/rubycode/views/response_handler/agent_finished.rb +31 -0
  53. data/lib/rubycode/views/response_handler/complete_message.rb +31 -0
  54. data/lib/rubycode/views/response_handler/max_iterations.rb +29 -0
  55. data/lib/rubycode/views/response_handler/max_tool_calls.rb +29 -0
  56. data/lib/rubycode/views/response_handler/tool_injection_warning.rb +17 -0
  57. data/lib/rubycode/views/response_handler.rb +8 -0
  58. data/lib/rubycode/views/skip_notification.rb +15 -0
  59. data/lib/rubycode/views/update_approval.rb +36 -0
  60. data/lib/rubycode/views/welcome.rb +27 -0
  61. data/lib/rubycode/views/write_approval.rb +42 -0
  62. data/lib/rubycode/views.rb +12 -0
  63. data/lib/rubycode.rb +9 -1
  64. data/rubycode_cli.rb +41 -51
  65. metadata +220 -5
  66. data/lib/rubycode/history.rb +0 -39
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "pastel"
4
+
5
+ module RubyCode
6
+ module Views
7
+ # Builds skip notification display
8
+ class SkipNotification
9
+ def self.build(message:)
10
+ pastel = Pastel.new
11
+ pastel.yellow(" ⓘ Skipped: #{message}")
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "pastel"
4
+
5
+ module RubyCode
6
+ module Views
7
+ # Builds file update approval prompt display with diff
8
+ class UpdateApproval
9
+ def self.build(file_path:, old_string:, new_string:)
10
+ pastel = Pastel.new
11
+
12
+ [
13
+ "",
14
+ pastel.yellow("━" * 80),
15
+ pastel.bold("Update Operation - Approval Required"),
16
+ "#{pastel.cyan("File:")} #{file_path}",
17
+ pastel.yellow("─" * 80),
18
+ format_removal_section(pastel, old_string),
19
+ "",
20
+ format_addition_section(pastel, new_string),
21
+ pastel.yellow("━" * 80)
22
+ ].join("\n")
23
+ end
24
+
25
+ def self.format_removal_section(pastel, old_string)
26
+ old_lines = old_string.lines.map { |line| pastel.red(" - #{line.chomp}") }
27
+ [pastel.red("- REMOVE:"), old_lines.join("\n")].join("\n")
28
+ end
29
+
30
+ def self.format_addition_section(pastel, new_string)
31
+ new_lines = new_string.lines.map { |line| pastel.green(" + #{line.chomp}") }
32
+ [pastel.green("+ ADD:"), new_lines.join("\n")].join("\n")
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "pastel"
4
+
5
+ module RubyCode
6
+ module Views
7
+ # Displays welcome message when CLI starts
8
+ class Welcome
9
+ def self.build
10
+ pastel = Pastel.new
11
+ TTY::Box.frame(
12
+ width: 80,
13
+ border: :thick,
14
+ title: { top_left: " RubyCode v#{RubyCode::VERSION} " }
15
+ ) do
16
+ [
17
+ pastel.bold.cyan("AI Ruby/Rails Code Assistant"),
18
+ "",
19
+ "Built with: #{pastel.dim("Ollama + DeepSeek + TTY Toolkit")}",
20
+ pastel.dim("─" * 76),
21
+ "#{pastel.yellow("Commands:")} exit, quit, clear"
22
+ ].join("\n")
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "pastel"
4
+
5
+ module RubyCode
6
+ module Views
7
+ # Builds file write approval prompt display
8
+ class WriteApproval
9
+ def self.build(file_path:, content:)
10
+ pastel = Pastel.new
11
+
12
+ [
13
+ "",
14
+ header_section(pastel),
15
+ file_info_section(pastel, file_path, content),
16
+ pastel.yellow("─" * 80),
17
+ preview_section(content),
18
+ truncation_notice(pastel, content),
19
+ pastel.yellow("━" * 80)
20
+ ].compact.join("\n")
21
+ end
22
+
23
+ def self.header_section(pastel)
24
+ [pastel.yellow("━" * 80), pastel.bold("Write Operation - Approval Required")].join("\n")
25
+ end
26
+
27
+ def self.file_info_section(pastel, file_path, content)
28
+ ["#{pastel.cyan("File:")} #{file_path}", "#{pastel.cyan("Lines:")} #{content.lines.count}"].join("\n")
29
+ end
30
+
31
+ def self.preview_section(content)
32
+ content.lines.first(20).join
33
+ end
34
+
35
+ def self.truncation_notice(pastel, content)
36
+ return "" unless content.lines.count > 20
37
+
38
+ pastel.dim("... (#{content.lines.count - 20} more lines)")
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ # View components for CLI display and user interaction
4
+ require_relative "views/welcome"
5
+ require_relative "views/bash_approval"
6
+ require_relative "views/write_approval"
7
+ require_relative "views/update_approval"
8
+ require_relative "views/skip_notification"
9
+ require_relative "views/cli"
10
+ require_relative "views/agent_loop"
11
+ require_relative "views/formatter"
12
+ require_relative "views/response_handler"
data/lib/rubycode.rb CHANGED
@@ -1,16 +1,19 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "i18n"
3
4
  require_relative "rubycode/version"
4
5
  require_relative "rubycode/errors"
5
6
  require_relative "rubycode/value_objects"
6
7
  require_relative "rubycode/configuration"
7
- require_relative "rubycode/history"
8
+ require_relative "rubycode/database"
9
+ require_relative "rubycode/models"
8
10
  require_relative "rubycode/context_builder"
9
11
  require_relative "rubycode/adapters/base"
10
12
  require_relative "rubycode/adapters/ollama"
11
13
  require_relative "rubycode/tools"
12
14
  require_relative "rubycode/agent_loop"
13
15
  require_relative "rubycode/client"
16
+ require_relative "rubycode/views"
14
17
 
15
18
  # Rubycode is a Ruby-native AI coding agent with pluggable LLM adapters
16
19
  module RubyCode
@@ -26,4 +29,9 @@ module RubyCode
26
29
  def self.config
27
30
  self.configuration ||= Configuration.new
28
31
  end
32
+
33
+ # Configure I18n
34
+ I18n.load_path += Dir[File.join(__dir__, "..", "config", "locales", "*.yml")]
35
+ I18n.backend.load_translations
36
+ I18n.default_locale = :en
29
37
  end
data/rubycode_cli.rb CHANGED
@@ -2,87 +2,77 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require_relative "lib/rubycode"
5
- require "readline"
5
+ require "tty-prompt"
6
6
 
7
- puts "\n#{"=" * 80}"
8
- puts "🚀 RubyCode - AI Ruby/Rails Code Assistant"
9
- puts "=" * 80
7
+ prompt = TTY::Prompt.new
8
+ adapter = :ollama
10
9
 
11
- # Ask for directory
12
- print "\nWhat directory do you want to work on? (default: current directory): "
13
- directory = gets.chomp
14
- directory = Dir.pwd if directory.empty?
10
+ model = "deepseek-v3.1:671b-cloud"
11
+ url = "http://localhost:11434"
12
+
13
+ puts "\n#{RubyCode::Views::Welcome.build}"
14
+
15
+ directory = prompt.ask("What directory do you want to work on?") do |q|
16
+ q.default Dir.pwd
17
+ q.required false
18
+ end
19
+ directory = Dir.pwd if directory.nil? || directory.empty?
15
20
 
16
- # Resolve the full path
17
21
  full_path = File.expand_path(directory)
18
22
 
19
23
  unless Dir.exist?(full_path)
20
- puts "\n❌ Error: Directory '#{full_path}' does not exist!"
24
+ puts RubyCode::Views::Cli::ErrorMessage.build(message: "Directory '#{full_path}' does not exist!")
21
25
  exit 1
22
26
  end
23
27
 
24
- puts "\n📁 Working directory: #{full_path}"
25
-
26
- # Ask if debug mode should be enabled
27
- print "Enable debug mode? (shows JSON requests/responses) [y/N]: "
28
- debug_input = gets.chomp.downcase
29
- debug_mode = %w[y yes].include?(debug_input)
28
+ debug_mode = prompt.yes?("Enable debug mode?") do |q|
29
+ q.default false
30
+ end
30
31
 
31
- # Configure the client
32
32
  RubyCode.configure do |config|
33
- config.adapter = :ollama
34
- config.url = "http://localhost:11434"
35
- config.model = "deepseek-v3.1:671b-cloud"
33
+ config.adapter = adapter
34
+ config.url = url
35
+ config.model = model
36
36
  config.root_path = full_path
37
37
  config.debug = debug_mode
38
38
 
39
- # Enable workaround to force tool-calling for models that don't follow instructions
40
39
  config.enable_tool_injection_workaround = true
41
40
  end
42
41
 
43
- puts "🐛 Debug mode: #{debug_mode ? "ON" : "OFF"}" if debug_mode
42
+ puts RubyCode::Views::Cli::ConfigurationTable.build(
43
+ directory: full_path,
44
+ model: model,
45
+ debug_mode: debug_mode
46
+ )
44
47
 
45
- # Create a client
46
- client = RubyCode::Client.new
48
+ client = RubyCode::Client.new(tty_prompt: prompt)
47
49
 
48
- puts "\n#{"=" * 80}"
49
- puts "✨ Agent initialized! You can now ask questions or request code changes."
50
- puts " Type 'exit' or 'quit' to exit, 'clear' to clear history"
51
- puts "=" * 80
50
+ puts RubyCode::Views::Cli::ReadyMessage.build
52
51
 
53
- # Interactive loop
54
52
  loop do
55
- print "\n💬 You: "
56
- prompt = Readline.readline("", true)
57
-
58
- # Handle empty input
59
- next if prompt.nil? || prompt.strip.empty?
53
+ user_input = begin
54
+ prompt.ask("You: ")
55
+ rescue StandardError
56
+ nil
57
+ end
58
+ break if user_input.nil?
60
59
 
61
- # Handle commands
62
- case prompt.strip.downcase
60
+ case user_input.strip.downcase
63
61
  when "exit", "quit"
64
- puts "\n👋 Goodbye!"
62
+ puts RubyCode::Views::Cli::ExitMessage.build
65
63
  break
66
64
  when "clear"
67
- client.clear_history
68
- puts "\n🗑️ History cleared!"
65
+ client.clear_memory
66
+ puts RubyCode::Views::Cli::MemoryClearedMessage.build
69
67
  next
70
68
  end
71
69
 
72
- puts "\n#{"-" * 80}"
73
-
74
70
  begin
75
- # Get response from agent
76
- response = client.ask(prompt: prompt)
77
-
78
- puts "\n🤖 Agent:"
79
- puts "-" * 80
80
- puts response
81
- puts "-" * 80
71
+ response = client.ask(prompt: user_input)
72
+ puts RubyCode::Views::Cli::ResponseBox.build(response: response)
82
73
  rescue Interrupt
83
- puts "\n\n⚠️ Interrupted! Type 'exit' to quit or continue chatting."
74
+ puts RubyCode::Views::Cli::InterruptMessage.build
84
75
  rescue StandardError => e
85
- puts "\n❌ Error: #{e.message}"
86
- puts e.backtrace.first(3).join("\n")
76
+ puts RubyCode::Views::Cli::ErrorDisplay.build(error: e)
87
77
  end
88
78
  end
metadata CHANGED
@@ -1,15 +1,185 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubycode
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jonas Medeiros
8
8
  bindir: exe
9
9
  cert_chain: []
10
10
  date: 1980-01-02 00:00:00.000000000 Z
11
- dependencies: []
12
- description: Ruby-native AI coding agent with pluggable LLM adapters.
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: i18n
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - "~>"
17
+ - !ruby/object:Gem::Version
18
+ version: '1.14'
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - "~>"
24
+ - !ruby/object:Gem::Version
25
+ version: '1.14'
26
+ - !ruby/object:Gem::Dependency
27
+ name: sequel
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - "~>"
31
+ - !ruby/object:Gem::Version
32
+ version: '5.87'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '5.87'
40
+ - !ruby/object:Gem::Dependency
41
+ name: sqlite3
42
+ requirement: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: '2.4'
47
+ type: :runtime
48
+ prerelease: false
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: '2.4'
54
+ - !ruby/object:Gem::Dependency
55
+ name: pastel
56
+ requirement: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: '0.8'
61
+ type: :runtime
62
+ prerelease: false
63
+ version_requirements: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: '0.8'
68
+ - !ruby/object:Gem::Dependency
69
+ name: tty-box
70
+ requirement: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - "~>"
73
+ - !ruby/object:Gem::Version
74
+ version: '0.7'
75
+ type: :runtime
76
+ prerelease: false
77
+ version_requirements: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - "~>"
80
+ - !ruby/object:Gem::Version
81
+ version: '0.7'
82
+ - !ruby/object:Gem::Dependency
83
+ name: tty-logger
84
+ requirement: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - "~>"
87
+ - !ruby/object:Gem::Version
88
+ version: '0.6'
89
+ type: :runtime
90
+ prerelease: false
91
+ version_requirements: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - "~>"
94
+ - !ruby/object:Gem::Version
95
+ version: '0.6'
96
+ - !ruby/object:Gem::Dependency
97
+ name: tty-markdown
98
+ requirement: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - "~>"
101
+ - !ruby/object:Gem::Version
102
+ version: '0.7'
103
+ type: :runtime
104
+ prerelease: false
105
+ version_requirements: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - "~>"
108
+ - !ruby/object:Gem::Version
109
+ version: '0.7'
110
+ - !ruby/object:Gem::Dependency
111
+ name: tty-pager
112
+ requirement: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - "~>"
115
+ - !ruby/object:Gem::Version
116
+ version: '0.14'
117
+ type: :runtime
118
+ prerelease: false
119
+ version_requirements: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - "~>"
122
+ - !ruby/object:Gem::Version
123
+ version: '0.14'
124
+ - !ruby/object:Gem::Dependency
125
+ name: tty-progressbar
126
+ requirement: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - "~>"
129
+ - !ruby/object:Gem::Version
130
+ version: '0.18'
131
+ type: :runtime
132
+ prerelease: false
133
+ version_requirements: !ruby/object:Gem::Requirement
134
+ requirements:
135
+ - - "~>"
136
+ - !ruby/object:Gem::Version
137
+ version: '0.18'
138
+ - !ruby/object:Gem::Dependency
139
+ name: tty-prompt
140
+ requirement: !ruby/object:Gem::Requirement
141
+ requirements:
142
+ - - "~>"
143
+ - !ruby/object:Gem::Version
144
+ version: '0.23'
145
+ type: :runtime
146
+ prerelease: false
147
+ version_requirements: !ruby/object:Gem::Requirement
148
+ requirements:
149
+ - - "~>"
150
+ - !ruby/object:Gem::Version
151
+ version: '0.23'
152
+ - !ruby/object:Gem::Dependency
153
+ name: tty-spinner
154
+ requirement: !ruby/object:Gem::Requirement
155
+ requirements:
156
+ - - "~>"
157
+ - !ruby/object:Gem::Version
158
+ version: '0.9'
159
+ type: :runtime
160
+ prerelease: false
161
+ version_requirements: !ruby/object:Gem::Requirement
162
+ requirements:
163
+ - - "~>"
164
+ - !ruby/object:Gem::Version
165
+ version: '0.9'
166
+ - !ruby/object:Gem::Dependency
167
+ name: tty-table
168
+ requirement: !ruby/object:Gem::Requirement
169
+ requirements:
170
+ - - "~>"
171
+ - !ruby/object:Gem::Version
172
+ version: '0.12'
173
+ type: :runtime
174
+ prerelease: false
175
+ version_requirements: !ruby/object:Gem::Requirement
176
+ requirements:
177
+ - - "~>"
178
+ - !ruby/object:Gem::Version
179
+ version: '0.12'
180
+ description: Ruby-native AI coding agent with pluggable LLM adapters, persistent memory,
181
+ and file editing tools. Features automatic retry logic, SQLite-backed conversation
182
+ history, and user approval workflows for file modifications.
13
183
  email:
14
184
  - jonas.g.medeiros@gmail.com
15
185
  executables: []
@@ -22,29 +192,74 @@ files:
22
192
  - README.md
23
193
  - Rakefile
24
194
  - USAGE.md
195
+ - config/locales/en.yml
196
+ - config/system_prompt.md
25
197
  - config/tools/bash.json
26
198
  - config/tools/done.json
27
199
  - config/tools/read.json
28
200
  - config/tools/search.json
201
+ - config/tools/update.json
202
+ - config/tools/write.json
203
+ - docs/images/demo.png
29
204
  - lib/rubycode.rb
30
205
  - lib/rubycode/adapters/base.rb
31
206
  - lib/rubycode/adapters/ollama.rb
32
207
  - lib/rubycode/agent_loop.rb
33
208
  - lib/rubycode/client.rb
209
+ - lib/rubycode/client/approval_handler.rb
34
210
  - lib/rubycode/client/display_formatter.rb
35
211
  - lib/rubycode/client/response_handler.rb
36
212
  - lib/rubycode/configuration.rb
37
213
  - lib/rubycode/context_builder.rb
214
+ - lib/rubycode/database.rb
38
215
  - lib/rubycode/errors.rb
39
- - lib/rubycode/history.rb
216
+ - lib/rubycode/models.rb
217
+ - lib/rubycode/models/base.rb
218
+ - lib/rubycode/models/memory.rb
40
219
  - lib/rubycode/tools.rb
41
220
  - lib/rubycode/tools/base.rb
42
221
  - lib/rubycode/tools/bash.rb
43
222
  - lib/rubycode/tools/done.rb
44
223
  - lib/rubycode/tools/read.rb
45
224
  - lib/rubycode/tools/search.rb
225
+ - lib/rubycode/tools/update.rb
226
+ - lib/rubycode/tools/write.rb
46
227
  - lib/rubycode/value_objects.rb
47
228
  - lib/rubycode/version.rb
229
+ - lib/rubycode/views.rb
230
+ - lib/rubycode/views/agent_loop.rb
231
+ - lib/rubycode/views/agent_loop/adapter_error.rb
232
+ - lib/rubycode/views/agent_loop/iteration_footer.rb
233
+ - lib/rubycode/views/agent_loop/iteration_header.rb
234
+ - lib/rubycode/views/agent_loop/response_received.rb
235
+ - lib/rubycode/views/agent_loop/retry_status.rb
236
+ - lib/rubycode/views/agent_loop/thinking_status.rb
237
+ - lib/rubycode/views/agent_loop/tool_error.rb
238
+ - lib/rubycode/views/bash_approval.rb
239
+ - lib/rubycode/views/cli.rb
240
+ - lib/rubycode/views/cli/configuration_table.rb
241
+ - lib/rubycode/views/cli/error_display.rb
242
+ - lib/rubycode/views/cli/error_message.rb
243
+ - lib/rubycode/views/cli/exit_message.rb
244
+ - lib/rubycode/views/cli/interrupt_message.rb
245
+ - lib/rubycode/views/cli/memory_cleared_message.rb
246
+ - lib/rubycode/views/cli/ready_message.rb
247
+ - lib/rubycode/views/cli/response_box.rb
248
+ - lib/rubycode/views/formatter.rb
249
+ - lib/rubycode/views/formatter/debug_tool_info.rb
250
+ - lib/rubycode/views/formatter/info_message.rb
251
+ - lib/rubycode/views/formatter/minimal_tool_info.rb
252
+ - lib/rubycode/views/formatter/tool_result.rb
253
+ - lib/rubycode/views/response_handler.rb
254
+ - lib/rubycode/views/response_handler/agent_finished.rb
255
+ - lib/rubycode/views/response_handler/complete_message.rb
256
+ - lib/rubycode/views/response_handler/max_iterations.rb
257
+ - lib/rubycode/views/response_handler/max_tool_calls.rb
258
+ - lib/rubycode/views/response_handler/tool_injection_warning.rb
259
+ - lib/rubycode/views/skip_notification.rb
260
+ - lib/rubycode/views/update_approval.rb
261
+ - lib/rubycode/views/welcome.rb
262
+ - lib/rubycode/views/write_approval.rb
48
263
  - rubycode_cli.rb
49
264
  - sig/rubycode.rbs
50
265
  homepage: https://github.com/jonasmedeiros/rubycode
@@ -71,5 +286,5 @@ required_rubygems_version: !ruby/object:Gem::Requirement
71
286
  requirements: []
72
287
  rubygems_version: 3.6.9
73
288
  specification_version: 4
74
- summary: Ruby AI code assistant (under development)
289
+ summary: AI coding assistant with autonomous task execution
75
290
  test_files: []
@@ -1,39 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module RubyCode
4
- # Manages conversation history between user and assistant
5
- class History
6
- attr_reader :messages
7
-
8
- def initialize
9
- @messages = []
10
- end
11
-
12
- # Accept either Message objects or keyword arguments for backwards compatibility
13
- def add_message(message = nil, role: nil, content: nil)
14
- if message.is_a?(Message)
15
- @messages << message
16
- elsif role && content
17
- @messages << Message.new(role: role, content: content)
18
- else
19
- raise ArgumentError, "Must provide either a Message object or role: and content: keyword arguments"
20
- end
21
- end
22
-
23
- def to_llm_format
24
- @messages.map(&:to_h)
25
- end
26
-
27
- def clear
28
- @messages = []
29
- end
30
-
31
- def last_user_message
32
- @messages.reverse.find { |msg| msg.role == "user" }
33
- end
34
-
35
- def last_assistant_message
36
- @messages.reverse.find { |msg| msg.role == "assistant" }
37
- end
38
- end
39
- end