#!/usr/bin/env ruby # encoding: utf-8 # frozen_string_literal: true # warn_indent: true ########################################################## ### ## File: aia ## Desc: AI Assistant ## Use generative AI with saved parameterized prompts ## By: Dewayne VanHoozer (dvanhoozer@gmail.com) ## ## This program makes use of the gem word_wrap's ## CLI tool: ww ## ## brew install fzf mods the_silver_searcher ripgrep # # TODO: refactor with a goal to isolate the search_proc and mods functionality # TODO: consider a config file. # TODO: remove use of CLI Helper. # TODO: consider --no-log # require 'pathname' HOME = Pathname.new( ENV['HOME'] ) PROMPTS_DIR = Pathname.new(ENV['PROMPTS_DIR'] || (HOME + ".prompts_dir")) require 'prompt_manager' require 'prompt_manager/storage/file_system_adapter' PromptManager::Prompt.storage_adapter = PromptManager::Storage::FileSystemAdapter.config do |config| config.prompts_dir = PROMPTS_DIR config.prompt_extension = '.txt' # default config.params_extension = '.json' # default # config.search_proc = nil # default end.new require 'amazing_print' require 'readline' # TODO: or reline ?? require 'word_wrap' require 'word_wrap/core_ext' require 'debug_me' include DebugMe require 'cli_helper' include CliHelper MODS_MODEL = ENV['MODS_MODEL'] || 'gpt-4-1106-preview' AI_CLI_PROGRAM = "mods" ai_default_opts = "-m #{MODS_MODEL} --no-limit -f" ai_options = ai_default_opts.dup extra_inx = ARGV.index('--') if extra_inx ai_options += " " + ARGV[extra_inx+1..].join(' ') ARGV.pop(ARGV.size - extra_inx) end AI_COMMAND = "#{AI_CLI_PROGRAM} #{ai_options} " EDITOR = ENV['EDITOR'] PROMPT_LOG = PROMPTS_DIR + "_prompts.log" # PROMPT_EXTNAME = ".txt" # DEFAULTS_EXTNAME = ".json" # SEARCH_COMMAND = "ag -l" # KEYWORD_REGEX = /(\[[A-Z _|]+\])/ configatron.version = '1.2.0' AI_CLI_PROGRAM_HELP = `#{AI_CLI_PROGRAM} --help` HELP = < ", false) puts a_string.empty? ? default : a_string end def log(prompt, answer) f = File.open(PROMPT_LOG, "ab") f.write <<~EOS ======================================= == #{Time.now} == #{prompt.path} PROMPT: #{prompt} RESULT: #{answer} EOS end def search_for_a_matching_prompt found_prompt_ids = PromptManager::Prompt.search( configatron.prompt_id ) if found_prompt_ids.size > 1 puts <<~EOS Search Results ============== The following prompt IDs have the search term '#{configatron.prompt_id}' #{found_prompt_ids.join(', ').wrap} EOS exit else configatron.prompt_id = found_prompt_ids.first configatron.prompt = PromptManager::Prompt.get(id: configatron.prompt_id) end end ###################################################### # Main at_exit do puts puts "Done." puts end ap configatron.to_h if debug? begin configatron.prompt = PromptManager::Prompt.get(id: configatron.prompt_id) rescue ArgumentError search_for_a_matching_prompt end puts puts "PROMPT:" puts configatron.prompt.text.wrap puts unless configatron.prompt.keywords.empty? replace_keywords configatron.prompt.build configatron.prompt.save end command = AI_COMMAND + configatron.prompt.to_s configatron.input_files.each do |input_file| command += " < #{input_file}" end print "\n\n" if verbose? && !keywords.empty? if verbose? puts "="*42 puts command puts "="*42 print "\n\n" end result = `#{command}` configatron.output.write result log configatron.prompt, result __END__