aia 0.9.11 → 0.9.12
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 +4 -4
- data/.version +1 -1
- data/CHANGELOG.md +66 -2
- data/README.md +133 -4
- data/docs/advanced-prompting.md +721 -0
- data/docs/cli-reference.md +582 -0
- data/docs/configuration.md +347 -0
- data/docs/contributing.md +332 -0
- data/docs/directives-reference.md +490 -0
- data/docs/examples/index.md +277 -0
- data/docs/examples/mcp/index.md +479 -0
- data/docs/examples/prompts/analysis/index.md +78 -0
- data/docs/examples/prompts/automation/index.md +108 -0
- data/docs/examples/prompts/development/index.md +125 -0
- data/docs/examples/prompts/index.md +333 -0
- data/docs/examples/prompts/learning/index.md +127 -0
- data/docs/examples/prompts/writing/index.md +62 -0
- data/docs/examples/tools/index.md +292 -0
- data/docs/faq.md +414 -0
- data/docs/guides/available-models.md +366 -0
- data/docs/guides/basic-usage.md +477 -0
- data/docs/guides/chat.md +474 -0
- data/docs/guides/executable-prompts.md +417 -0
- data/docs/guides/first-prompt.md +454 -0
- data/docs/guides/getting-started.md +455 -0
- data/docs/guides/image-generation.md +507 -0
- data/docs/guides/index.md +46 -0
- data/docs/guides/models.md +507 -0
- data/docs/guides/tools.md +856 -0
- data/docs/index.md +173 -0
- data/docs/installation.md +238 -0
- data/docs/mcp-integration.md +612 -0
- data/docs/prompt_management.md +579 -0
- data/docs/security.md +629 -0
- data/docs/tools-and-mcp-examples.md +1186 -0
- data/docs/workflows-and-pipelines.md +563 -0
- data/examples/tools/mcp/github_mcp_server.json +11 -0
- data/examples/tools/mcp/imcp.json +7 -0
- data/lib/aia/chat_processor_service.rb +19 -3
- data/lib/aia/config/base.rb +224 -0
- data/lib/aia/config/cli_parser.rb +409 -0
- data/lib/aia/config/defaults.rb +88 -0
- data/lib/aia/config/file_loader.rb +131 -0
- data/lib/aia/config/validator.rb +184 -0
- data/lib/aia/config.rb +10 -860
- data/lib/aia/directive_processor.rb +27 -372
- data/lib/aia/directives/configuration.rb +114 -0
- data/lib/aia/directives/execution.rb +37 -0
- data/lib/aia/directives/models.rb +178 -0
- data/lib/aia/directives/registry.rb +120 -0
- data/lib/aia/directives/utility.rb +70 -0
- data/lib/aia/directives/web_and_file.rb +71 -0
- data/lib/aia/prompt_handler.rb +23 -3
- data/lib/aia/ruby_llm_adapter.rb +307 -128
- data/lib/aia/session.rb +27 -14
- data/lib/aia/utility.rb +12 -8
- data/lib/aia.rb +11 -2
- data/lib/extensions/ruby_llm/.irbrc +56 -0
- data/mkdocs.yml +165 -0
- metadata +77 -20
- /data/{images → docs/assets/images}/aia.png +0 -0
@@ -2,119 +2,58 @@
|
|
2
2
|
|
3
3
|
require 'active_support/all'
|
4
4
|
require 'faraday'
|
5
|
-
require 'word_wrapper'
|
5
|
+
require 'word_wrapper'
|
6
|
+
require_relative 'directives/registry'
|
6
7
|
|
7
8
|
module AIA
|
8
9
|
class DirectiveProcessor
|
9
10
|
using Refinements
|
10
11
|
|
11
|
-
PUREMD_API_KEY = ENV.fetch('PUREMD_API_KEY', nil)
|
12
12
|
EXCLUDED_METHODS = %w[ run initialize private? ]
|
13
|
-
@descriptions = {}
|
14
|
-
@aliases = {}
|
15
|
-
|
16
|
-
class << self
|
17
|
-
attr_reader :descriptions, :aliases
|
18
|
-
|
19
|
-
def desc(description, method_name = nil)
|
20
|
-
@last_description = description
|
21
|
-
@descriptions[method_name.to_s] = description if method_name
|
22
|
-
nil
|
23
|
-
end
|
24
|
-
|
25
|
-
def method_added(method_name)
|
26
|
-
if @last_description
|
27
|
-
@descriptions[method_name.to_s] = @last_description
|
28
|
-
@last_description = nil
|
29
|
-
end
|
30
|
-
super if defined?(super)
|
31
|
-
end
|
32
|
-
|
33
|
-
def build_aliases(private_methods)
|
34
|
-
private_methods.each do |method_name|
|
35
|
-
method = instance_method(method_name)
|
36
|
-
|
37
|
-
@aliases[method_name] = []
|
38
|
-
|
39
|
-
private_methods.each do |other_method_name|
|
40
|
-
next if method_name == other_method_name
|
41
|
-
|
42
|
-
other_method = instance_method(other_method_name)
|
43
|
-
|
44
|
-
if method == other_method
|
45
|
-
@aliases[method_name] << other_method_name
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|
51
13
|
|
52
14
|
def initialize
|
53
|
-
@prefix_size
|
15
|
+
@prefix_size = PromptManager::Prompt::DIRECTIVE_SIGNAL.size
|
54
16
|
@included_files = []
|
17
|
+
Directives::WebAndFile.included_files = @included_files
|
55
18
|
end
|
56
19
|
|
57
|
-
def directive?(
|
58
|
-
|
59
|
-
content = if a_string.is_a?(RubyLLM::Message)
|
60
|
-
a_string.content rescue a_string.to_s
|
61
|
-
else
|
62
|
-
a_string.to_s
|
63
|
-
end
|
64
|
-
|
65
|
-
content.strip.start_with?(PromptManager::Prompt::DIRECTIVE_SIGNAL)
|
20
|
+
def directive?(string)
|
21
|
+
Directives::Registry.directive?(string)
|
66
22
|
end
|
67
23
|
|
68
|
-
|
69
|
-
|
70
|
-
return a_string unless directive?(a_string)
|
24
|
+
def process(string, context_manager)
|
25
|
+
return string unless directive?(string)
|
71
26
|
|
72
|
-
|
73
|
-
|
74
|
-
a_string.content rescue a_string.to_s
|
27
|
+
content = if string.is_a?(RubyLLM::Message)
|
28
|
+
string.content rescue string.to_s
|
75
29
|
else
|
76
|
-
|
30
|
+
string.to_s
|
77
31
|
end
|
78
32
|
|
79
33
|
key = content.strip
|
80
34
|
sans_prefix = key[@prefix_size..]
|
81
|
-
args
|
35
|
+
args = sans_prefix.split(' ')
|
82
36
|
method_name = args.shift.downcase
|
83
37
|
|
84
|
-
|
85
|
-
return "Error: #{method_name} is not a valid directive: #{key}"
|
86
|
-
elsif respond_to?(method_name, true)
|
87
|
-
return send(method_name, args, context_manager)
|
88
|
-
else
|
89
|
-
return "Error: Unknown directive '#{key}'"
|
90
|
-
end
|
38
|
+
Directives::Registry.process(method_name, args, context_manager)
|
91
39
|
end
|
92
40
|
|
93
41
|
def run(directives)
|
94
42
|
return {} if directives.nil? || directives.empty?
|
43
|
+
|
95
44
|
directives.each do |key, _|
|
96
45
|
sans_prefix = key[@prefix_size..]
|
97
|
-
args
|
46
|
+
args = sans_prefix.split(' ')
|
98
47
|
method_name = args.shift.downcase
|
99
48
|
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
elsif respond_to?(method_name, true)
|
104
|
-
directives[key] = send(method_name, args)
|
105
|
-
else
|
106
|
-
directives[key] = "Error: Unknown directive '#{key}'"
|
107
|
-
end
|
49
|
+
# Use the new module-based directive system
|
50
|
+
# Pass nil as context_manager since it's not available at the prompt processing level
|
51
|
+
directives[key] = Directives::Registry.process(method_name, args, nil)
|
108
52
|
end
|
109
53
|
|
110
54
|
directives
|
111
55
|
end
|
112
56
|
|
113
|
-
|
114
|
-
#####################################################
|
115
|
-
## Directives are implemented as private methods
|
116
|
-
## All directives return a String. It can be empty.
|
117
|
-
#
|
118
57
|
private
|
119
58
|
|
120
59
|
def private?(method_name)
|
@@ -125,304 +64,20 @@ module AIA
|
|
125
64
|
## Directives ##
|
126
65
|
################
|
127
66
|
|
67
|
+
# All directive implementations are now in separate modules
|
68
|
+
# and are accessed through the Registry
|
128
69
|
|
129
|
-
|
130
|
-
def
|
131
|
-
if
|
132
|
-
|
133
|
-
else
|
134
|
-
url = `echo #{args.shift}`.strip
|
135
|
-
puremd_url = "https://pure.md/#{url}"
|
136
|
-
|
137
|
-
response = Faraday.get(puremd_url) do |req|
|
138
|
-
req.headers['x-puremd-api-token'] = PUREMD_API_KEY
|
139
|
-
end
|
140
|
-
|
141
|
-
if 200 == response.status
|
142
|
-
response.body
|
143
|
-
else
|
144
|
-
"Error: wtatus was #{r.status}\n#{ap response}"
|
145
|
-
end
|
146
|
-
end
|
147
|
-
end
|
148
|
-
|
149
|
-
desc "Specify the next prompt ID to process after this one"
|
150
|
-
def next(args = [], context_manager=nil)
|
151
|
-
if args.empty?
|
152
|
-
ap AIA.config.next
|
153
|
-
else
|
154
|
-
AIA.config.next = args.shift
|
155
|
-
end
|
156
|
-
''
|
157
|
-
end
|
158
|
-
|
159
|
-
desc "Show a list of tools and their description"
|
160
|
-
def tools(args = [], context_manager=nil)
|
161
|
-
indent = 4
|
162
|
-
spaces = " "*indent
|
163
|
-
width = TTY::Screen.width - indent - 2
|
164
|
-
|
165
|
-
if AIA.config.tools.empty?
|
166
|
-
puts "No tools are available"
|
167
|
-
else
|
168
|
-
puts
|
169
|
-
puts "Available Tools"
|
170
|
-
puts "==============="
|
171
|
-
|
172
|
-
AIA.config.tools.each do |tool|
|
173
|
-
name = tool.respond_to?(:name) ? tool.name : tool.class.name
|
174
|
-
puts "\n#{name}"
|
175
|
-
puts "-"*name.size
|
176
|
-
puts WordWrapper::MinimumRaggedness.new(width, tool.description).wrap.split("\n").map{|s| spaces+s+"\n"}.join
|
177
|
-
end
|
178
|
-
end
|
179
|
-
puts
|
180
|
-
|
181
|
-
''
|
182
|
-
end
|
183
|
-
|
184
|
-
desc "Specify a sequence pf prompt IDs to process after this one"
|
185
|
-
def pipeline(args = [], context_manager=nil)
|
186
|
-
if args.empty?
|
187
|
-
ap AIA.config.pipeline
|
188
|
-
elsif 1 == args.size
|
189
|
-
AIA.config.pipeline += args.first.split(',').map(&:strip).reject{|id| id.empty?}
|
190
|
-
else
|
191
|
-
AIA.config.pipeline += args.map{|id| id.gsub(',', '').strip}.reject{|id| id.empty?}
|
192
|
-
end
|
193
|
-
''
|
194
|
-
end
|
195
|
-
alias_method :workflow, :pipeline
|
196
|
-
|
197
|
-
desc "Inserts the contents of a file Example: //include path/to/file"
|
198
|
-
def include(args, context_manager=nil)
|
199
|
-
# echo takes care of envars and tilde expansion
|
200
|
-
file_path = `echo #{args.shift}`.strip
|
201
|
-
|
202
|
-
if file_path.start_with?(/http?:\/\//)
|
203
|
-
return webpage(args)
|
204
|
-
end
|
205
|
-
|
206
|
-
if @included_files.include?(file_path)
|
207
|
-
""
|
70
|
+
# Keep backward compatibility by delegating to Registry
|
71
|
+
def method_missing(method_name, *args, &block)
|
72
|
+
if Directives::Registry.respond_to?(method_name, true)
|
73
|
+
Directives::Registry.send(method_name, *args, &block)
|
208
74
|
else
|
209
|
-
|
210
|
-
@included_files << file_path
|
211
|
-
File.read(file_path)
|
212
|
-
else
|
213
|
-
"Error: File '#{file_path}' is not accessible"
|
214
|
-
end
|
75
|
+
super
|
215
76
|
end
|
216
77
|
end
|
217
|
-
alias_method :include_file, :include
|
218
|
-
alias_method :import, :include
|
219
|
-
|
220
|
-
desc "Without arguments it will print a list of all config items and their values _or_ //config item (for one item's value) _or_ //config item = value (to set a value of an item)"
|
221
|
-
def config(args = [], context_manager=nil)
|
222
|
-
args = Array(args)
|
223
|
-
|
224
|
-
if args.empty?
|
225
|
-
ap AIA.config
|
226
|
-
""
|
227
|
-
elsif args.length == 1
|
228
|
-
config_item = args.first
|
229
|
-
local_cfg = Hash.new
|
230
|
-
local_cfg[config_item] = AIA.config[config_item]
|
231
|
-
ap local_cfg
|
232
|
-
""
|
233
|
-
else
|
234
|
-
config_item = args.shift
|
235
|
-
boolean = AIA.respond_to?("#{config_item}?")
|
236
|
-
new_value = args.join(' ').gsub('=', '').strip
|
237
|
-
|
238
|
-
if boolean
|
239
|
-
new_value = %w[true t yes y on 1 yea yeah yep yup].include?(new_value.downcase)
|
240
|
-
end
|
241
|
-
|
242
|
-
AIA.config[config_item] = new_value
|
243
|
-
""
|
244
|
-
end
|
245
|
-
end
|
246
|
-
alias_method :cfg, :config
|
247
|
-
|
248
|
-
desc "Shortcut for //config top_p _and_ //config top_p = value"
|
249
|
-
def top_p(args, context_manager=nil)
|
250
|
-
send(:config, args.prepend('top_p'), context_manager)
|
251
|
-
end
|
252
|
-
alias_method :topp, :top_p
|
253
|
-
|
254
|
-
desc "Review the current context"
|
255
|
-
def review(args, context_manager=nil)
|
256
|
-
ap context_manager.get_context
|
257
|
-
''
|
258
|
-
end
|
259
|
-
alias_method :context, :review
|
260
|
-
|
261
|
-
desc "Shortcut for //config model _and_ //config model = value"
|
262
|
-
def model(args, context_manager=nil)
|
263
|
-
if args.empty?
|
264
|
-
puts
|
265
|
-
puts AIA.config.client.model.to_h.pretty_inspect
|
266
|
-
puts
|
267
|
-
else
|
268
|
-
send(:config, args.prepend('model'), context_manager)
|
269
|
-
end
|
270
|
-
|
271
|
-
return ''
|
272
|
-
end
|
273
|
-
|
274
|
-
desc "Shortcut for //config temperature _and_ //config temperature = value"
|
275
|
-
def temperature(args, context_manager=nil)
|
276
|
-
send(:config, args.prepend('temperature'), context_manager)
|
277
|
-
end
|
278
|
-
alias_method :temp, :temperature
|
279
|
-
|
280
|
-
desc "Clears the conversation history (aka context) same as //config clear = true"
|
281
|
-
def clear(args, context_manager=nil)
|
282
|
-
# TODO: review the robot's code in the Session class for when the
|
283
|
-
# //clear directive is used in a follow up prompt. That processing
|
284
|
-
# should be moved here so that it is also available in batch
|
285
|
-
# sessions.
|
286
|
-
if context_manager.nil?
|
287
|
-
return "Error: Context manager not available for //clear directive."
|
288
|
-
end
|
289
|
-
|
290
|
-
context_manager.clear_context
|
291
|
-
|
292
|
-
''
|
293
|
-
end
|
294
|
-
|
295
|
-
desc "Shortcut for a one line of ruby code; result is added to the context"
|
296
|
-
def ruby(args, context_manager=nil)
|
297
|
-
ruby_code = args.join(' ')
|
298
|
-
|
299
|
-
begin
|
300
|
-
String(eval(ruby_code))
|
301
|
-
rescue Exception => e
|
302
|
-
<<~ERROR
|
303
|
-
This ruby code failed: #{ruby_code}
|
304
|
-
#{e.message}
|
305
|
-
ERROR
|
306
|
-
end
|
307
|
-
end
|
308
|
-
alias_method :rb, :ruby
|
309
|
-
|
310
|
-
|
311
|
-
desc "Executes one line of shell code; result is added to the context"
|
312
|
-
def shell(args, context_manager=nil)
|
313
|
-
shell_code = args.join(' ')
|
314
|
-
|
315
|
-
`#{shell_code}`
|
316
|
-
end
|
317
|
-
alias_method :sh, :shell
|
318
|
-
|
319
|
-
desc "Use the system's say command to speak text //say some text"
|
320
|
-
def say(args, context_manager=nil)
|
321
|
-
`say #{args.join(' ')}`
|
322
|
-
""
|
323
|
-
end
|
324
|
-
|
325
|
-
desc "Inserts an instruction to keep responses short and to the point."
|
326
|
-
def terse(args, context_manager=nil)
|
327
|
-
AIA::Session::TERSE_PROMPT
|
328
|
-
end
|
329
|
-
|
330
|
-
desc "Display the ASCII art AIA robot."
|
331
|
-
def robot(args, context_manager=nil)
|
332
|
-
AIA::Utility.robot
|
333
|
-
""
|
334
|
-
end
|
335
|
-
|
336
|
-
desc "All Available models or query on [partial LLM or provider name] Examples: //llms ; //llms openai ; //llms claude"
|
337
|
-
def available_models( args=nil, context_manager=nil)
|
338
|
-
query = args
|
339
|
-
|
340
|
-
if 1 == query.size
|
341
|
-
query = query.first.split(',')
|
342
|
-
end
|
343
|
-
|
344
|
-
header = "\nAvailable LLMs"
|
345
|
-
header += " for #{query.join(' and ')}" if query
|
346
|
-
|
347
|
-
puts header + ':'
|
348
|
-
puts
|
349
|
-
|
350
|
-
q1 = query.select{|q| q.include?('_to_')} # SMELL: ?? .map{|q| ':'==q[0] ? q[1...] : q}
|
351
|
-
q2 = query.reject{|q| q.include?('_to_')}
|
352
|
-
|
353
|
-
counter = 0
|
354
|
-
|
355
|
-
RubyLLM.models.all.each do |llm|
|
356
|
-
cw = llm.context_window
|
357
|
-
caps = llm.capabilities.join(',')
|
358
|
-
inputs = llm.modalities.input.join(',')
|
359
|
-
outputs = llm.modalities.output.join(',')
|
360
|
-
mode = "#{inputs} to #{outputs}"
|
361
|
-
in_1m = llm.pricing.text_tokens.standard.to_h[:input_per_million]
|
362
|
-
entry = "- #{llm.id} (#{llm.provider}) in: $#{in_1m} cw: #{cw} mode: #{mode} caps: #{caps}"
|
363
|
-
|
364
|
-
if query.nil? || query.empty?
|
365
|
-
counter += 1
|
366
|
-
puts entry
|
367
|
-
next
|
368
|
-
end
|
369
|
-
|
370
|
-
show_it = true
|
371
|
-
q1.each{|q| show_it &&= llm.modalities.send("#{q}?")}
|
372
|
-
q2.each{|q| show_it &&= entry.include?(q)}
|
373
|
-
|
374
|
-
if show_it
|
375
|
-
counter += 1
|
376
|
-
puts entry
|
377
|
-
end
|
378
|
-
end
|
379
|
-
|
380
|
-
puts if counter > 0
|
381
|
-
puts "#{counter} LLMs matching your query"
|
382
|
-
puts
|
383
|
-
|
384
|
-
""
|
385
|
-
end
|
386
|
-
alias_method :am, :available_models
|
387
|
-
alias_method :available, :available_models
|
388
|
-
alias_method :models, :available_models
|
389
|
-
alias_method :all_models, :available_models
|
390
|
-
alias_method :llms, :available_models
|
391
|
-
|
392
|
-
desc "Generates this help content"
|
393
|
-
def help(args=nil, context_manager=nil)
|
394
|
-
puts
|
395
|
-
puts "Available Directives"
|
396
|
-
puts "===================="
|
397
|
-
puts
|
398
|
-
|
399
|
-
directives = self.class
|
400
|
-
.private_instance_methods(false)
|
401
|
-
.map(&:to_s)
|
402
|
-
.reject { |m| EXCLUDED_METHODS.include?(m) }
|
403
|
-
.sort
|
404
|
-
|
405
|
-
self.class.build_aliases(directives)
|
406
|
-
|
407
|
-
directives.each do |directive|
|
408
|
-
next unless self.class.descriptions[directive]
|
409
|
-
|
410
|
-
others = self.class.aliases[directive]
|
411
|
-
|
412
|
-
if others.empty?
|
413
|
-
others_line = ""
|
414
|
-
else
|
415
|
-
with_prefix = others.map{|m| PromptManager::Prompt::DIRECTIVE_SIGNAL + m}
|
416
|
-
others_line = "\tAliases:#{with_prefix.join(' ')}\n"
|
417
|
-
end
|
418
|
-
|
419
|
-
puts <<~TEXT
|
420
|
-
//#{directive} #{self.class.descriptions[directive]}
|
421
|
-
#{others_line}
|
422
|
-
TEXT
|
423
|
-
end
|
424
78
|
|
425
|
-
|
79
|
+
def respond_to_missing?(method_name, include_private = false)
|
80
|
+
Directives::Registry.respond_to?(method_name, include_private) || super
|
426
81
|
end
|
427
82
|
end
|
428
83
|
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
# lib/aia/directives/configuration.rb
|
2
|
+
|
3
|
+
module AIA
|
4
|
+
module Directives
|
5
|
+
module Configuration
|
6
|
+
def self.config(args = [], context_manager = nil)
|
7
|
+
args = Array(args)
|
8
|
+
|
9
|
+
if args.empty?
|
10
|
+
ap AIA.config
|
11
|
+
""
|
12
|
+
elsif args.length == 1
|
13
|
+
config_item = args.first
|
14
|
+
local_cfg = Hash.new
|
15
|
+
local_cfg[config_item] = AIA.config[config_item]
|
16
|
+
ap local_cfg
|
17
|
+
""
|
18
|
+
else
|
19
|
+
config_item = args.shift
|
20
|
+
boolean = AIA.respond_to?("#{config_item}?")
|
21
|
+
new_value = args.join(' ').gsub('=', '').strip
|
22
|
+
|
23
|
+
if boolean
|
24
|
+
new_value = %w[true t yes y on 1 yea yeah yep yup].include?(new_value.downcase)
|
25
|
+
end
|
26
|
+
|
27
|
+
AIA.config[config_item] = new_value
|
28
|
+
""
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.model(args, context_manager = nil)
|
33
|
+
if args.empty?
|
34
|
+
# Display details for all configured models
|
35
|
+
puts
|
36
|
+
models = Array(AIA.config.model)
|
37
|
+
|
38
|
+
if models.size == 1
|
39
|
+
puts "Current Model:"
|
40
|
+
puts "=============="
|
41
|
+
puts AIA.config.client.model.to_h.pretty_inspect
|
42
|
+
else
|
43
|
+
puts "Multi-Model Configuration:"
|
44
|
+
puts "=========================="
|
45
|
+
puts "Model count: #{models.size}"
|
46
|
+
puts "Primary model: #{models.first} (used for consensus when --consensus flag is enabled)"
|
47
|
+
puts "Consensus mode: #{AIA.config.consensus.nil? ? 'auto-detect (disabled by default)' : AIA.config.consensus}"
|
48
|
+
puts
|
49
|
+
puts "Model Details:"
|
50
|
+
puts "-" * 50
|
51
|
+
|
52
|
+
models.each_with_index do |model_name, index|
|
53
|
+
puts "#{index + 1}. #{model_name}#{index == 0 ? ' (primary)' : ''}"
|
54
|
+
|
55
|
+
# Try to get model details if available
|
56
|
+
begin
|
57
|
+
# Access the model details from RubyLLM's model registry
|
58
|
+
model_info = RubyLLM::Models.find(name: model_name)
|
59
|
+
if model_info
|
60
|
+
puts " Provider: #{model_info.provider || 'Unknown'}"
|
61
|
+
puts " Context window: #{model_info.context_window || 'Unknown'}"
|
62
|
+
puts " Input cost: $#{model_info.input_cost || 'Unknown'}"
|
63
|
+
puts " Output cost: $#{model_info.output_cost || 'Unknown'}"
|
64
|
+
puts " Mode: #{model_info.modalities || 'Unknown'}"
|
65
|
+
puts " Capabilities: #{(model_info.capabilities || []).join(', ')}" if model_info.capabilities&.any?
|
66
|
+
else
|
67
|
+
puts " Details: Model not found in registry"
|
68
|
+
end
|
69
|
+
rescue StandardError => e
|
70
|
+
puts " Details: Unable to fetch (#{e.class.name}: #{e.message})"
|
71
|
+
end
|
72
|
+
puts
|
73
|
+
end
|
74
|
+
end
|
75
|
+
puts
|
76
|
+
else
|
77
|
+
send(:config, args.prepend('model'), context_manager)
|
78
|
+
end
|
79
|
+
|
80
|
+
return ''
|
81
|
+
end
|
82
|
+
|
83
|
+
def self.temperature(args, context_manager = nil)
|
84
|
+
send(:config, args.prepend('temperature'), context_manager)
|
85
|
+
end
|
86
|
+
|
87
|
+
def self.top_p(args, context_manager = nil)
|
88
|
+
send(:config, args.prepend('top_p'), context_manager)
|
89
|
+
end
|
90
|
+
|
91
|
+
def self.clear(args, context_manager = nil)
|
92
|
+
if context_manager.nil?
|
93
|
+
return "Error: Context manager not available for //clear directive."
|
94
|
+
end
|
95
|
+
|
96
|
+
context_manager.clear_context
|
97
|
+
''
|
98
|
+
end
|
99
|
+
|
100
|
+
def self.review(args, context_manager = nil)
|
101
|
+
ap context_manager.get_context
|
102
|
+
''
|
103
|
+
end
|
104
|
+
|
105
|
+
# Set up aliases - these work on the module's singleton class
|
106
|
+
class << self
|
107
|
+
alias_method :cfg, :config
|
108
|
+
alias_method :temp, :temperature
|
109
|
+
alias_method :topp, :top_p
|
110
|
+
alias_method :context, :review
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# lib/aia/directives/execution.rb
|
2
|
+
|
3
|
+
module AIA
|
4
|
+
module Directives
|
5
|
+
module Execution
|
6
|
+
def self.ruby(args, context_manager = nil)
|
7
|
+
ruby_code = args.join(' ')
|
8
|
+
|
9
|
+
begin
|
10
|
+
String(eval(ruby_code))
|
11
|
+
rescue Exception => e
|
12
|
+
<<~ERROR
|
13
|
+
This ruby code failed: #{ruby_code}
|
14
|
+
#{e.message}
|
15
|
+
ERROR
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.shell(args, context_manager = nil)
|
20
|
+
shell_code = args.join(' ')
|
21
|
+
|
22
|
+
`#{shell_code}`
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.say(args, context_manager = nil)
|
26
|
+
`say #{args.join(' ')}`
|
27
|
+
""
|
28
|
+
end
|
29
|
+
|
30
|
+
# Set up aliases - these work on the module's singleton class
|
31
|
+
class << self
|
32
|
+
alias_method :rb, :ruby
|
33
|
+
alias_method :sh, :shell
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|