aia 0.5.2 → 0.5.6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 35bff72b31591194079e96f6e1dfab9dc76db90fda1f635e962377aeb77b5662
4
- data.tar.gz: 60704012ba00cca73bdb6bb344a4207df189b97b5dc2d686a53215836c5d27d5
3
+ metadata.gz: '021416691c11252ce3462ee7ec394691e0a7d0fd81eb6df473df3447dd02da3b'
4
+ data.tar.gz: 2bd5eb6bd2098c7e9bd04234a11c1192004bb217ec054aa9222334d9b96309d2
5
5
  SHA512:
6
- metadata.gz: a7b3f5bb0bee380f3863bfe80599e8898e16143587d374db27f99d27a718433d9e6869da1a8f44207016185c0b28935b5c5edbaf45d939992ad58ecd65a68fa9
7
- data.tar.gz: 3f4fd8f0707e55cfc2147090d55ff4c865eba8c14bb22bb07831b3e46653530c9800a8d69f148e978bcb763a91d47ac3b58c1f2ab19e387019d6537b9446059e
6
+ metadata.gz: 0e2d78c3b6b1b8848645ef586c3b2f7a4557339504efc1a7434b12e313637e47b6803da8e5fa21908f88ee59046a372ef22553a5fdffe97d5777b65845f5ce41
7
+ data.tar.gz: 142dd7b40622124089363670fcb6ffde02368ad07de7016e6c12e0511a47d89d8b0be9b153d31076758c321e6762e1d361fd4ac086b6f8ffca8d2a2abebeff7b
data/.semver CHANGED
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  :major: 0
3
3
  :minor: 5
4
- :patch: 2
4
+ :patch: 6
5
5
  :special: ''
6
6
  :metadata: ''
data/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [0.5.6] 2024-01-15
4
+ - Adding processing for directives, shell integration and erb to the follow up prompt in a chat session
5
+ - some code refactoring.
6
+
7
+ ## [0.5.3] 2024-01-14
8
+ - adding ability to render markdown to the terminal using the "glow" CLI utility
9
+
3
10
  ## [0.5.2] 2024-01-13
4
11
  - wrap response when its going to the terminal
5
12
 
data/README.md CHANGED
@@ -5,6 +5,15 @@
5
5
  It leverages the `prompt_manager` gem to manage prompts for the `mods` and `sgpt` CLI utilities. It utilizes "ripgrep" for searching for prompt files. It uses `fzf` for prompt selection based on a search term and fuzzy matching.
6
6
 
7
7
  **Most Recent Change**: Refer to the [Changelog](CHANGELOG.md)
8
+ v0.5.6
9
+ - Directives within a chat session follow up are now available
10
+ - when the `--shell` option is set access to envars and shell scripts are availabe in a chat session follow up prompt
11
+ - when the `--erb` option is set, access to ERB-based dynamic content is available in a chat session follow up prompt.
12
+
13
+ v0.5.3
14
+ - `--render` will render markdown formatted content to the terminal using the `glow` CLI utility.
15
+ - fixes to some terminal UI stuff like AI response is not being wrapped to the terminal width to make for easier reading.
16
+ - fixed the completion functions to use the correct $AIA_PROMPTS_DIR envar
8
17
 
9
18
  v0.5.0 - Breaking changes:
10
19
  - `--config` is now `--config_file`
@@ -21,11 +30,14 @@ v0.5.0 - Breaking changes:
21
30
  - [Shell Integration inside of a Prompt](#shell-integration-inside-of-a-prompt)
22
31
  - [Access to System Environment Variables](#access-to-system-environment-variables)
23
32
  - [Dynamic Shell Commands](#dynamic-shell-commands)
33
+ - [Chat Session Use](#chat-session-use)
24
34
  - [*E*mbedded *R*u*B*y (ERB)](#embedded-ruby-erb)
35
+ - [Chat Session Behavior](#chat-session-behavior)
25
36
  - [Prompt Directives](#prompt-directives)
26
37
  - [`aia` Specific Directive Commands](#aia-specific-directive-commands)
27
38
  - [//config](#config)
28
39
  - [Backend Directive Commands](#backend-directive-commands)
40
+ - [Using Directives in Chat Sessions](#using-directives-in-chat-sessions)
29
41
  - [All About ROLES](#all-about-roles)
30
42
  - [Other Ways to Insert Roles into Prompts](#other-ways-to-insert-roles-into-prompts)
31
43
  - [External CLI Tools Used](#external-cli-tools-used)
@@ -97,7 +109,15 @@ ARGUMENTS
97
109
 
98
110
  OPTIONS
99
111
  --chat begin a chat session with the backend after the initial prompt response; will
100
- set --no-out_file so that the backend response comes to STDOUT.
112
+ set --no-out_file so that the backend response comes to STDOUT. After the
113
+ initial prompt is processed, you will be asked to provide a follow up. Just
114
+ enter whatever is appropriate terminating your input with a RETURN. The
115
+ backend will provide a response to you follow up and ask you again if you have
116
+ another follow up. This back and forth chatting will continue until you enter a
117
+ RETURN without any other content - an empty follow up prompt. You may also
118
+ enter a directive to be processed after which another follow up is requested.
119
+ If you have the --shell and/or the --erb options set you may use those tools
120
+ within your follow up to provide dynamic content.
101
121
 
102
122
  --completion SHELL_NAME
103
123
 
@@ -125,6 +145,9 @@ OPTIONS
125
145
  --model NAME
126
146
  Name of the LLM model to use - default is gpt-4-1106-preview
127
147
 
148
+ --render
149
+ Render markdown to the terminal using the external tool “glow” - default: false
150
+
128
151
  --speak
129
152
  Simple implementation. Uses the “say” command to speak the response. Fun with
130
153
  --chat
@@ -251,12 +274,29 @@ SEE ALSO
251
274
  text, and more, using simple commands. Streamline your workflow and enhance
252
275
  productivity with this powerful and user-friendly CLI tool.
253
276
 
277
+ • fzf <https://github.com/junegunn/fzf>
278
+ fzf is a general-purpose command-line fuzzy finder. It’s an interactive
279
+ Unix filter for command-line that can be used with any list; files, command
280
+ history, processes, hostnames, bookmarks, git commits, etc.
281
+
282
+ • ripgrep <https://github.com/BurntSushi/ripgrep>
283
+ Search tool like grep and The Silver Searcher. It is a line-oriented search
284
+ tool that recursively searches a directory tree for a regex pattern. By
285
+ default, ripgrep will respect gitignore rules and automatically skip hidden
286
+ files/directories and binary files. (To disable all automatic filtering by
287
+ default, use rg -uuu.) ripgrep has first class support on Windows, macOS and
288
+ Linux, with binary downloads available for every release.
289
+
290
+ • glow <https://github.com/charmbracelet/glow>
291
+ Render markdown on the CLI
292
+
254
293
  AUTHOR
255
294
  Dewayne VanHoozer <dvanhoozer@gmail.com>
256
295
 
257
296
  AIA 2024-01-01 aia(1)
258
297
  ```
259
298
 
299
+
260
300
  ## Configuration Using Envars
261
301
 
262
302
  The `aia` configuration defaults can be over-ridden by system environment variables *(envars)* with the prefix "AIA_" followed by the config item name also in uppercase. All configuration items can be over-ridden in this way by an envar. The following table show a few examples.
@@ -305,6 +345,15 @@ or insert content from a file in your home directory:
305
345
  Given the following constraints $(cat ~/3_laws_of_robotics.txt) determine the best way to instruct my roomba to clean my kids room.
306
346
  ```
307
347
 
348
+ #### Chat Session Use
349
+
350
+ When you use the `--shell` option to start a chat session, shell integration is available in your follow up prompts. Suppose you started up a chat session using a roll of "Ruby Expert" expecting to chat about changes that could be made to a specific class BUT you forgot to include the class source file as part of the context when you got started. You could enter this as your follow up prompt to this to keep going:
351
+
352
+ ```
353
+ The class I want to chat about refactoring is this one: $(cat my_class.rb)
354
+ ```
355
+
356
+ That inserts the entire class source file into your follow up prompt. You can continue chatting with you AI Assistant avout changes to the class.
308
357
 
309
358
  ## *E*mbedded *R*u*B*y (ERB)
310
359
 
@@ -314,6 +363,11 @@ The `--erb` option turns the prompt text file into a fully functioning ERB templ
314
363
 
315
364
  Most websites that have information about ERB will give examples of how to use ERB to generate dynamice HTML content for web-based applications. That is a common use case for ERB. `aia` on the other hand uses ERB to generate dynamic prompt text.
316
365
 
366
+ ### Chat Session Behavior
367
+
368
+ In a chat session whether started by the `--chat` option or its equivalent with a directive within a prompt text file behaves a little differently w/r/t its binding and local variable assignments. Since a chat session by definition has multiple prompts, setting a local variable in one prompt and expecting it to be available in a subsequent prompt does not work. You need to use instance variables to accomplish this prompt to prompt carry over of information.
369
+
370
+ Also since follow up prompts are expected to be a single thing - sentence or paragraph - terminated by a single return, its likely that ERB enhance will be of benefit; but, you may find a use for it.
317
371
 
318
372
  ## Prompt Directives
319
373
 
@@ -367,6 +421,17 @@ FOr example `mods` has a configuration item `topp` which can be set by a directi
367
421
 
368
422
  If `mods` is not the backend the `//topp` direcive is ignored.
369
423
 
424
+ ### Using Directives in Chat Sessions
425
+
426
+ Whe you are in a chat session, you may use a directive as a follow up prompt. For example if you started the chat session with the option `--terse` expecting to get short answers from the backend; but, then you decide that you want more comprehensive answers you may do this:
427
+
428
+ ```
429
+ //config terse? false
430
+ ```
431
+
432
+ The directive is executed and a new follow up prompt can be entered with a more lengthy response generated from the backend.
433
+
434
+
370
435
  ## All About ROLES
371
436
 
372
437
  `aia` provides the `--role` CLI option to identify a prompt ID within your prompts directory which defines the context within which the LLM is to provide its response. The text of the role ID is pre-pended to the text of the primary prompt to form a complete prompt to be processed by the backend.
@@ -402,31 +467,32 @@ When this prompt is processed, `aia` will ask you for a value for the keyword "R
402
467
 
403
468
  ## External CLI Tools Used
404
469
 
405
- ```text
406
- External Tools Used
407
- -------------------
408
-
409
470
  To install the external CLI programs used by aia:
410
- brew install fzf mods rg
471
+
472
+ brew install fzf mods rg glow
411
473
 
412
474
  fzf
413
475
  Command-line fuzzy finder written in Go
414
- https://github.com/junegunn/fzf
476
+ [https://github.com/junegunn/fzf](https://github.com/junegunn/fzf)
415
477
 
416
478
  mods
417
479
  AI on the command-line
418
- https://github.com/charmbracelet/mods
480
+ [https://github.com/charmbracelet/mods](https://github.com/charmbracelet/mods)
419
481
 
420
482
  rg
421
483
  Search tool like grep and The Silver Searcher
422
- https://github.com/BurntSushi/ripgrep
484
+ [https://github.com/BurntSushi/ripgrep](https://github.com/BurntSushi/ripgrep)
485
+
486
+ glow
487
+ Render markdown on the CLI
488
+ [https://github.com/charmbracelet/glow](https://github.com/charmbracelet/glow)
423
489
 
424
490
  A text editor whose executable is setup in the
425
491
  system environment variable 'EDITOR' like this:
426
492
 
427
- export EDITOR="subl -w"
493
+ export EDITOR="subl -w"
494
+
428
495
 
429
- ```
430
496
 
431
497
  ## Shell Completion
432
498
 
data/lib/aia/cli.rb CHANGED
@@ -125,18 +125,19 @@ class AIA::Cli
125
125
  dump: [nil, "--dump"],
126
126
  completion: [nil, "--completion"],
127
127
  #
128
+ chat?: [false, "--chat"],
129
+ debug?: [false, "-d --debug"],
128
130
  edit?: [false, "-e --edit"],
129
- shell?: [false, "--shell"],
130
131
  erb?: [false, "--erb"],
131
- debug?: [false, "-d --debug"],
132
- verbose?: [false, "-v --verbose"],
133
- version?: [false, "--version"],
134
- help?: [false, "-h --help"],
135
132
  fuzzy?: [false, "-f --fuzzy"],
133
+ help?: [false, "-h --help"],
136
134
  markdown?: [true, "-m --markdown --no-markdown --md --no-md"],
137
- chat?: [false, "--chat"],
138
- terse?: [false, "--terse"],
135
+ render?: [false, "--render"],
136
+ shell?: [false, "--shell"],
139
137
  speak?: [false, "--speak"],
138
+ terse?: [false, "--terse"],
139
+ verbose?: [false, "-v --verbose"],
140
+ version?: [false, "--version"],
140
141
  #
141
142
  role: ['', "-r --role"],
142
143
  #
@@ -2,13 +2,15 @@
2
2
 
3
3
  require 'hashie'
4
4
 
5
- class AIA::Directives
6
- def initialize( prompt: )
7
- @prompt = prompt # PromptManager::Prompt instance
8
- AIA.config.directives = @prompt.directives
9
- end
5
+ =begin
6
+ AIA.config.directives is an Array of Arrays. An
7
+ entry looks like this:
8
+ [directive, parameters]
9
+ where both are String objects
10
+ =end
10
11
 
11
12
 
13
+ class AIA::Directives
12
14
  def execute_my_directives
13
15
  return if AIA.config.directives.nil? || AIA.config.directives.empty?
14
16
 
@@ -0,0 +1,26 @@
1
+ # aia/lib/aia/dynamic_content.rb
2
+
3
+ require 'erb'
4
+
5
+ module AIA::DynamicContent
6
+
7
+ # inserts environment variables (envars) and dynamic content into a prompt
8
+ # replaces patterns like $HOME and ${HOME} with the value of ENV['HOME']
9
+ # replaces patterns like $(shell command) with the output of the shell command
10
+ #
11
+ def render_env(a_string)
12
+ a_string.gsub(/\$(\w+|\{\w+\})/) do |match|
13
+ ENV[match.tr('$', '').tr('{}', '')]
14
+ end.gsub(/\$\((.*?)\)/) do |match|
15
+ `#{match[2..-2]}`.chomp
16
+ end
17
+ end
18
+
19
+
20
+ # Need to use instance variables in assignments
21
+ # to maintain binding from one follow up prompt
22
+ # to another.
23
+ def render_erb(the_prompt_text)
24
+ ERB.new(the_prompt_text).result(binding)
25
+ end
26
+ end
data/lib/aia/main.rb CHANGED
@@ -5,6 +5,7 @@ module AIA ; end
5
5
  require_relative 'config'
6
6
  require_relative 'cli'
7
7
  require_relative 'directives'
8
+ require_relative 'dynamic_content'
8
9
  require_relative 'prompt'
9
10
  require_relative 'logging'
10
11
  require_relative 'tools'
@@ -13,6 +14,7 @@ require_relative 'tools'
13
14
  # of a single class.
14
15
 
15
16
  class AIA::Main
17
+ include AIA::DynamicContent
16
18
 
17
19
  attr_accessor :logger, :tools, :backend
18
20
 
@@ -33,7 +35,8 @@ class AIA::Main
33
35
 
34
36
  @prompt = AIA::Prompt.new.prompt
35
37
 
36
- @engine = AIA::Directives.new(prompt: @prompt)
38
+
39
+ @directives_processor = AIA::Directives.new
37
40
 
38
41
  # TODO: still should verify that the tools are ion the $PATH
39
42
  # tools.class.verify_tools
@@ -57,6 +60,7 @@ class AIA::Main
57
60
  # Function to prompt the user with a question using reline
58
61
  def ask_question_with_reline(prompt)
59
62
  if prompt.start_with?("\n")
63
+ puts
60
64
  puts
61
65
  prompt = prompt[1..]
62
66
  end
@@ -70,7 +74,7 @@ class AIA::Main
70
74
 
71
75
 
72
76
  def call
73
- @engine.execute_my_directives
77
+ @directives_processor.execute_my_directives
74
78
 
75
79
  if AIA.config.chat?
76
80
  AIA.config.out_file = STDOUT
@@ -111,20 +115,10 @@ class AIA::Main
111
115
  files: AIA.config.arguments # FIXME: want validated context files
112
116
  )
113
117
 
114
-
115
- result = backend.run
116
-
117
- if STDOUT == AIA.config.out_file
118
- result = result.wrap(indent: 2)
119
- end
120
-
121
- # TODO: consider using glow to render markdown to
122
- # terminal `brew install glow`
123
- AIA.config.out_file.write result
118
+ result = get_and_display_result(the_prompt)
124
119
 
125
120
  logger.prompt_result(@prompt, result)
126
121
 
127
-
128
122
  if AIA.config.chat?
129
123
  setup_reline_history
130
124
  speak result
@@ -133,36 +127,87 @@ class AIA::Main
133
127
  end
134
128
 
135
129
 
136
- def lets_chat
130
+ def get_and_display_result(the_prompt_text)
131
+ backend.text = the_prompt_text
132
+ result = backend.run
133
+
134
+ AIA.config.out_file.write "\nResponse:\n"
135
+
136
+ if STDOUT == AIA.config.out_file
137
+ if AIA.config.render?
138
+ AIA::Glow.new(content: result).run
139
+ else
140
+ result = result.wrap(indent: 2)
141
+ AIA.config.out_file.write result
142
+ end
143
+ else
144
+ AIA.config.out_file.write result
145
+ if AIA.config.render?
146
+ AIA::Glow.new(file_path: AIA.config.out_file).run
147
+ end
148
+ end
149
+
150
+ result
151
+ end
152
+
153
+
154
+ def log_the_follow_up(the_prompt_text, result)
155
+ logger.info "Follow Up:\n#{the_prompt_text}"
156
+ logger.info "Response:\n#{result}"
157
+ end
158
+
159
+
160
+ def add_continue_option
137
161
  if 'mods' == AIA.config.backend
138
- AIA.config.extra += " -C"
162
+ continue_option = " -C"
163
+ AIA.config.extra += continue_option unless AIA.config.extra.include?(continue_option)
139
164
  end
140
-
141
- backend.text = ask_question_with_reline("\nFollow Up: ")
142
-
143
- until backend.text.empty?
144
- if AIA.config.terse?
145
- backend.text.prepend "Be terse in your response. "
146
- end
147
-
148
- logger.info "Follow Up: #{backend.text}"
149
- response = backend.run
150
-
151
- speak response
152
-
153
- puts "\nResponse:\n#{response.wrap(indent: 2)}"
154
- logger.info "Response: #{backend.run}"
165
+ end
166
+
167
+
168
+ def insert_terse_phrase(a_string)
169
+ if AIA.config.terse?
170
+ a_string.prepend "Be terse in your response. "
171
+ end
172
+
173
+ a_string
174
+ end
175
+
155
176
 
156
- # TODO: Allow user to enter a directive; loop
157
- # until answer is not a directive
158
- #
159
- # while !directive do
160
- backend.text = ask_question_with_reline("\nFollow Up: ")
161
-
162
- speak backend.text
163
-
164
- # execute the directive
165
- # end
177
+ def handle_directives(the_prompt_text)
178
+ signal = PromptManager::Prompt::DIRECTIVE_SIGNAL
179
+ result = the_prompt_text.start_with?(signal)
180
+
181
+ if result
182
+ parts = the_prompt_text[signal.size..].split(' ')
183
+ directive = parts.shift
184
+ parameters = parts.join(' ')
185
+ AIA.config.directives << [directive, parameters]
186
+ @directives_processor.execute_my_directives
187
+ end
188
+
189
+ result
190
+ end
191
+
192
+
193
+ def lets_chat
194
+ add_continue_option
195
+
196
+ the_prompt_text = ask_question_with_reline("\nFollow Up: ")
197
+
198
+ until the_prompt_text.empty?
199
+ the_prompt_text = render_erb(the_prompt_text) if AIA.config.erb?
200
+ the_prompt_text = render_env(the_prompt_text) if AIA.config.shell?
201
+
202
+ unless handle_directives(the_prompt_text)
203
+ the_prompt_text = insert_terse_phrase(the_prompt_text)
204
+ result = get_and_display_result(the_prompt_text)
205
+
206
+ log_the_follow_up(the_prompt_text, result)
207
+ speak result
208
+ end
209
+
210
+ the_prompt_text = ask_question_with_reline("\nFollow Up: ")
166
211
  end
167
212
  end
168
213
  end
data/lib/aia/prompt.rb CHANGED
@@ -1,9 +1,12 @@
1
1
  # lib/aia/prompt.rb
2
2
 
3
3
  require 'reline'
4
- require 'erb'
4
+
5
+ require_relative 'dynamic_content'
5
6
 
6
7
  class AIA::Prompt
8
+ include AIA::DynamicContent
9
+
7
10
  #
8
11
  # used when no prompt_id is provided but there
9
12
  # are extra parameters that need to be passed
@@ -42,9 +45,11 @@ class AIA::Prompt
42
45
 
43
46
  if build
44
47
  @prompt.text = render_erb(@prompt.text) if AIA.config.erb?
45
- @prompt.text = replace_env(@prompt.text) if AIA.config.shell?
48
+ @prompt.text = render_env(@prompt.text) if AIA.config.shell?
46
49
  process_prompt
47
50
  end
51
+
52
+ AIA.config.directives = @prompt.directives
48
53
  end
49
54
 
50
55
 
@@ -93,25 +98,6 @@ class AIA::Prompt
93
98
  end
94
99
 
95
100
 
96
- # inserts environmant variables and dynamic content into a prompt
97
- # replaces patterns like $HOME and ${HOME} with the value of ENV['HOME']
98
- # replaces patterns like $(shell command) with the output of the shell command
99
- #
100
- def replace_env(a_string)
101
- a_string.gsub(/\$(\w+|\{\w+\})/) do |match|
102
- ENV[match.tr('$', '').tr('{}', '')]
103
- end.gsub(/\$\((.*?)\)/) do |match|
104
- `#{match[2..-2]}`.chomp
105
- end
106
- end
107
-
108
-
109
- # You are just asking for trouble!
110
- def render_erb(a_string)
111
- ERB.new(a_string).result(binding)
112
- end
113
-
114
-
115
101
  def replace_keywords
116
102
  puts
117
103
  puts "ID: #{@prompt.id}"
@@ -151,6 +137,7 @@ class AIA::Prompt
151
137
  # Function to prompt the user with a question using reline
152
138
  def ask_question_with_reline(prompt)
153
139
  if prompt.start_with?("\n")
140
+ puts
154
141
  puts
155
142
  prompt = prompt[1..]
156
143
  end
@@ -12,9 +12,12 @@ module AIA::BackendCommon
12
12
  build_command
13
13
  end
14
14
 
15
+
15
16
  def sanitize(input)
16
17
  Shellwords.escape(input)
17
18
  end
19
+
20
+
18
21
  def build_command
19
22
  @parameters += " --model #{AIA.config.model} " if AIA.config.model
20
23
  @parameters += AIA.config.extra
@@ -29,6 +32,7 @@ module AIA::BackendCommon
29
32
  @command
30
33
  end
31
34
 
35
+
32
36
  def set_parameter_from_directives
33
37
  AIA.config.directives.each do |entry|
34
38
  directive, value = entry
@@ -38,6 +42,7 @@ module AIA::BackendCommon
38
42
  end
39
43
  end
40
44
 
45
+
41
46
  def run
42
47
  case @files.size
43
48
  when 0
@@ -45,32 +50,9 @@ module AIA::BackendCommon
45
50
  when 1
46
51
  @result = `#{build_command} < #{@files.first}`
47
52
  else
48
- create_temp_file_with_contexts
49
- run_with_temp_file
50
- clean_up_temp_file
53
+ @result = %x[cat #{@files.join(' ')} | #{build_command}]
51
54
  end
52
55
 
53
56
  @result
54
57
  end
55
-
56
- def create_temp_file_with_contexts
57
- @temp_file = Tempfile.new("#{self.class::COMMAND_NAME}-context")
58
-
59
- @files.each do |file|
60
- content = File.read(file)
61
- @temp_file.write(content)
62
- @temp_file.write("\n")
63
- end
64
-
65
- @temp_file.close
66
- end
67
-
68
- def run_with_temp_file
69
- command = "#{build_command} < #{@temp_file.path}"
70
- @result = `#{command}`
71
- end
72
-
73
- def clean_up_temp_file
74
- @temp_file.unlink if @temp_file
75
- end
76
58
  end
@@ -0,0 +1,90 @@
1
+ # aia/lib/aia/tools/glow.rb
2
+
3
+ require 'tempfile'
4
+ require 'tty-screen'
5
+ require 'shellwords'
6
+
7
+
8
+ =begin
9
+
10
+ This class supports two use cases:
11
+ 1) rendering markdown from an existing file
12
+ 2) rendering markdown from a String object via a temporary file
13
+
14
+ In both cases a String object is created and returned that contains the
15
+ rendered version of the content so that it can be written to STDOUT
16
+ by the caller.
17
+
18
+ =end
19
+
20
+ class AIA::Glow < AIA::Tools
21
+
22
+ meta(
23
+ name: 'glow',
24
+ role: :markdown_renderer,
25
+ desc: "A markdown renderer utility",
26
+ url: "https://github.com/charmbracelet/glow",
27
+ install: "brew install glow",
28
+ )
29
+
30
+ DEFAULT_PARAMETERS = "--width #{TTY::Screen.width-2}" # Magic: -2 just because I want it
31
+
32
+ attr_accessor :content, :file_path
33
+
34
+
35
+ def initialize(content: nil, file_path: nil)
36
+ @content = content
37
+ @file_path = file_path
38
+ end
39
+
40
+
41
+ def build_command(file_path)
42
+ "#{self.class.meta[:name]} #{DEFAULT_PARAMETERS} #{Shellwords.escape(file_path)}"
43
+ end
44
+
45
+
46
+ def run
47
+ return unless content || file_path
48
+
49
+ if @file_path && File.exist?(@file_path)
50
+ command = build_command(@file_path)
51
+ system(command)
52
+ else
53
+ Tempfile.create(['glow', '.md']) do |file|
54
+ file.write(@content)
55
+ file.close
56
+ command = build_command(file.path)
57
+ system(command)
58
+ end
59
+ end
60
+ end
61
+ end
62
+
63
+ __END__
64
+
65
+ $ glow --help
66
+
67
+ Render markdown on the CLI, with pizzazz!
68
+
69
+ Usage:
70
+ glow [SOURCE|DIR] [flags]
71
+ glow [command]
72
+
73
+ Available Commands:
74
+ completion Generate the autocompletion script for the specified shell
75
+ config Edit the glow config file
76
+ help Help about any command
77
+ stash Stash a markdown
78
+
79
+ Flags:
80
+ -a, --all show system files and directories (TUI-mode only)
81
+ --config string config file (default /Users/dewayne/Library/Preferences/glow/glow.yml)
82
+ -h, --help help for glow
83
+ -l, --local show local files only; no network (TUI-mode only)
84
+ -p, --pager display with pager
85
+ -s, --style string style name or JSON path (default "auto")
86
+ -v, --version version for glow
87
+ -w, --width uint word-wrap at width
88
+
89
+ Use "glow [command] --help" for more information about a command.
90
+
data/man/aia.1 CHANGED
@@ -23,7 +23,7 @@ External options are optional\. Anything that follow \[lq] \-\- \[lq] will be s
23
23
  .SH OPTIONS
24
24
  .TP
25
25
  \fB\-\-chat\fR
26
- begin a chat session with the backend after the initial prompt response; will set \-\-no\-out\[ru]file so that the backend response comes to STDOUT\.
26
+ begin a chat session with the backend after the initial prompt response; will set \-\-no\-out\[ru]file so that the backend response comes to STDOUT\. After the initial prompt is processed, you will be asked to provide a follow up\. Just enter whatever is appropriate terminating your input with a RETURN\. The backend will provide a response to you follow up and ask you again if you have another follow up\. This back and forth chatting will continue until you enter a RETURN without any other content \- an empty follow up prompt\. You may also enter a directive to be processed after which another follow up is requested\. If you have the \fB\-\-shell\fR and\[sl]or the \fB\-\-erb\fR options set you may use those tools within your follow up to provide dynamic content\.
27
27
  .TP
28
28
  \fB\-\-completion\fR \fISHELL\[ru]NAME\fP
29
29
  .TP
@@ -41,6 +41,9 @@ If dynamic prompt content using \[Do](\.\.\.) wasn\[cq]t enough here is ERB\. E
41
41
  \fB\-\-model\fR \fINAME\fP
42
42
  Name of the LLM model to use \- default is gpt\-4\-1106\-preview
43
43
  .TP
44
+ \fB\-\-render\fR
45
+ Render markdown to the terminal using the external tool \[lq]glow\[rq] \- default: false
46
+ .TP
44
47
  \fB\-\-speak\fR
45
48
  Simple implementation\. Uses the \[lq]say\[rq] command to speak the response\. Fun with \-\-chat
46
49
  .TP
@@ -147,6 +150,21 @@ sgpt
147
150
  .UR https:\[sl]\[sl]github\.com\[sl]tbckr\[sl]sgpt
148
151
  .UE
149
152
  (aka shell\-gpt) is a powerful command\-line interface (CLI) tool designed for seamless interaction with OpenAI models directly from your terminal\. Effortlessly run queries, generate shell commands or code, create images from text, and more, using simple commands\. Streamline your workflow and enhance productivity with this powerful and user\-friendly CLI tool\.
153
+ .IP \(bu 2
154
+ fzf
155
+ .UR https:\[sl]\[sl]github\.com\[sl]junegunn\[sl]fzf
156
+ .UE
157
+ fzf is a general\-purpose command\-line fuzzy finder\. It\[cq]s an interactive Unix filter for command\-line that can be used with any list; files, command history, processes, hostnames, bookmarks, git commits, etc\.
158
+ .IP \(bu 2
159
+ ripgrep
160
+ .UR https:\[sl]\[sl]github\.com\[sl]BurntSushi\[sl]ripgrep
161
+ .UE
162
+ Search tool like grep and The Silver Searcher\. It is a line\-oriented search tool that recursively searches a directory tree for a regex pattern\. By default, ripgrep will respect gitignore rules and automatically skip hidden files\[sl]directories and binary files\. (To disable all automatic filtering by default, use rg \-uuu\.) ripgrep has first class support on Windows, macOS and Linux, with binary downloads available for every release\.
163
+ .IP \(bu 2
164
+ glow
165
+ .UR https:\[sl]\[sl]github\.com\[sl]charmbracelet\[sl]glow
166
+ .UE
167
+ Render markdown on the CLI
150
168
  .RE
151
169
  .SH AUTHOR
152
170
  .PP
data/man/aia.1.md CHANGED
@@ -26,7 +26,7 @@ The aia command-line tool is an interface for interacting with an AI model backe
26
26
  ## OPTIONS
27
27
 
28
28
  `--chat`
29
- : begin a chat session with the backend after the initial prompt response; will set --no-out_file so that the backend response comes to STDOUT.
29
+ : begin a chat session with the backend after the initial prompt response; will set --no-out_file so that the backend response comes to STDOUT. After the initial prompt is processed, you will be asked to provide a follow up. Just enter whatever is appropriate terminating your input with a RETURN. The backend will provide a response to you follow up and ask you again if you have another follow up. This back and forth chatting will continue until you enter a RETURN without any other content - an empty follow up prompt. You may also enter a directive to be processed after which another follow up is requested. If you have the `--shell` and/or the `--erb` options set you may use those tools within your follow up to provide dynamic content.
30
30
 
31
31
  `--completion` *SHELL_NAME*
32
32
  : Show completion script for bash|zsh|fish - default is nil
@@ -46,6 +46,9 @@ The aia command-line tool is an interface for interacting with an AI model backe
46
46
  `--model` *NAME*
47
47
  : Name of the LLM model to use - default is gpt-4-1106-preview
48
48
 
49
+ `--render`
50
+ : Render markdown to the terminal using the external tool "glow" - default: false
51
+
49
52
  `--speak`
50
53
  : Simple implementation. Uses the "say" command to speak the response. Fun with --chat
51
54
 
@@ -135,6 +138,13 @@ Detail discussion on individual prompt directives is TBD. Most likely it will b
135
138
 
136
139
  - [sgpt](https://github.com/tbckr/sgpt) (aka shell-gpt) is a powerful command-line interface (CLI) tool designed for seamless interaction with OpenAI models directly from your terminal. Effortlessly run queries, generate shell commands or code, create images from text, and more, using simple commands. Streamline your workflow and enhance productivity with this powerful and user-friendly CLI tool.
137
140
 
141
+ - [fzf](https://github.com/junegunn/fzf) fzf is a general-purpose command-line fuzzy finder. It's an interactive Unix filter for command-line that can be used with any list; files, command history, processes, hostnames, bookmarks, git commits, etc.
142
+
143
+ - [ripgrep](https://github.com/BurntSushi/ripgrep) Search tool like grep and The Silver Searcher. It is a line-oriented search tool that recursively searches a directory tree for a regex pattern. By default, ripgrep will respect gitignore rules and automatically skip hidden files/directories and binary files. (To disable all automatic filtering by default, use rg -uuu.) ripgrep has first class support on Windows, macOS and Linux, with binary downloads available for every release.
144
+
145
+ - [glow](https://github.com/charmbracelet/glow) Render markdown on the CLI
146
+
147
+
138
148
  ## AUTHOR
139
149
 
140
150
  Dewayne VanHoozer <dvanhoozer@gmail.com>
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: aia
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.2
4
+ version: 0.5.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dewayne VanHoozer
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-01-13 00:00:00.000000000 Z
11
+ date: 2024-01-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: hashie
@@ -94,6 +94,34 @@ dependencies:
94
94
  - - ">="
95
95
  - !ruby/object:Gem::Version
96
96
  version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: tty-screen
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: tty-spinner
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
97
125
  - !ruby/object:Gem::Dependency
98
126
  name: minitest
99
127
  requirement: !ruby/object:Gem::Requirement
@@ -164,12 +192,18 @@ dependencies:
164
192
  - - ">="
165
193
  - !ruby/object:Gem::Version
166
194
  version: '0'
167
- description: "A command-line AI Assistante (aia) that provides\nparameterized prompt
168
- management (via the prompt_manager gem) to\nvarious backend gen-AI processes. aia
169
- currently supports the \"mods\"\nCLI tool. aia uses \"ripgrep\" and \"fzf\" CLI
170
- utilities \nto search for and select prompt files to send to the backend gen-AI\ntool
171
- along with supported context files. Example usage: \"aia refactor my_class.rb\"
172
- \nwhere \"refactor\" is the prompt ID for the file \"refactor.txt\" from your\nRPROMPTS_DIR\n"
195
+ description: |
196
+ `aia` - the AI Assistant - is a command-line (CLI) tool for
197
+ interfacing with generative AI (gen-AI/GPT) backends. Its designed
198
+ to provide developers with the ability to issue prompts, receive
199
+ AI-generated responses, and incorporate additional context from files
200
+ such as Ruby source code. It supports configuration and customization
201
+ for different environments, includes options for output formats like
202
+ markdown rendering or spoken responses, and allows dynamic content
203
+ generation within prompts such as shell integration and embedded
204
+ Ruby. With `aia`, users benefit from a simplified setup process and
205
+ an extendable interaction model with AI, suitable for a range of
206
+ command-line tasks.
173
207
  email:
174
208
  - dvanhoozer@gmail.com
175
209
  executables:
@@ -195,12 +229,14 @@ files:
195
229
  - lib/aia/cli.rb
196
230
  - lib/aia/config.rb
197
231
  - lib/aia/directives.rb
232
+ - lib/aia/dynamic_content.rb
198
233
  - lib/aia/logging.rb
199
234
  - lib/aia/main.rb
200
235
  - lib/aia/prompt.rb
201
236
  - lib/aia/tools.rb
202
237
  - lib/aia/tools/backend_common.rb
203
238
  - lib/aia/tools/editor.rb
239
+ - lib/aia/tools/glow.rb
204
240
  - lib/aia/tools/mods.rb
205
241
  - lib/aia/tools/sgpt.rb
206
242
  - lib/aia/tools/subl.rb