aia 0.0.1

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 993c2562cf2bad7c76f3408376883dc32cc8d7b69a6810f16cecf7753360f2e6
4
+ data.tar.gz: 1e7f5c44c0b4e5d753a43aad73cb7bd2e681b0873c26ecaf0b185be86536b03d
5
+ SHA512:
6
+ metadata.gz: 47cc84453f2f57bf5f996546ea63c7232866906e27409448aa11e63b43ff7e0045412da5c55637f039bee39a04044c569a2fd368ba12a3248d41d68a1e699d79
7
+ data.tar.gz: fd72b98ba96ce71f0da3cb81c467d3b326608878df6062f9ad8dcccf55767aef14aaff84ed918118ab926d6422b0a5b1122a035440753f52ee6960b9aba19ef6
data/.envrc ADDED
@@ -0,0 +1 @@
1
+ export RR=`pwd`
data/CHANGELOG.md ADDED
@@ -0,0 +1,5 @@
1
+ ## [Unreleased]
2
+
3
+ ## [0.1.0] - 2023-11-23
4
+
5
+ - Initial release
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2023 Dewayne VanHoozer
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2023 Dewayne VanHoozer
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,86 @@
1
+ # AI Assistant (AIA)
2
+
3
+ **Under Development**
4
+
5
+ `aia` is a command-line utility that integrates prameterized prompt management with generative AI (gen-AI) execution.
6
+
7
+ Uses the gem "prompt_manager" to manage the prompts sent to the `mods` command-line utility. Uses the command line tools "ripgrep" to search for prompts to send and "fzf" to select the prompts that match the search term.
8
+
9
+
10
+
11
+ ## Installation
12
+
13
+ Install the gem by executing:
14
+
15
+ gem install aia
16
+
17
+
18
+ Install the command-line utilities by executing:
19
+
20
+ brew install mods fzf ripgrep
21
+
22
+ You will also need to establish a directory in your file system where your prompt text files, last used parameters and usage log files are kept.
23
+
24
+ Setup a system environment variable named "PROMPTS_DIR" that points to your prompts directory. The default is in your HOME directory named ".prompts_dir"
25
+
26
+ You will also need to source the completion script.
27
+
28
+ TODO: May want to add a `setup` function to the command-line options that will create the directory, and do something with the completion function.
29
+
30
+ TODO: don't forget to mention have access token (API keys) setup as envars for the various backend services like OpenAI... if they are still in business.
31
+
32
+ ## Usage
33
+
34
+ `aia prompt_id [context_file]*`
35
+
36
+ `prompt_id` is the basename of the `prompt_id.txt` file that is located in the `$PROMPTS_DIR` directory. There is also a `prompt_id.json` file saved in the same place to hold the last-used values (parameters) for the keywords (if any) found in your prompt file.
37
+
38
+ TODO: consider a config file.
39
+ TODO: consider a --no-log option to turn off logging
40
+
41
+ The `_prompts.log` file is also located in the `$PROMPTS_DIR`
42
+
43
+ The default output file is `temp.md` which is written to the current directory from which `aia` was executed.
44
+
45
+
46
+ ```text
47
+ $ aia -h
48
+ Use generative AI with saved parameterized prompts
49
+
50
+ Usage: aia [options] ...
51
+
52
+ Where:
53
+
54
+ Common Options Are:
55
+ -h, --help show this message
56
+ -v, --verbose enable verbose mode
57
+ -d, --debug enable debug mode
58
+ --version print the version: 1.2.0
59
+
60
+ Program Options Are:
61
+ -f, --fuzzy Allow fuzzy matching
62
+ -o, --output The output file
63
+
64
+ AI Assistant (aia)
65
+ ==================
66
+
67
+ The AI cli program being used is: mods
68
+
69
+ The defaul options to mods are:
70
+ "-m gpt-4-1106-preview --no-limit -f"
71
+
72
+ You can pass additional CLI options to mods like this:
73
+ "aia my options -- options for mods"
74
+ ```
75
+
76
+ ## Development
77
+
78
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
79
+
80
+ ## Contributing
81
+
82
+ Bug reports and pull requests are welcome on GitHub at https://github.com/MadBomber/aia.
83
+
84
+ ## License
85
+
86
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ begin
4
+ require "tocer/rake/register"
5
+ rescue LoadError => error
6
+ puts error.message
7
+ end
8
+
9
+ Tocer::Rake::Register.call
10
+
11
+
12
+ require "bundler/gem_tasks"
13
+ require "rake/testtask"
14
+
15
+ Rake::TestTask.new(:test) do |t|
16
+ t.libs << "test"
17
+ t.libs << "lib"
18
+ t.test_files = FileList["test/**/test_*.rb"]
19
+ end
20
+
21
+ task default: :test
data/bin/aia ADDED
@@ -0,0 +1,272 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: utf-8
3
+ # frozen_string_literal: true
4
+ # warn_indent: true
5
+ ##########################################################
6
+ ###
7
+ ## File: aia
8
+ ## Desc: AI Assistant
9
+ ## Use generative AI with saved parameterized prompts
10
+ ## By: Dewayne VanHoozer (dvanhoozer@gmail.com)
11
+ ##
12
+ ## This program makes use of the gem word_wrap's
13
+ ## CLI tool: ww
14
+ ##
15
+ ## brew install fzf mods the_silver_searcher ripgrep
16
+ #
17
+ # TODO: refactor with a goal to isolate the search_proc and mods functionality
18
+ # TODO: consider a config file.
19
+ # TODO: remove use of CLI Helper.
20
+ # TODO: consider --no-log
21
+ #
22
+
23
+ require 'pathname'
24
+ HOME = Pathname.new( ENV['HOME'] )
25
+ PROMPTS_DIR = Pathname.new(ENV['PROMPTS_DIR'] || (HOME + ".prompts_dir"))
26
+
27
+ require 'prompt_manager'
28
+ require 'prompt_manager/storage/file_system_adapter'
29
+
30
+ PromptManager::Prompt.storage_adapter =
31
+ PromptManager::Storage::FileSystemAdapter.config do |config|
32
+ config.prompts_dir = PROMPTS_DIR
33
+ config.prompt_extension = '.txt' # default
34
+ config.params_extension = '.json' # default
35
+ # config.search_proc = nil # default
36
+ end.new
37
+
38
+
39
+
40
+ require 'amazing_print'
41
+ require 'readline' # TODO: or reline ??
42
+ require 'word_wrap'
43
+ require 'word_wrap/core_ext'
44
+
45
+ require 'debug_me'
46
+ include DebugMe
47
+
48
+ require 'cli_helper'
49
+ include CliHelper
50
+
51
+ MODS_MODEL = ENV['MODS_MODEL'] || 'gpt-4-1106-preview'
52
+
53
+ AI_CLI_PROGRAM = "mods"
54
+ ai_default_opts = "-m #{MODS_MODEL} --no-limit -f"
55
+ ai_options = ai_default_opts.dup
56
+
57
+ extra_inx = ARGV.index('--')
58
+
59
+ if extra_inx
60
+ ai_options += " " + ARGV[extra_inx+1..].join(' ')
61
+ ARGV.pop(ARGV.size - extra_inx)
62
+ end
63
+
64
+ AI_COMMAND = "#{AI_CLI_PROGRAM} #{ai_options} "
65
+ EDITOR = ENV['EDITOR']
66
+ PROMPT_LOG = PROMPTS_DIR + "_prompts.log"
67
+
68
+ # PROMPT_EXTNAME = ".txt"
69
+ # DEFAULTS_EXTNAME = ".json"
70
+
71
+ # SEARCH_COMMAND = "ag -l"
72
+ # KEYWORD_REGEX = /(\[[A-Z _|]+\])/
73
+
74
+
75
+ configatron.version = '1.2.0'
76
+
77
+ AI_CLI_PROGRAM_HELP = `#{AI_CLI_PROGRAM} --help`
78
+
79
+ HELP = <<EOHELP
80
+ AI Assistant (aia)
81
+ ==================
82
+
83
+ The AI cli program being used is: #{AI_CLI_PROGRAM}
84
+
85
+ The defaul options to #{AI_CLI_PROGRAM} are:
86
+ "#{ai_default_opts}"
87
+
88
+ You can pass additional CLI options to #{AI_CLI_PROGRAM} like this:
89
+ "#{my_name} my options -- options for #{AI_CLI_PROGRAM}"
90
+
91
+ EOHELP
92
+
93
+ cli_helper("Use generative AI with saved parameterized prompts") do |o|
94
+ o.bool '-f', '--fuzzy', 'Allow fuzzy matching', default: false
95
+ o.path '-o', '--output', 'The output file', default: Pathname.pwd + "temp.md"
96
+ end
97
+
98
+
99
+ AG_COMMAND = "ag --file-search-regex '\.txt$' e" # searching for the letter "e"
100
+ CD_COMMAND = "cd #{PROMPTS_DIR}"
101
+ FIND_COMMAND = "find . -name '*.txt'"
102
+
103
+ FZF_OPTIONS = [
104
+ "--tabstop=2", # 2 soaces for a tab
105
+ "--header='Prompt contents below'",
106
+ "--header-first",
107
+ "--prompt='Search term: '",
108
+ '--delimiter :',
109
+ "--preview 'ww {1}'", # ww comes from the word_wrap gem
110
+ "--preview-window=down:50%:wrap"
111
+ ].join(' ')
112
+
113
+ FZF_OPTIONS += " --exact" unless fuzzy?
114
+
115
+ FZF_COMMAND = "#{CD_COMMAND} ; #{FIND_COMMAND} | fzf #{FZF_OPTIONS}"
116
+ AG_FZF_COMMAND = "#{CD_COMMAND} ; #{AG_COMMAND} | fzf #{FZF_OPTIONS}"
117
+
118
+ # use `ag` to build a list of text lines from each prompt
119
+ # use `fzf` to search through that list to select a prompt file
120
+
121
+ def ag_fzf = `#{AG_FZF_COMMAND}`.split(':')&.first&.strip&.gsub('.txt','')
122
+
123
+
124
+
125
+ # The prompt_id is always the first argument
126
+ if configatron.arguments.empty?
127
+ show_usage
128
+ exit
129
+ end
130
+
131
+
132
+ def process_arguments
133
+ prompt_id = configatron.arguments.shift
134
+
135
+ if prompt_id.include?('.')
136
+ error "Invalid prompt_id: #{configatron.prompt_id}"
137
+ else
138
+ configatron.input_files = []
139
+ configatron.arguments.each do |arg|
140
+ file_path = Pathname.new(arg)
141
+ if file_path.exist?
142
+ configatron.input_files << file_path
143
+ else
144
+ error "File does not exist: #{file_path}"
145
+ end
146
+ end
147
+ end
148
+
149
+ prompt_id # may be invalid
150
+ end
151
+
152
+ configatron.prompt_id = process_arguments
153
+
154
+ abort_if_errors
155
+
156
+ ######################################################
157
+ # Local methods
158
+
159
+ def replace_keywords
160
+ defaults = configatron.prompt.parameters
161
+
162
+ configatron.prompt.keywords.each do |kw|
163
+ defaults[kw] = keyword_value(kw, defaults[kw])
164
+ end
165
+
166
+ configatron.prompt.parameters = defaults
167
+ configatron.prompt.save
168
+ end
169
+
170
+
171
+ def keyword_value(kw, default)
172
+ label = "Default: "
173
+ puts "#{kw} ..."
174
+ print label
175
+ puts default.wrap.split("\n").join("\n"+" "*label.length)
176
+ a_string = Readline.readline("\n-=> ", false)
177
+ puts
178
+ a_string.empty? ? default : a_string
179
+ end
180
+
181
+
182
+ def log(prompt, answer)
183
+ f = File.open(PROMPT_LOG, "ab")
184
+
185
+ f.write <<~EOS
186
+ =======================================
187
+ == #{Time.now}
188
+ == #{prompt.path}
189
+
190
+ PROMPT: #{prompt}
191
+
192
+ RESULT:
193
+ #{answer}
194
+
195
+ EOS
196
+ end
197
+
198
+
199
+ def search_for_a_matching_prompt
200
+ found_prompt_ids = PromptManager::Prompt.search(
201
+ configatron.prompt_id
202
+ )
203
+ if found_prompt_ids.size > 1
204
+ puts <<~EOS
205
+
206
+ Search Results
207
+ ==============
208
+
209
+ The following prompt IDs have the search term '#{configatron.prompt_id}'
210
+ #{found_prompt_ids.join(', ').wrap}
211
+
212
+ EOS
213
+ exit
214
+ else
215
+ configatron.prompt_id = found_prompt_ids.first
216
+ configatron.prompt = PromptManager::Prompt.get(id: configatron.prompt_id)
217
+ end
218
+ end
219
+
220
+ ######################################################
221
+ # Main
222
+
223
+ at_exit do
224
+ puts
225
+ puts "Done."
226
+ puts
227
+ end
228
+
229
+ ap configatron.to_h if debug?
230
+
231
+
232
+ begin
233
+ configatron.prompt = PromptManager::Prompt.get(id: configatron.prompt_id)
234
+ rescue ArgumentError
235
+ search_for_a_matching_prompt
236
+ end
237
+
238
+
239
+ puts
240
+ puts "PROMPT:"
241
+ puts configatron.prompt.text.wrap
242
+ puts
243
+
244
+ unless configatron.prompt.keywords.empty?
245
+ replace_keywords
246
+ configatron.prompt.build
247
+ configatron.prompt.save
248
+ end
249
+
250
+ command = AI_COMMAND + configatron.prompt.to_s
251
+
252
+ configatron.input_files.each do |input_file|
253
+ command += " < #{input_file}"
254
+ end
255
+
256
+ print "\n\n" if verbose? && !keywords.empty?
257
+
258
+ if verbose?
259
+ puts "="*42
260
+ puts command
261
+ puts "="*42
262
+ print "\n\n"
263
+ end
264
+
265
+ result = `#{command}`
266
+
267
+ configatron.output.write result
268
+
269
+ log configatron.prompt, result
270
+
271
+
272
+ __END__
@@ -0,0 +1,33 @@
1
+ # bin/aia_completion.sh
2
+ # Setup a prompt completion for use with
3
+ # aia (a Ruby program) AI Assistant
4
+ #
5
+ # Requires the $PROMPTS_DIR envar be set
6
+
7
+ # SMELL: Is this BASH-only or will it work with other shells?
8
+
9
+ # Function to generate prompt completions for aia
10
+
11
+ _aia_completion() {
12
+ # The current word being completed
13
+ local cur_word="${COMP_WORDS[COMP_CWORD]}"
14
+
15
+ # Store the previous directory to return to it later
16
+ local initial_pwd=$(pwd)
17
+
18
+ # Change directory to the prompts directory
19
+ cd $PROMPTS_DIR
20
+
21
+ # Generate a list of relative paths from the ~/.prompts directory (without .txt extension)
22
+ local files=($(find . -name "*.txt" -type f | sed 's|^\./||' | sed 's/\.txt$//'))
23
+
24
+ # Change back to the initial directory
25
+ cd "$initial_pwd"
26
+
27
+ # Generate possible matches and store them in the COMPREPLY array
28
+ COMPREPLY=($(compgen -W "${files[*]}" -- "$cur_word"))
29
+ }
30
+
31
+
32
+ # Register the completion function for the aip command
33
+ complete -F _aia_completion aia
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AIA
4
+ VERSION = "0.0.1"
5
+ end
data/lib/aia.rb ADDED
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "aia/version"
4
+
5
+ module AIA
6
+ class Error < StandardError; end
7
+ # Your code goes here...
8
+ end
metadata ADDED
@@ -0,0 +1,147 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: aia
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Dewayne VanHoozer
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2023-11-24 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: prompt_manager
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: word_wrap
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: amazing_print
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: debug_me
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: minitest
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: tocer
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ description: "A command-line AI Assistante (aia) that provides\nparameterized prompt
98
+ management (via the prompt_manager gem) to\nvarious backend gen-AI processes. Currently
99
+ supports the `mods`\nCLI tool. `aia`uses `ripgrep` and `fzf` command-line utilities
100
+ \nto search for and select prompt files to send to the backend gen-AI\ntool along
101
+ with supported context files.\n"
102
+ email:
103
+ - dvanhoozer@gmail.com
104
+ executables:
105
+ - aia
106
+ - aia_completion.sh
107
+ extensions: []
108
+ extra_rdoc_files: []
109
+ files:
110
+ - ".envrc"
111
+ - CHANGELOG.md
112
+ - LICENSE
113
+ - LICENSE.txt
114
+ - README.md
115
+ - Rakefile
116
+ - bin/aia
117
+ - bin/aia_completion.sh
118
+ - lib/aia.rb
119
+ - lib/aia/version.rb
120
+ homepage: https://github.com/MadBomber/aia
121
+ licenses:
122
+ - MIT
123
+ metadata:
124
+ allowed_push_host: https://rubygems.org
125
+ homepage_uri: https://github.com/MadBomber/aia
126
+ source_code_uri: https://github.com/MadBomber/aia
127
+ changelog_uri: https://github.com/MadBomber/aia
128
+ post_install_message:
129
+ rdoc_options: []
130
+ require_paths:
131
+ - lib
132
+ required_ruby_version: !ruby/object:Gem::Requirement
133
+ requirements:
134
+ - - ">="
135
+ - !ruby/object:Gem::Version
136
+ version: 3.2.0
137
+ required_rubygems_version: !ruby/object:Gem::Requirement
138
+ requirements:
139
+ - - ">="
140
+ - !ruby/object:Gem::Version
141
+ version: '0'
142
+ requirements: []
143
+ rubygems_version: 3.4.22
144
+ signing_key:
145
+ specification_version: 4
146
+ summary: AI Assistant (aia) a command-ling utility
147
+ test_files: []