aider-ruby 0.1.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 +7 -0
- data/LICENSE +21 -0
- data/README.md +542 -0
- data/bin/aider-ruby +320 -0
- data/lib/aider_ruby/client.rb +571 -0
- data/lib/aider_ruby/config.rb +371 -0
- data/lib/aider_ruby/error_handling.rb +57 -0
- data/lib/aider_ruby/models.rb +204 -0
- data/lib/aider_ruby/task_executor.rb +301 -0
- data/lib/aider_ruby/validation.rb +103 -0
- data/lib/aider_ruby/version.rb +3 -0
- data/lib/aider_ruby.rb +30 -0
- metadata +154 -0
data/bin/aider-ruby
ADDED
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
require 'thor'
|
|
3
|
+
require_relative '../lib/aider_ruby'
|
|
4
|
+
|
|
5
|
+
class AiderRubyCLI < Thor
|
|
6
|
+
desc 'execute MESSAGE', 'Execute aider with a message'
|
|
7
|
+
option :model, aliases: :m, desc: 'Model to use'
|
|
8
|
+
option :files, aliases: :f, type: :array, desc: 'Files to edit'
|
|
9
|
+
option :read, aliases: :r, type: :array, desc: 'Read-only files'
|
|
10
|
+
option :config, aliases: :c, desc: 'Config file path'
|
|
11
|
+
option :env_file, desc: 'Environment file path'
|
|
12
|
+
option :verbose, aliases: :v, type: :boolean, desc: 'Verbose output'
|
|
13
|
+
option :dry_run, type: :boolean, desc: 'Dry run mode'
|
|
14
|
+
option :yes_always, type: :boolean, desc: 'Always say yes'
|
|
15
|
+
option :conventions, desc: 'Conventions file path'
|
|
16
|
+
option :edit_format, desc: 'Edit format (whole, diff, diff-fenced)'
|
|
17
|
+
option :reasoning_effort, desc: 'Reasoning effort (low, medium, high)'
|
|
18
|
+
option :thinking_tokens, desc: 'Thinking tokens budget'
|
|
19
|
+
option :use_temperature, type: :boolean, desc: 'Use temperature sampling'
|
|
20
|
+
option :use_system_prompt, type: :boolean, desc: 'Use system prompt'
|
|
21
|
+
option :use_repo_map, type: :boolean, desc: 'Use repository map'
|
|
22
|
+
def execute(message)
|
|
23
|
+
client = create_client
|
|
24
|
+
result = client.execute(message, cli_options)
|
|
25
|
+
puts result
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
desc 'interactive', 'Start aider in interactive mode'
|
|
29
|
+
option :model, aliases: :m, desc: 'Model to use'
|
|
30
|
+
option :files, aliases: :f, type: :array, desc: 'Files to edit'
|
|
31
|
+
option :read, aliases: :r, type: :array, desc: 'Read-only files'
|
|
32
|
+
option :config, aliases: :c, desc: 'Config file path'
|
|
33
|
+
option :env_file, desc: 'Environment file path'
|
|
34
|
+
option :verbose, aliases: :v, type: :boolean, desc: 'Verbose output'
|
|
35
|
+
def interactive
|
|
36
|
+
client = create_client
|
|
37
|
+
client.interactive(cli_options)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
desc 'from_file MESSAGE_FILE', 'Execute aider with a message file'
|
|
41
|
+
option :model, aliases: :m, desc: 'Model to use'
|
|
42
|
+
option :files, aliases: :f, type: :array, desc: 'Files to edit'
|
|
43
|
+
option :read, aliases: :r, type: :array, desc: 'Read-only files'
|
|
44
|
+
option :config, aliases: :c, desc: 'Config file path'
|
|
45
|
+
option :env_file, desc: 'Environment file path'
|
|
46
|
+
option :verbose, aliases: :v, type: :boolean, desc: 'Verbose output'
|
|
47
|
+
def from_file(message_file)
|
|
48
|
+
client = create_client
|
|
49
|
+
result = client.execute_from_file(message_file, cli_options)
|
|
50
|
+
puts result
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
desc 'apply FILE', 'Apply changes from a file'
|
|
54
|
+
option :model, aliases: :m, desc: 'Model to use'
|
|
55
|
+
option :files, aliases: :f, type: :array, desc: 'Files to edit'
|
|
56
|
+
option :read, aliases: :r, type: :array, desc: 'Read-only files'
|
|
57
|
+
option :config, aliases: :c, desc: 'Config file path'
|
|
58
|
+
option :env_file, desc: 'Environment file path'
|
|
59
|
+
option :verbose, aliases: :v, type: :boolean, desc: 'Verbose output'
|
|
60
|
+
def apply(file)
|
|
61
|
+
client = create_client
|
|
62
|
+
result = client.apply_changes(file, cli_options)
|
|
63
|
+
puts result
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
desc 'repo_map', 'Show repository map'
|
|
67
|
+
option :model, aliases: :m, desc: 'Model to use'
|
|
68
|
+
option :config, aliases: :c, desc: 'Config file path'
|
|
69
|
+
option :env_file, desc: 'Environment file path'
|
|
70
|
+
def repo_map
|
|
71
|
+
client = create_client
|
|
72
|
+
result = client.show_repo_map(cli_options)
|
|
73
|
+
puts result
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
desc 'prompts', 'Show system prompts'
|
|
77
|
+
option :model, aliases: :m, desc: 'Model to use'
|
|
78
|
+
option :config, aliases: :c, desc: 'Config file path'
|
|
79
|
+
option :env_file, desc: 'Environment file path'
|
|
80
|
+
def prompts
|
|
81
|
+
client = create_client
|
|
82
|
+
result = client.show_prompts(cli_options)
|
|
83
|
+
puts result
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
desc 'models [PROVIDER]', 'List available models'
|
|
87
|
+
def models(provider = nil)
|
|
88
|
+
if provider
|
|
89
|
+
models = AiderRuby::Models.list_models(provider)
|
|
90
|
+
puts "Models for #{provider}:"
|
|
91
|
+
models.each { |model| puts " - #{model}" }
|
|
92
|
+
else
|
|
93
|
+
puts 'Available providers:'
|
|
94
|
+
AiderRuby::Models.list_providers.each do |prov|
|
|
95
|
+
puts " #{prov}:"
|
|
96
|
+
AiderRuby::Models.list_models(prov).each { |model| puts " - #{model}" }
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
desc 'model_info MODEL', 'Show information about a model'
|
|
102
|
+
def model_info(model)
|
|
103
|
+
info = AiderRuby::Models.model_info(model)
|
|
104
|
+
if info
|
|
105
|
+
puts "Model: #{info[:name]}"
|
|
106
|
+
puts "Provider: #{info[:provider]}"
|
|
107
|
+
puts "Reasoning: #{info[:reasoning]}"
|
|
108
|
+
puts "Vision: #{info[:vision]}"
|
|
109
|
+
puts "Context Window: #{info[:context_window]} tokens"
|
|
110
|
+
puts 'Cost per 1M tokens:'
|
|
111
|
+
puts " Input: $#{info[:cost_per_token][:input]}"
|
|
112
|
+
puts " Output: $#{info[:cost_per_token][:output]}"
|
|
113
|
+
else
|
|
114
|
+
puts "Model '#{model}' not found"
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
desc 'recommended', 'Show recommended models'
|
|
119
|
+
def recommended
|
|
120
|
+
puts 'Recommended models:'
|
|
121
|
+
AiderRuby::Models.recommended_models.each do |category, model|
|
|
122
|
+
puts " #{category.to_s.gsub('_', ' ').capitalize}: #{model}"
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
desc 'check_update', 'Check for aider updates'
|
|
127
|
+
def check_update
|
|
128
|
+
client = create_client
|
|
129
|
+
result = client.check_update
|
|
130
|
+
puts result
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
desc 'upgrade', 'Upgrade aider'
|
|
134
|
+
def upgrade
|
|
135
|
+
client = create_client
|
|
136
|
+
result = client.upgrade
|
|
137
|
+
puts result
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
desc 'config', 'Show current configuration'
|
|
141
|
+
option :config, aliases: :c, desc: 'Config file path'
|
|
142
|
+
option :env_file, desc: 'Environment file path'
|
|
143
|
+
def config
|
|
144
|
+
client = create_client
|
|
145
|
+
puts 'Current configuration:'
|
|
146
|
+
puts JSON.pretty_generate(client.config.to_h)
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
desc 'task TYPE DESCRIPTION', 'Execute a specific type of task'
|
|
150
|
+
option :model, aliases: :m, desc: 'Model to use'
|
|
151
|
+
option :files, aliases: :f, type: :array, desc: 'Files to edit'
|
|
152
|
+
option :read, aliases: :r, type: :array, desc: 'Read-only files'
|
|
153
|
+
option :config, aliases: :c, desc: 'Config file path'
|
|
154
|
+
option :env_file, desc: 'Environment file path'
|
|
155
|
+
option :verbose, aliases: :v, type: :boolean, desc: 'Verbose output'
|
|
156
|
+
def task(type, description)
|
|
157
|
+
client = create_client
|
|
158
|
+
executor = AiderRuby::TaskExecutor.new(client)
|
|
159
|
+
|
|
160
|
+
case type
|
|
161
|
+
when 'coding'
|
|
162
|
+
result = executor.execute_coding_task(description, options[:files] || [], cli_options)
|
|
163
|
+
when 'refactoring'
|
|
164
|
+
result = executor.execute_refactoring_task(description, options[:files] || [], cli_options)
|
|
165
|
+
when 'debugging'
|
|
166
|
+
result = executor.execute_debugging_task(description, options[:files] || [], cli_options)
|
|
167
|
+
when 'documentation'
|
|
168
|
+
result = executor.execute_documentation_task(description, options[:files] || [], cli_options)
|
|
169
|
+
when 'test_generation'
|
|
170
|
+
result = executor.execute_test_generation_task(description, options[:files] || [], cli_options)
|
|
171
|
+
else
|
|
172
|
+
puts "Unknown task type: #{type}"
|
|
173
|
+
puts 'Available types: coding, refactoring, debugging, documentation, test_generation'
|
|
174
|
+
exit 1
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
puts result
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
desc 'history', 'Show task history'
|
|
181
|
+
option :type, desc: 'Filter by task type'
|
|
182
|
+
option :status, desc: 'Filter by status'
|
|
183
|
+
option :since, desc: 'Filter by date (YYYY-MM-DD)'
|
|
184
|
+
def history
|
|
185
|
+
client = create_client
|
|
186
|
+
executor = AiderRuby::TaskExecutor.new(client)
|
|
187
|
+
|
|
188
|
+
filter = {}
|
|
189
|
+
filter[:type] = options[:type].to_sym if options[:type]
|
|
190
|
+
filter[:status] = options[:status].to_sym if options[:status]
|
|
191
|
+
filter[:since] = Date.parse(options[:since]) if options[:since]
|
|
192
|
+
|
|
193
|
+
tasks = executor.get_task_history(filter)
|
|
194
|
+
|
|
195
|
+
if tasks.empty?
|
|
196
|
+
puts 'No tasks found'
|
|
197
|
+
else
|
|
198
|
+
tasks.each do |task|
|
|
199
|
+
puts "ID: #{task[:id]}"
|
|
200
|
+
puts "Type: #{task[:type]}"
|
|
201
|
+
puts "Status: #{task[:status]}"
|
|
202
|
+
puts "Description: #{task[:description]}"
|
|
203
|
+
puts "Created: #{task[:created_at]}"
|
|
204
|
+
puts '---'
|
|
205
|
+
end
|
|
206
|
+
end
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
desc 'version', 'Show version information'
|
|
210
|
+
def version
|
|
211
|
+
puts "AiderRuby version: #{AiderRuby::VERSION}"
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
desc 'conventions FILE', 'Load coding conventions from a file'
|
|
215
|
+
option :model, aliases: :m, desc: 'Model to use'
|
|
216
|
+
option :files, aliases: :f, type: :array, desc: 'Files to edit'
|
|
217
|
+
option :read, aliases: :r, type: :array, desc: 'Read-only files'
|
|
218
|
+
option :config, aliases: :c, desc: 'Config file path'
|
|
219
|
+
option :env_file, desc: 'Environment file path'
|
|
220
|
+
option :verbose, aliases: :v, type: :boolean, desc: 'Verbose output'
|
|
221
|
+
def conventions(file)
|
|
222
|
+
client = create_client
|
|
223
|
+
client.conventions_file(file)
|
|
224
|
+
puts "Conventions file '#{file}' loaded successfully"
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
desc 'edit_format FORMAT', 'Set edit format (whole, diff, diff-fenced)'
|
|
228
|
+
option :model, aliases: :m, desc: 'Model to use'
|
|
229
|
+
option :files, aliases: :f, type: :array, desc: 'Files to edit'
|
|
230
|
+
option :read, aliases: :r, type: :array, desc: 'Read-only files'
|
|
231
|
+
option :config, aliases: :c, desc: 'Config file path'
|
|
232
|
+
option :env_file, desc: 'Environment file path'
|
|
233
|
+
option :verbose, aliases: :v, type: :boolean, desc: 'Verbose output'
|
|
234
|
+
def edit_format(format)
|
|
235
|
+
client = create_client
|
|
236
|
+
|
|
237
|
+
case format
|
|
238
|
+
when 'whole'
|
|
239
|
+
client.edit_format_whole(true)
|
|
240
|
+
when 'diff'
|
|
241
|
+
client.edit_format_diff(true)
|
|
242
|
+
when 'diff-fenced'
|
|
243
|
+
client.edit_format_diff_fenced(true)
|
|
244
|
+
else
|
|
245
|
+
puts "Unknown edit format: #{format}"
|
|
246
|
+
puts 'Available formats: whole, diff, diff-fenced'
|
|
247
|
+
exit 1
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
puts "Edit format set to: #{format}"
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
desc 'reasoning_settings', 'Show reasoning model settings'
|
|
254
|
+
def reasoning_settings
|
|
255
|
+
puts 'Reasoning Model Settings:'
|
|
256
|
+
puts ' reasoning_effort: low, medium, high'
|
|
257
|
+
puts ' thinking_tokens: number of tokens (e.g., 1000, 1k, 8k)'
|
|
258
|
+
puts ' reasoning_tag: XML tag for reasoning output (e.g., think)'
|
|
259
|
+
puts ''
|
|
260
|
+
puts 'Example usage:'
|
|
261
|
+
puts ' aider-ruby execute "task" --reasoning-effort high --thinking-tokens 8k'
|
|
262
|
+
end
|
|
263
|
+
|
|
264
|
+
private
|
|
265
|
+
|
|
266
|
+
def create_client
|
|
267
|
+
client_options = {}
|
|
268
|
+
|
|
269
|
+
# Load config file if specified
|
|
270
|
+
AiderRuby::Config::Configuration.load_from_file(options[:config]) if options[:config]
|
|
271
|
+
|
|
272
|
+
# Load env file if specified
|
|
273
|
+
AiderRuby::Config::Configuration.load_from_env_file(options[:env_file]) if options[:env_file]
|
|
274
|
+
|
|
275
|
+
# Set model if specified
|
|
276
|
+
client_options[:model] = options[:model] if options[:model]
|
|
277
|
+
|
|
278
|
+
client = AiderRuby::Client::Client.new(client_options)
|
|
279
|
+
|
|
280
|
+
# Add files
|
|
281
|
+
(options[:files] || []).each { |file| client.add_file(file) }
|
|
282
|
+
(options[:read] || []).each { |file| client.add_read_only_file(file) }
|
|
283
|
+
|
|
284
|
+
# Set conventions if specified
|
|
285
|
+
client.conventions_file(options[:conventions]) if options[:conventions]
|
|
286
|
+
|
|
287
|
+
# Set edit format if specified
|
|
288
|
+
case options[:edit_format]
|
|
289
|
+
when 'whole'
|
|
290
|
+
client.edit_format_whole(true)
|
|
291
|
+
when 'diff'
|
|
292
|
+
client.edit_format_diff(true)
|
|
293
|
+
when 'diff-fenced'
|
|
294
|
+
client.edit_format_diff_fenced(true)
|
|
295
|
+
end
|
|
296
|
+
|
|
297
|
+
# Set reasoning settings if specified
|
|
298
|
+
client.reasoning_effort(options[:reasoning_effort]) if options[:reasoning_effort]
|
|
299
|
+
client.thinking_tokens(options[:thinking_tokens]) if options[:thinking_tokens]
|
|
300
|
+
|
|
301
|
+
# Set advanced model settings if specified
|
|
302
|
+
client.use_temperature(options[:use_temperature]) if options.key?(:use_temperature)
|
|
303
|
+
client.use_system_prompt(options[:use_system_prompt]) if options.key?(:use_system_prompt)
|
|
304
|
+
client.use_repo_map(options[:use_repo_map]) if options.key?(:use_repo_map)
|
|
305
|
+
|
|
306
|
+
client
|
|
307
|
+
end
|
|
308
|
+
|
|
309
|
+
def cli_options
|
|
310
|
+
{
|
|
311
|
+
config_file: options[:config],
|
|
312
|
+
env_file: options[:env_file],
|
|
313
|
+
verbose: options[:verbose],
|
|
314
|
+
dry_run: options[:dry_run],
|
|
315
|
+
yes_always: options[:yes_always]
|
|
316
|
+
}.compact
|
|
317
|
+
end
|
|
318
|
+
end
|
|
319
|
+
|
|
320
|
+
AiderRubyCLI.start(ARGV)
|