aia 0.9.8 → 0.9.10
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 +15 -0
- data/README.md +62 -5
- data/Rakefile +16 -8
- data/examples/directives/ask.rb +21 -0
- data/examples/tools/edit_file.rb +2 -0
- data/examples/tools/incomplete/calculator_tool.rb +70 -0
- data/examples/tools/incomplete/composite_analysis_tool.rb +89 -0
- data/examples/tools/incomplete/data_science_kit.rb +128 -0
- data/examples/tools/incomplete/database_query_tool.rb +100 -0
- data/examples/tools/incomplete/devops_toolkit.rb +112 -0
- data/examples/tools/incomplete/error_handling_tool.rb +109 -0
- data/examples/tools/{pdf_page_reader.rb → incomplete/pdf_page_reader.rb} +2 -0
- data/examples/tools/incomplete/secure_tool_template.rb +117 -0
- data/examples/tools/incomplete/weather_tool.rb +110 -0
- data/examples/tools/incomplete/workflow_manager_tool.rb +145 -0
- data/examples/tools/list_files.rb +2 -0
- data/examples/tools/mcp/README.md +1 -0
- data/examples/tools/mcp/github_mcp_server.rb +41 -0
- data/examples/tools/mcp/imcp.rb +15 -0
- data/examples/tools/read_file.rb +2 -0
- data/examples/tools/run_shell_command.rb +2 -0
- data/justfile +3 -25
- data/lib/aia/chat_processor_service.rb +0 -3
- data/lib/aia/config.rb +542 -436
- data/lib/aia/context_manager.rb +3 -8
- data/lib/aia/directive_processor.rb +21 -10
- data/lib/aia/ruby_llm_adapter.rb +78 -10
- data/lib/aia/session.rb +187 -138
- data/lib/aia/ui_presenter.rb +7 -5
- data/lib/aia/utility.rb +26 -6
- data/lib/aia.rb +5 -1
- data/main.just +3 -25
- metadata +31 -12
- data/lib/aia/shell_command_executor.rb +0 -109
data/lib/aia/utility.rb
CHANGED
@@ -5,6 +5,15 @@ require 'word_wrapper' # Pure ruby word wrapping
|
|
5
5
|
module AIA
|
6
6
|
class Utility
|
7
7
|
class << self
|
8
|
+
def tools?
|
9
|
+
!AIA.config.tool_names.empty?
|
10
|
+
end
|
11
|
+
|
12
|
+
def supports_tools?
|
13
|
+
AIA.config.client.model.supports_functions?
|
14
|
+
end
|
15
|
+
|
16
|
+
|
8
17
|
# Displays the AIA robot ASCII art
|
9
18
|
# Yes, its slightly frivolous but it does contain some
|
10
19
|
# useful configuration information.
|
@@ -13,20 +22,31 @@ module AIA
|
|
13
22
|
spaces = " "*indent
|
14
23
|
width = TTY::Screen.width - indent - 2
|
15
24
|
|
25
|
+
mcp_version = defined?(RubyLLM::MCP::VERSION) ? " MCP v" + RubyLLM::MCP::VERSION : ''
|
26
|
+
|
16
27
|
puts <<-ROBOT
|
17
28
|
|
18
29
|
, ,
|
19
30
|
(\\____/) AI Assistant (v#{AIA::VERSION}) is Online
|
20
|
-
(_oo_) #{AIA.config.model}
|
21
|
-
(O) using #{AIA.config.adapter} (v#{RubyLLM::VERSION})
|
31
|
+
(_oo_) #{AIA.config.model}#{supports_tools? ? ' (supports tools)' : ''}
|
32
|
+
(O) using #{AIA.config.adapter} (v#{RubyLLM::VERSION}#{mcp_version})
|
22
33
|
__||__ \\) model db was last refreshed on
|
23
34
|
[/______\\] / #{AIA.config.last_refresh}
|
24
|
-
/ \\__AI__/ \\/ #{
|
35
|
+
/ \\__AI__/ \\/ #{tools? ? 'You can share my tools' : 'I did not bring any tools'}
|
25
36
|
/ /__\\
|
26
|
-
(\\ /____\\ #{
|
37
|
+
(\\ /____\\ #{tools? ? 'My Toolbox contains:' : ''}
|
27
38
|
ROBOT
|
28
|
-
if
|
29
|
-
|
39
|
+
if tools?
|
40
|
+
tool_names = AIA.config.respond_to?(:tool_names) ? AIA.config.tool_names : AIA.config.tools
|
41
|
+
if tool_names && !tool_names.to_s.empty?
|
42
|
+
puts WordWrapper::MinimumRaggedness.new(
|
43
|
+
width,
|
44
|
+
tool_names.to_s # String of tool names, comma separated
|
45
|
+
).wrap
|
46
|
+
.split("\n")
|
47
|
+
.map{|s| spaces+s+"\n"}
|
48
|
+
.join
|
49
|
+
end
|
30
50
|
end
|
31
51
|
end
|
32
52
|
end
|
data/lib/aia.rb
CHANGED
@@ -6,6 +6,11 @@
|
|
6
6
|
|
7
7
|
require 'ruby_llm'
|
8
8
|
require 'ruby_llm/mcp'
|
9
|
+
|
10
|
+
# FIXME: Actually fix ruby_llm; this is supposed to a temporary fix for the issues
|
11
|
+
# discovered with shared_tools/ruby_llm/mcp/github_mcp_server
|
12
|
+
RubyLLM::MCP.support_complex_parameters!
|
13
|
+
|
9
14
|
require 'prompt_manager'
|
10
15
|
|
11
16
|
|
@@ -25,7 +30,6 @@ require_relative 'refinements/string.rb' # adds #include_any? #include_al
|
|
25
30
|
require_relative 'aia/utility'
|
26
31
|
require_relative 'aia/version'
|
27
32
|
require_relative 'aia/config'
|
28
|
-
require_relative 'aia/shell_command_executor'
|
29
33
|
require_relative 'aia/prompt_handler'
|
30
34
|
require_relative 'aia/ruby_llm_adapter'
|
31
35
|
require_relative 'aia/directive_processor'
|
data/main.just
CHANGED
@@ -1,12 +1,8 @@
|
|
1
1
|
# aia/main.just
|
2
2
|
#
|
3
|
-
# Support man pages with ...
|
4
|
-
# gem install kramdown-man versionaire
|
5
|
-
#
|
6
3
|
|
7
4
|
RR := env_var('RR')
|
8
5
|
version_filepath := env_var('RR') + "/.version"
|
9
|
-
man_filepath := env_var('RR') + "/man/aia.1.md"
|
10
6
|
|
11
7
|
with ~/.justfile
|
12
8
|
|
@@ -20,7 +16,7 @@ module git /Users/dewayne/just_modules/git.just
|
|
20
16
|
|
21
17
|
|
22
18
|
# Install Locally
|
23
|
-
install: update_toc_in_readmen
|
19
|
+
install: update_toc_in_readmen flay
|
24
20
|
rake install
|
25
21
|
|
26
22
|
|
@@ -29,10 +25,6 @@ update_toc_in_readmen:
|
|
29
25
|
rake toc
|
30
26
|
|
31
27
|
|
32
|
-
# Preview man page
|
33
|
-
preview_man_page:
|
34
|
-
kramdown-man {{RR}}/man/aia.1.md
|
35
|
-
|
36
28
|
# Static Code Check
|
37
29
|
flay: coverage
|
38
30
|
flay {{RR}}
|
@@ -46,20 +38,10 @@ coverage: test
|
|
46
38
|
# Run Unit Tests
|
47
39
|
test:
|
48
40
|
rake test
|
49
|
-
|
50
|
-
|
51
|
-
# View man page
|
52
|
-
view_man_page: create_man_page
|
53
|
-
man {{RR}}/man/aia.1
|
54
|
-
|
55
|
-
|
56
|
-
# Create man page
|
57
|
-
create_man_page:
|
58
|
-
rake man
|
59
41
|
|
60
42
|
|
61
43
|
# Generate the Documentation
|
62
|
-
gen_doc:
|
44
|
+
gen_doc: update_toc_in_readmen
|
63
45
|
|
64
46
|
|
65
47
|
##########################################
|
@@ -91,8 +73,4 @@ alias inc := bump
|
|
91
73
|
File.open("{{version_filepath}}", 'w')
|
92
74
|
.write(new_version.to_s + "\n")
|
93
75
|
#
|
94
|
-
|
95
|
-
#
|
96
|
-
File.write({{man_filepath}}, content)
|
97
|
-
#
|
98
|
-
`git add {{version_filepath}} {{man_filepath}}`
|
76
|
+
`git add {{version_filepath}}`
|
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.9.
|
4
|
+
version: 0.9.10
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dewayne VanHoozer
|
@@ -85,14 +85,14 @@ dependencies:
|
|
85
85
|
requirements:
|
86
86
|
- - ">="
|
87
87
|
- !ruby/object:Gem::Version
|
88
|
-
version:
|
88
|
+
version: 0.6.1
|
89
89
|
type: :runtime
|
90
90
|
prerelease: false
|
91
91
|
version_requirements: !ruby/object:Gem::Requirement
|
92
92
|
requirements:
|
93
93
|
- - ">="
|
94
94
|
- !ruby/object:Gem::Version
|
95
|
-
version:
|
95
|
+
version: 0.6.1
|
96
96
|
- !ruby/object:Gem::Dependency
|
97
97
|
name: reline
|
98
98
|
requirement: !ruby/object:Gem::Requirement
|
@@ -290,12 +290,19 @@ dependencies:
|
|
290
290
|
- !ruby/object:Gem::Version
|
291
291
|
version: '0'
|
292
292
|
description: |
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
293
|
+
Unlock the Power of AI Right from Your Terminal! AIA is a
|
294
|
+
revolutionary CLI console application designed for generative AI
|
295
|
+
workflows. With AIA, you can effortlessly manage prompts,
|
296
|
+
integrate seamlessly with shell and embedded Ruby (ERB), and
|
297
|
+
engage in interactive chats, all while harnessing advanced
|
298
|
+
automation features. Experience a new level of productivity with
|
299
|
+
dynamic prompt management, tailored directives, and comprehensive
|
300
|
+
history tracking. AIA supports callback functions (Tools) and
|
301
|
+
model context protocol (MCP) servers, making it the ultimate tool
|
302
|
+
for developers, power users, and AI enthusiasts alike. Transform
|
303
|
+
your command line into a powerhouse of creativity and efficiency.
|
304
|
+
Elevate your workflow with AIA and unleash the full potential of
|
305
|
+
AI at your fingertips!
|
299
306
|
email:
|
300
307
|
- dvanhoozer@gmail.com
|
301
308
|
executables:
|
@@ -315,10 +322,23 @@ files:
|
|
315
322
|
- _notes.txt
|
316
323
|
- bin/aia
|
317
324
|
- examples/README.md
|
325
|
+
- examples/directives/ask.rb
|
318
326
|
- examples/headlines
|
319
327
|
- examples/tools/edit_file.rb
|
328
|
+
- examples/tools/incomplete/calculator_tool.rb
|
329
|
+
- examples/tools/incomplete/composite_analysis_tool.rb
|
330
|
+
- examples/tools/incomplete/data_science_kit.rb
|
331
|
+
- examples/tools/incomplete/database_query_tool.rb
|
332
|
+
- examples/tools/incomplete/devops_toolkit.rb
|
333
|
+
- examples/tools/incomplete/error_handling_tool.rb
|
334
|
+
- examples/tools/incomplete/pdf_page_reader.rb
|
335
|
+
- examples/tools/incomplete/secure_tool_template.rb
|
336
|
+
- examples/tools/incomplete/weather_tool.rb
|
337
|
+
- examples/tools/incomplete/workflow_manager_tool.rb
|
320
338
|
- examples/tools/list_files.rb
|
321
|
-
- examples/tools/
|
339
|
+
- examples/tools/mcp/README.md
|
340
|
+
- examples/tools/mcp/github_mcp_server.rb
|
341
|
+
- examples/tools/mcp/imcp.rb
|
322
342
|
- examples/tools/read_file.rb
|
323
343
|
- examples/tools/run_shell_command.rb
|
324
344
|
- images/aia.png
|
@@ -336,7 +356,6 @@ files:
|
|
336
356
|
- lib/aia/prompt_handler.rb
|
337
357
|
- lib/aia/ruby_llm_adapter.rb
|
338
358
|
- lib/aia/session.rb
|
339
|
-
- lib/aia/shell_command_executor.rb
|
340
359
|
- lib/aia/ui_presenter.rb
|
341
360
|
- lib/aia/utility.rb
|
342
361
|
- lib/aia/version.rb
|
@@ -372,7 +391,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
372
391
|
- !ruby/object:Gem::Version
|
373
392
|
version: '0'
|
374
393
|
requirements: []
|
375
|
-
rubygems_version: 3.
|
394
|
+
rubygems_version: 3.7.0
|
376
395
|
specification_version: 4
|
377
396
|
summary: 'AI Assistant: dynamic prompts, shell & Ruby integration, and seamless chat
|
378
397
|
workflows.'
|
@@ -1,109 +0,0 @@
|
|
1
|
-
# lib/aia/shell_command_executor.rb
|
2
|
-
|
3
|
-
module AIA
|
4
|
-
class ShellCommandExecutor
|
5
|
-
DANGEROUS_PATTERNS = [
|
6
|
-
# File system destructive commands
|
7
|
-
/\brm\s+(-[a-z]*)?f/i, # rm with force flag
|
8
|
-
/\bmkfs/i, # format filesystems
|
9
|
-
/\bdd\b.*\bof=/i, # dd with output file
|
10
|
-
/\bshred\b/i, # securely delete files
|
11
|
-
# System modification commands
|
12
|
-
/\bsystemctl\s+(stop|disable|mask)/i, # stopping system services
|
13
|
-
/\bchmod\s+777\b/i, # setting dangerous permissions
|
14
|
-
/\b(halt|poweroff|shutdown|reboot)\b/i, # system power commands
|
15
|
-
# Network security related
|
16
|
-
/\btcpdump\b/i, # packet capturing
|
17
|
-
/\bifconfig\b.*\bdown\b/i, # taking down network interfaces
|
18
|
-
# Process control
|
19
|
-
/\bkill\s+-9\b/i, # force killing processes
|
20
|
-
/\bpkill\b/i # pattern-based process killing
|
21
|
-
].freeze
|
22
|
-
|
23
|
-
|
24
|
-
MAX_COMMAND_LENGTH = 500
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
def initialize
|
29
|
-
# Stub method for future implementation
|
30
|
-
end
|
31
|
-
|
32
|
-
# Class-level
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
def self.execute_command(command)
|
39
|
-
new.execute_command(command)
|
40
|
-
end
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
def execute_command(command)
|
45
|
-
return "No command specified" if blank?(command)
|
46
|
-
|
47
|
-
validation_result = validate_command(command)
|
48
|
-
return validation_result if validation_result
|
49
|
-
|
50
|
-
`#{command}`.chomp
|
51
|
-
rescue StandardError => error
|
52
|
-
"Error executing shell command: #{error.message}"
|
53
|
-
end
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
def dangerous_command?(command)
|
58
|
-
return false if blank?(command)
|
59
|
-
DANGEROUS_PATTERNS.any? { |pattern| command =~ pattern }
|
60
|
-
end
|
61
|
-
|
62
|
-
private
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
def blank?(str)
|
67
|
-
str.nil? || str.strip.empty?
|
68
|
-
end
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
def validate_command(command)
|
73
|
-
command_length = command.length
|
74
|
-
|
75
|
-
if command_length > MAX_COMMAND_LENGTH
|
76
|
-
return "Error: Command too long (#{command_length} chars). Maximum length is #{MAX_COMMAND_LENGTH}."
|
77
|
-
end
|
78
|
-
|
79
|
-
|
80
|
-
is_dangerous = dangerous_command?(command)
|
81
|
-
|
82
|
-
|
83
|
-
if AIA.strict_shell_safety? && is_dangerous
|
84
|
-
return "Error: Potentially dangerous command blocked for security reasons: '#{command}'"
|
85
|
-
end
|
86
|
-
|
87
|
-
if AIA.shell_confirm? && is_dangerous
|
88
|
-
return prompt_confirmation(command)
|
89
|
-
end
|
90
|
-
|
91
|
-
nil # Command is valid
|
92
|
-
end
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
def prompt_confirmation(command)
|
101
|
-
puts "\n⚠️ WARNING: Potentially dangerous shell command detected:"
|
102
|
-
puts "\n #{command}\n"
|
103
|
-
print "\nDo you want to execute this command? [y/N]: "
|
104
|
-
confirm = STDIN.gets.chomp.downcase
|
105
|
-
return "Command execution canceled by user" unless confirm == 'y'
|
106
|
-
nil
|
107
|
-
end
|
108
|
-
end
|
109
|
-
end
|