Module: AiCli::Helpers::Completion
- Defined in:
- lib/aicli/helpers/completion.rb
Constant Summary collapse
- SHELL_CODE_EXCLUSIONS =
[/```[a-zA-Z]*\n/i, /```[a-zA-Z]*/i, "\n"].freeze
Class Method Summary collapse
- .ask(prompt, config, exclusions) ⇒ Object
- .chat_system_prompt ⇒ Object
- .explain_script ⇒ Object
- .explanation_prompt(script) ⇒ Object
- .extract_commands(text) ⇒ Object
- .full_prompt(prompt) ⇒ Object
- .generation_details ⇒ Object
- .get_explanation(script:, config:) ⇒ Object
- .get_models(provider) ⇒ Object
- .get_revision(prompt:, code:, config:) ⇒ Object
- .get_script(prompt:, config:) ⇒ Object
- .revision_prompt(prompt, code) ⇒ Object
- .start_chat(config) ⇒ Object
- .stream_chat_message(chat, message, writer:) ⇒ Object
Class Method Details
.ask(prompt, config, exclusions) ⇒ Object
67 68 69 |
# File 'lib/aicli/helpers/completion.rb', line 67 def ask(prompt, config, exclusions) ask_stream(prompt, config, exclusions) { |_chunk| } end |
.chat_system_prompt ⇒ Object
30 31 32 33 34 35 36 37 38 39 40 |
# File 'lib/aicli/helpers/completion.rb', line 30 def chat_system_prompt <<~PROMPT You are ai, a terminal assistant. The user is asking for shell commands. Target OS: #{OsDetect.} Target shell: #{OsDetect.detect_shell} Whenever you suggest a command the user can run, put the exact runnable command alone inside a markdown fenced code block. Prefer a single command. PROMPT end |
.explain_script ⇒ Object
116 117 118 |
# File 'lib/aicli/helpers/completion.rb', line 116 def explain_script 'In one or two short sentences, explain what the script does. Plain text only.' end |
.explanation_prompt(script) ⇒ Object
108 109 110 111 112 113 114 |
# File 'lib/aicli/helpers/completion.rb', line 108 def explanation_prompt(script) <<~PROMPT #{explain_script} Please reply in #{I18n.current_language_name} The script: #{script} PROMPT end |
.extract_commands(text) ⇒ Object
42 43 44 45 46 47 48 49 |
# File 'lib/aicli/helpers/completion.rb', line 42 def extract_commands(text) return [] if text.nil? || text.empty? text.scan(/```(?:[a-zA-Z0-9_+-]*)\s*\n?(.*?)```/m) .flatten .map { |block| block.strip.gsub(/\A`+|`+\z/, '') } .reject(&:empty?) end |
.full_prompt(prompt) ⇒ Object
128 129 130 131 132 133 134 135 136 137 138 |
# File 'lib/aicli/helpers/completion.rb', line 128 def full_prompt(prompt) <<~PROMPT Create a single line command that one can enter in a terminal and run, based on what is specified in the prompt. The target shell is #{OsDetect.detect_shell} #{generation_details} The prompt is: #{prompt} PROMPT end |
.generation_details ⇒ Object
120 121 122 123 124 125 126 |
# File 'lib/aicli/helpers/completion.rb', line 120 def generation_details <<~DETAILS.chomp Only reply with the single line command surrounded by three backticks. It must be able to be directly run in the target shell. Do not include any other text. Make sure the command runs on #{OsDetect.} operating system. DETAILS end |
.get_explanation(script:, config:) ⇒ Object
14 15 16 |
# File 'lib/aicli/helpers/completion.rb', line 14 def get_explanation(script:, config:) ask(explanation_prompt(script), config, []) end |
.get_models(provider) ⇒ Object
22 23 24 |
# File 'lib/aicli/helpers/completion.rb', line 22 def get_models(provider) Llm.list_chat_models(provider) end |
.get_revision(prompt:, code:, config:) ⇒ Object
18 19 20 |
# File 'lib/aicli/helpers/completion.rb', line 18 def get_revision(prompt:, code:, config:) ask(revision_prompt(prompt, code), config, SHELL_CODE_EXCLUSIONS) end |
.get_script(prompt:, config:) ⇒ Object
10 11 12 |
# File 'lib/aicli/helpers/completion.rb', line 10 def get_script(prompt:, config:) ask(full_prompt(prompt), config, SHELL_CODE_EXCLUSIONS) end |
.revision_prompt(prompt, code) ⇒ Object
140 141 142 143 144 145 146 147 148 149 150 |
# File 'lib/aicli/helpers/completion.rb', line 140 def revision_prompt(prompt, code) <<~PROMPT Update the following script based on what is asked in the following prompt. The script: #{code} The prompt: #{prompt} #{generation_details} PROMPT end |
.start_chat(config) ⇒ Object
26 27 28 |
# File 'lib/aicli/helpers/completion.rb', line 26 def start_chat(config) Llm.build_chat(config).tap { |chat| chat.with_instructions(chat_system_prompt) } end |
.stream_chat_message(chat, message, writer:) ⇒ Object
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
# File 'lib/aicli/helpers/completion.rb', line 51 def (chat, , writer:) data = +'' chat.ask() do |chunk| content = chunk.content.to_s next if content.empty? data << content writer.call(content) end data rescue RubyLLM::Error, RubyLLM::ConfigurationError => e handle_ruby_llm_error(e) end |