aia 0.8.5 → 0.9.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 +4 -4
- data/.version +1 -1
- data/CHANGELOG.md +9 -1
- data/COMMITS.md +23 -0
- data/README.md +131 -163
- data/lib/aia/chat_processor_service.rb +14 -1
- data/lib/aia/config.rb +157 -10
- data/lib/aia/prompt_handler.rb +7 -2
- data/lib/aia/ruby_llm_adapter.rb +225 -0
- data/lib/aia/session.rb +127 -96
- data/lib/aia/ui_presenter.rb +10 -1
- data/lib/aia/utility.rb +1 -1
- data/lib/aia.rb +14 -3
- data/lib/extensions/ruby_llm/chat.rb +197 -0
- data/mcp_servers/README.md +90 -0
- data/mcp_servers/filesystem.json +9 -0
- data/mcp_servers/imcp.json +7 -0
- data/mcp_servers/launcher.json +11 -0
- data/mcp_servers/playwright_server_definition.json +9 -0
- data/mcp_servers/timeserver.json +8 -0
- metadata +33 -11
- data/lib/aia/ai_client_adapter.rb +0 -210
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: aia
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.9.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dewayne VanHoozer
|
@@ -10,7 +10,7 @@ cert_chain: []
|
|
10
10
|
date: 1980-01-02 00:00:00.000000000 Z
|
11
11
|
dependencies:
|
12
12
|
- !ruby/object:Gem::Dependency
|
13
|
-
name:
|
13
|
+
name: amazing_print
|
14
14
|
requirement: !ruby/object:Gem::Requirement
|
15
15
|
requirements:
|
16
16
|
- - ">="
|
@@ -24,7 +24,7 @@ dependencies:
|
|
24
24
|
- !ruby/object:Gem::Version
|
25
25
|
version: '0'
|
26
26
|
- !ruby/object:Gem::Dependency
|
27
|
-
name:
|
27
|
+
name: faraday
|
28
28
|
requirement: !ruby/object:Gem::Requirement
|
29
29
|
requirements:
|
30
30
|
- - ">="
|
@@ -38,7 +38,7 @@ dependencies:
|
|
38
38
|
- !ruby/object:Gem::Version
|
39
39
|
version: '0'
|
40
40
|
- !ruby/object:Gem::Dependency
|
41
|
-
name:
|
41
|
+
name: os
|
42
42
|
requirement: !ruby/object:Gem::Requirement
|
43
43
|
requirements:
|
44
44
|
- - ">="
|
@@ -52,33 +52,47 @@ dependencies:
|
|
52
52
|
- !ruby/object:Gem::Version
|
53
53
|
version: '0'
|
54
54
|
- !ruby/object:Gem::Dependency
|
55
|
-
name:
|
55
|
+
name: prompt_manager
|
56
56
|
requirement: !ruby/object:Gem::Requirement
|
57
57
|
requirements:
|
58
58
|
- - ">="
|
59
59
|
- !ruby/object:Gem::Version
|
60
|
-
version:
|
60
|
+
version: 0.5.2
|
61
61
|
type: :runtime
|
62
62
|
prerelease: false
|
63
63
|
version_requirements: !ruby/object:Gem::Requirement
|
64
64
|
requirements:
|
65
65
|
- - ">="
|
66
66
|
- !ruby/object:Gem::Version
|
67
|
-
version:
|
67
|
+
version: 0.5.2
|
68
68
|
- !ruby/object:Gem::Dependency
|
69
|
-
name:
|
69
|
+
name: ruby_llm
|
70
70
|
requirement: !ruby/object:Gem::Requirement
|
71
71
|
requirements:
|
72
72
|
- - ">="
|
73
73
|
- !ruby/object:Gem::Version
|
74
|
-
version:
|
74
|
+
version: 1.2.0
|
75
75
|
type: :runtime
|
76
76
|
prerelease: false
|
77
77
|
version_requirements: !ruby/object:Gem::Requirement
|
78
78
|
requirements:
|
79
79
|
- - ">="
|
80
80
|
- !ruby/object:Gem::Version
|
81
|
-
version:
|
81
|
+
version: 1.2.0
|
82
|
+
- !ruby/object:Gem::Dependency
|
83
|
+
name: ruby-mcp-client
|
84
|
+
requirement: !ruby/object:Gem::Requirement
|
85
|
+
requirements:
|
86
|
+
- - ">="
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: '0'
|
89
|
+
type: :runtime
|
90
|
+
prerelease: false
|
91
|
+
version_requirements: !ruby/object:Gem::Requirement
|
92
|
+
requirements:
|
93
|
+
- - ">="
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: '0'
|
82
96
|
- !ruby/object:Gem::Dependency
|
83
97
|
name: reline
|
84
98
|
requirement: !ruby/object:Gem::Requirement
|
@@ -280,6 +294,7 @@ files:
|
|
280
294
|
- ".envrc"
|
281
295
|
- ".version"
|
282
296
|
- CHANGELOG.md
|
297
|
+
- COMMITS.md
|
283
298
|
- LICENSE
|
284
299
|
- README.md
|
285
300
|
- Rakefile
|
@@ -289,7 +304,6 @@ files:
|
|
289
304
|
- examples/headlines
|
290
305
|
- justfile
|
291
306
|
- lib/aia.rb
|
292
|
-
- lib/aia/ai_client_adapter.rb
|
293
307
|
- lib/aia/aia_completion.bash
|
294
308
|
- lib/aia/aia_completion.fish
|
295
309
|
- lib/aia/aia_completion.zsh
|
@@ -300,13 +314,21 @@ files:
|
|
300
314
|
- lib/aia/fzf.rb
|
301
315
|
- lib/aia/history_manager.rb
|
302
316
|
- lib/aia/prompt_handler.rb
|
317
|
+
- lib/aia/ruby_llm_adapter.rb
|
303
318
|
- lib/aia/session.rb
|
304
319
|
- lib/aia/shell_command_executor.rb
|
305
320
|
- lib/aia/ui_presenter.rb
|
306
321
|
- lib/aia/utility.rb
|
307
322
|
- lib/aia/version.rb
|
308
323
|
- lib/extensions/openstruct_merge.rb
|
324
|
+
- lib/extensions/ruby_llm/chat.rb
|
309
325
|
- main.just
|
326
|
+
- mcp_servers/README.md
|
327
|
+
- mcp_servers/filesystem.json
|
328
|
+
- mcp_servers/imcp.json
|
329
|
+
- mcp_servers/launcher.json
|
330
|
+
- mcp_servers/playwright_server_definition.json
|
331
|
+
- mcp_servers/timeserver.json
|
310
332
|
homepage: https://github.com/MadBomber/aia
|
311
333
|
licenses:
|
312
334
|
- MIT
|
@@ -1,210 +0,0 @@
|
|
1
|
-
# lib/aia/ai_client_adapter.rb
|
2
|
-
#
|
3
|
-
|
4
|
-
|
5
|
-
require 'ai_client'
|
6
|
-
require 'tty-spinner'
|
7
|
-
|
8
|
-
|
9
|
-
module AIA
|
10
|
-
class AIClientAdapter
|
11
|
-
def initialize
|
12
|
-
@model = AIA.config.model
|
13
|
-
|
14
|
-
model_info = extract_model_parts(@model)
|
15
|
-
@client = AiClient.new(
|
16
|
-
model_info[:model],
|
17
|
-
provider: model_info[:provider]
|
18
|
-
)
|
19
|
-
end
|
20
|
-
|
21
|
-
|
22
|
-
def chat(prompt)
|
23
|
-
if @model.downcase.include?('dall-e') || @model.downcase.include?('image-generation')
|
24
|
-
text_to_image(prompt)
|
25
|
-
elsif @model.downcase.include?('vision') || @model.downcase.include?('image')
|
26
|
-
image_to_text(prompt)
|
27
|
-
elsif @model.downcase.include?('tts') || @model.downcase.include?('speech')
|
28
|
-
text_to_audio(prompt)
|
29
|
-
elsif @model.downcase.include?('whisper') || @model.downcase.include?('transcription')
|
30
|
-
audio_to_text(prompt)
|
31
|
-
else
|
32
|
-
text_to_text(prompt)
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
def transcribe(audio_file)
|
39
|
-
@client.transcribe(audio_file)
|
40
|
-
end
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
def speak(text)
|
45
|
-
output_file = "#{Time.now.to_i}.mp3"
|
46
|
-
|
47
|
-
begin
|
48
|
-
# Try with options
|
49
|
-
@client.speak(text, output_file, {
|
50
|
-
model: AIA.config.speech_model,
|
51
|
-
voice: AIA.config.voice
|
52
|
-
})
|
53
|
-
rescue ArgumentError
|
54
|
-
@client.speak(text)
|
55
|
-
end
|
56
|
-
|
57
|
-
system("#{AIA.config.speak_command} #{output_file}") if File.exist?(output_file) && system("which #{AIA.config.speak_command} > /dev/null 2>&1")
|
58
|
-
end
|
59
|
-
|
60
|
-
def method_missing(method, *args, &block)
|
61
|
-
if @client.respond_to?(method)
|
62
|
-
@client.public_send(method, *args, &block)
|
63
|
-
else
|
64
|
-
super
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
def respond_to_missing?(method, include_private = false)
|
69
|
-
@client.respond_to?(method) || super
|
70
|
-
end
|
71
|
-
|
72
|
-
private
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
def extract_model_parts(model_string)
|
77
|
-
parts = model_string.split('/')
|
78
|
-
parts.map!(&:strip)
|
79
|
-
|
80
|
-
if parts.length > 1
|
81
|
-
provider = parts[0]
|
82
|
-
model = parts[1]
|
83
|
-
else
|
84
|
-
provider = nil # AiClient will figure it out from the model name
|
85
|
-
model = parts[0]
|
86
|
-
end
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
{ provider: provider, model: model }
|
91
|
-
end
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
def extract_text_prompt(prompt)
|
96
|
-
|
97
|
-
if prompt.is_a?(String)
|
98
|
-
prompt
|
99
|
-
elsif prompt.is_a?(Hash) && prompt[:text]
|
100
|
-
prompt[:text]
|
101
|
-
elsif prompt.is_a?(Hash) && prompt[:content]
|
102
|
-
prompt[:content]
|
103
|
-
else
|
104
|
-
prompt.to_s
|
105
|
-
end
|
106
|
-
end
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
def text_to_text(prompt)
|
111
|
-
text_prompt = extract_text_prompt(prompt)
|
112
|
-
@client.chat(text_prompt)
|
113
|
-
end
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
def text_to_image(prompt)
|
118
|
-
text_prompt = extract_text_prompt(prompt)
|
119
|
-
|
120
|
-
|
121
|
-
output_file = "#{Time.now.to_i}.png"
|
122
|
-
|
123
|
-
begin
|
124
|
-
begin
|
125
|
-
@client.generate_image(text_prompt, output_file, {
|
126
|
-
size: AIA.config.image_size,
|
127
|
-
quality: AIA.config.image_quality,
|
128
|
-
style: AIA.config.image_style
|
129
|
-
})
|
130
|
-
rescue ArgumentError
|
131
|
-
@client.generate_image(text_prompt)
|
132
|
-
end
|
133
|
-
|
134
|
-
"Image generated and saved to: #{output_file}"
|
135
|
-
rescue => e
|
136
|
-
"Error generating image: #{e.message}"
|
137
|
-
end
|
138
|
-
end
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
def image_to_text(prompt)
|
143
|
-
image_path = extract_image_path(prompt)
|
144
|
-
text_prompt = extract_text_prompt(prompt)
|
145
|
-
|
146
|
-
if image_path && File.exist?(image_path)
|
147
|
-
begin
|
148
|
-
@client.chat("#{text_prompt}\n[Analyzing image: #{image_path}]")
|
149
|
-
rescue => e
|
150
|
-
"Error analyzing image: #{e.message}"
|
151
|
-
end
|
152
|
-
else
|
153
|
-
text_to_text(prompt)
|
154
|
-
end
|
155
|
-
end
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
def text_to_audio(prompt)
|
160
|
-
text_prompt = extract_text_prompt(prompt)
|
161
|
-
|
162
|
-
output_file = "#{Time.now.to_i}.mp3"
|
163
|
-
|
164
|
-
begin
|
165
|
-
begin
|
166
|
-
@client.speak(text_prompt, output_file, {
|
167
|
-
model: AIA.config.speech_model,
|
168
|
-
voice: AIA.config.voice
|
169
|
-
})
|
170
|
-
rescue ArgumentError
|
171
|
-
@client.speak(text_prompt)
|
172
|
-
end
|
173
|
-
|
174
|
-
system("#{AIA.config.speak_command} #{output_file}") if File.exist?(output_file) && system("which #{AIA.config.speak_command} > /dev/null 2>&1")
|
175
|
-
|
176
|
-
"Audio generated and saved to: #{output_file}"
|
177
|
-
rescue => e
|
178
|
-
"Error generating audio: #{e.message}"
|
179
|
-
end
|
180
|
-
end
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
def audio_to_text(prompt)
|
185
|
-
if prompt.is_a?(String) && File.exist?(prompt) &&
|
186
|
-
prompt.downcase.end_with?('.mp3', '.wav', '.m4a', '.flac')
|
187
|
-
begin
|
188
|
-
@client.transcribe(prompt)
|
189
|
-
rescue => e
|
190
|
-
"Error transcribing audio: #{e.message}"
|
191
|
-
end
|
192
|
-
else
|
193
|
-
# Fall back to regular chat if no valid audio file is found
|
194
|
-
text_to_text(prompt)
|
195
|
-
end
|
196
|
-
end
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
def extract_image_path(prompt)
|
201
|
-
if prompt.is_a?(String)
|
202
|
-
prompt.scan(/\b[\w\/\.\-]+\.(jpg|jpeg|png|gif|webp)\b/i).first&.first
|
203
|
-
elsif prompt.is_a?(Hash)
|
204
|
-
prompt[:image] || prompt[:image_path]
|
205
|
-
else
|
206
|
-
nil
|
207
|
-
end
|
208
|
-
end
|
209
|
-
end
|
210
|
-
end
|