aia 0.9.6 → 0.9.7

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 02a36ff149a0fa6eb782735e963ca860260c10b43133b56ebe49adda5074c86d
4
- data.tar.gz: 588411eb80ac91a88fc8dd456595610f9bfb71947201629ec1d5b64f5a1cf2d6
3
+ metadata.gz: 21134c8c9fa3664309baf0c3d1bce2857dffd3dd1ad8c554c7cb15ac48b57634
4
+ data.tar.gz: 46f64bdbefe73eede9add530bad3a4957f6b7033706a1d1daf5aa6bef1fb6084
5
5
  SHA512:
6
- metadata.gz: 59eb282bad1dd8e450ec98608e8f4b295ce6c9b0084d2aef7772df4834d5beecddd7fd785a46db1a47e72cf6f90c8d1b15dbd2843a8d2be737d6bf6f47911002
7
- data.tar.gz: 4483f697b88266a73187b2483bae32ac6b82a4fc432bc3e494f35c5d3c63c4395949a95a8282a3a18f475bb9cbdacaf7253069817fc54c3d3927ae4a66a401bf
6
+ metadata.gz: dc1273757619b1962986e1dfac94b8d10b2c493ff0cf0d01d0938c65a902700d96484d42e661770328a4f6f904a1265f6a136964fb8c31218ed22135fed806dc
7
+ data.tar.gz: edc7124424b74f7d167a78635abd7302eb05cd4208058947dd8700e5e05c1200eba47346d1f0beea0ed9ea37a5875ca7cb585d40752dbcf88c64063dc278e398
data/.version CHANGED
@@ -1 +1 @@
1
- 0.9.6
1
+ 0.9.7
data/CHANGELOG.md CHANGED
@@ -1,7 +1,21 @@
1
1
  # Changelog
2
2
  ## [Unreleased]
3
+
4
+ ### [0.9.8] WIP
5
+
3
6
  ## Released
4
7
 
8
+ ### [0.9.7] 2025-06-20
9
+
10
+ - **NEW FEATURE**: Added `--available_models` CLI option to list all available AI models
11
+ - **NEW FEATURE**: Added `//tools` to show a list of available tools and their description
12
+ - **BUG FIX**: Fixed SharedTools compatibility issue with models that don't support function calling
13
+ - **BUG FIX**: Fixed problem with piped text through STDIN not being handled correctly.
14
+ - **BUG FIX**: Fixed issue with output going to the default out_file evenhen --no-out_file is specified.
15
+ - **BUG FIX**: Fixed issue with executable prompt files by adding the --exec option
16
+ - **DOCUMENTATION**: Updated README for better clarity and structure
17
+ - **DEPENDENCY**: Updated Gemfile.lock with latest dependency versions
18
+
5
19
  ### [0.9.6] 2025-06-13
6
20
  - fixed issue 84 with the //llms directive
7
21
  - changed the monkey patch to the RubyLLM::Model::Modalities class at the suggestions of the RubyLLM author in prep for a PR against that gem.
data/README.md CHANGED
@@ -6,7 +6,7 @@
6
6
 
7
7
  AIA is a command-line utility that facilitates interaction with AI models through dynamic prompt management. It automates the management of pre-compositional prompts and executes generative AI commands with enhanced features including embedded directives, shell integration, embedded Ruby, history management, interactive chat, and prompt workflows.
8
8
 
9
- AIA leverages the [prompt_manager gem](https://github.com/madbomber/prompt_manager) to manage prompts, utilizes the [CLI tool fzf](https://github.com/junegunn/fzf) for prompt selection, and includes the [shared_tools gem](https://github.com/madbomber/shared_tools) which provides a collection of ready-to-use functions for use with LLMs that support tools.
9
+ AIA leverages the [prompt_manager gem](https://github.com/madbomber/prompt_manager) to manage prompts, utilizes the [CLI tool fzf](https://github.com/junegunn/fzf) for prompt selection, and can use the [shared_tools gem](https://github.com/madbomber/shared_tools) which provides a collection of common ready-to-use functions for use with LLMs that support tools.
10
10
 
11
11
  **Wiki**: [Checkout the AIA Wiki](https://github.com/MadBomber/aia/wiki)
12
12
 
@@ -25,12 +25,12 @@ AIA leverages the [prompt_manager gem](https://github.com/madbomber/prompt_manag
25
25
  3. **Create your first prompt:**
26
26
  ```bash
27
27
  mkdir -p ~/.prompts
28
- echo "What is [TOPIC]?" > ~/.prompts/ask.txt
28
+ echo "What is [TOPIC]?" > ~/.prompts/what_is.txt
29
29
  ```
30
30
 
31
31
  4. **Run your prompt:**
32
32
  ```bash
33
- aia ask
33
+ aia what_is
34
34
  ```
35
35
  You'll be prompted to enter a value for `[TOPIC]`, then AIA will send your question to the AI model.
36
36
 
@@ -40,43 +40,76 @@ AIA leverages the [prompt_manager gem](https://github.com/madbomber/prompt_manag
40
40
  ```
41
41
 
42
42
  ```plain
43
- , ,
44
- (\____/) AI Assistant
45
- (_oo_) Fancy LLM
46
- (O) is Online
47
- __||__ \)
48
- [/______\] /
49
- / \__AI__/ \/
50
- / /__\
51
- (\ /____\
43
+
44
+ , ,
45
+ (\____/) AI Assistant (v0.9.7) is Online
46
+ (_oo_) gpt-4o-mini
47
+ (O) using ruby_llm (v1.3.1)
48
+ __||__ \) model db was last refreshed on
49
+ [/______\] / 2025-06-18
50
+ / \__AI__/ \/ You can share my tools
51
+ / /__\
52
+ (\ /____\
53
+
52
54
  ```
53
55
 
54
56
  <!-- Tocer[start]: Auto-generated, don't remove. -->
55
57
 
56
58
  ## Table of Contents
57
59
 
58
- - [Quick Start](#quick-start)
59
60
  - [Installation & Prerequisites](#installation--prerequisites)
61
+ - [Requirements](#requirements)
62
+ - [Installation](#installation)
63
+ - [Setup Shell Completion](#setup-shell-completion)
60
64
  - [Basic Usage](#basic-usage)
65
+ - [Command Line Interface](#command-line-interface)
66
+ - [Key Command-Line Options](#key-command-line-options)
67
+ - [Directory Structure](#directory-structure)
61
68
  - [Configuration](#configuration)
62
69
  - [Essential Configuration Options](#essential-configuration-options)
63
70
  - [Configuration Precedence](#configuration-precedence)
71
+ - [Configuration Methods](#configuration-methods)
64
72
  - [Complete Configuration Reference](#complete-configuration-reference)
65
73
  - [Advanced Features](#advanced-features)
66
74
  - [Prompt Directives](#prompt-directives)
75
+ - [Configuration Directive Examples](#configuration-directive-examples)
76
+ - [Dynamic Content Examples](#dynamic-content-examples)
67
77
  - [Shell Integration](#shell-integration)
68
78
  - [Embedded Ruby (ERB)](#embedded-ruby-erb)
69
79
  - [Prompt Sequences](#prompt-sequences)
80
+ - [Using --next](#using---next)
81
+ - [Using --pipeline](#using---pipeline)
82
+ - [Example Workflow](#example-workflow)
70
83
  - [Roles and System Prompts](#roles-and-system-prompts)
71
84
  - [RubyLLM::Tool Support](#rubyllmtool-support)
72
85
  - [Examples & Tips](#examples--tips)
73
86
  - [Practical Examples](#practical-examples)
87
+ - [Code Review Prompt](#code-review-prompt)
88
+ - [Meeting Notes Processor](#meeting-notes-processor)
89
+ - [Documentation Generator](#documentation-generator)
74
90
  - [Executable Prompts](#executable-prompts)
75
91
  - [Tips from the Author](#tips-from-the-author)
92
+ - [The run Prompt](#the-run-prompt)
93
+ - [The Ad Hoc One-shot Prompt](#the-ad-hoc-one-shot-prompt)
94
+ - [Recommended Shell Setup](#recommended-shell-setup)
95
+ - [Prompt Directory Organization](#prompt-directory-organization)
76
96
  - [Security Considerations](#security-considerations)
97
+ - [Shell Command Execution](#shell-command-execution)
98
+ - [Safe Practices](#safe-practices)
99
+ - [Recommended Security Setup](#recommended-security-setup)
77
100
  - [Troubleshooting](#troubleshooting)
101
+ - [Common Issues](#common-issues)
102
+ - [Error Messages](#error-messages)
103
+ - [Debug Mode](#debug-mode)
104
+ - [Performance Issues](#performance-issues)
78
105
  - [Development](#development)
106
+ - [Testing](#testing)
107
+ - [Building](#building)
108
+ - [Architecture Notes](#architecture-notes)
79
109
  - [Contributing](#contributing)
110
+ - [Reporting Issues](#reporting-issues)
111
+ - [Development Setup](#development-setup)
112
+ - [Areas for Improvement](#areas-for-improvement)
80
113
  - [Roadmap](#roadmap)
81
114
  - [License](#license)
82
115
 
@@ -281,16 +314,21 @@ Directives are special commands in prompt files that begin with `//` and provide
281
314
  | Directive | Description | Example |
282
315
  |-----------|-------------|---------|
283
316
  | `//config` | Set configuration values | `//config model = gpt-4` |
317
+ | `//context` | Show context for this conversation | `//context` |
284
318
  | `//include` | Insert file contents | `//include path/to/file.txt` |
285
319
  | `//shell` | Execute shell commands | `//shell ls -la` |
320
+ | `//robot` | Show the pet robot ASCII art w/versions | `//robot` |
286
321
  | `//ruby` | Execute Ruby code | `//ruby puts "Hello World"` |
287
322
  | `//next` | Set next prompt in sequence | `//next summary` |
288
323
  | `//pipeline` | Set prompt workflow | `//pipeline analyze,summarize,report` |
289
324
  | `//clear` | Clear conversation history | `//clear` |
290
325
  | `//help` | Show available directives | `//help` |
291
326
  | `//available_models` | List available models | `//available_models` |
327
+ | `//tools` | Show a list of available tools and their description | `//tools` |
292
328
  | `//review` | Review current context | `//review` |
293
329
 
330
+ Directives can also be used in the interactive chat sessions.
331
+
294
332
  #### Configuration Directive Examples
295
333
 
296
334
  ```bash
@@ -462,22 +500,20 @@ aia --tools ~/tools/ --rejected_tools deprecated
462
500
  - Data processing utilities
463
501
 
464
502
  **Shared Tools Collection:**
465
- AIA includes the [shared_tools gem](https://github.com/madbomber/shared_tools) which provides a curated collection of commonly-used RubyLLM::Tool implementations:
503
+ AIA can use the [shared_tools gem](https://github.com/madbomber/shared_tools) which provides a curated collection of commonly-used tools (aka functions) via the --require option.
466
504
 
467
505
  ```bash
468
506
  # Access shared tools automatically (included with AIA)
469
- aia --tools shared --chat
507
+ aia --require shared_tools/ruby_llm --chat
470
508
 
471
- # Combine with custom tools
472
- aia --tools shared,~/my-tools/ --chat
509
+ # To access just one specific shared tool
510
+ aia --require shared_tools/ruby_llm/edit_file --chat
511
+
512
+ # Combine with your own local custom RubyLLM-based tools
513
+ aia --require shared_tools/ruby_llm --tools ~/my-tools/ --chat
473
514
  ```
474
515
 
475
- Available shared tools include:
476
- - **File operations**: read, write, edit, search files
477
- - **Web utilities**: fetch web pages, parse HTML/JSON
478
- - **System tools**: execute commands, get system info
479
- - **Data processing**: CSV/JSON manipulation, text analysis
480
- - **API helpers**: HTTP requests, common API patterns
516
+ The above examples show the shared_tools being used within an interactive chat session. They are also available in batch prompts as well using the same --require option. You can also use the //ruby directive to require the shared_tools as well and using a require statement within an ERB block.
481
517
 
482
518
  ## Examples & Tips
483
519
 
@@ -486,7 +522,7 @@ Available shared tools include:
486
522
  #### Code Review Prompt
487
523
  ```bash
488
524
  # ~/.prompts/code_review.txt
489
- //config model = gpt-4
525
+ //config model = gpt-4o-mini
490
526
  //config temperature = 0.3
491
527
 
492
528
  Review this code for:
@@ -496,7 +532,6 @@ Review this code for:
496
532
  - Maintainability concerns
497
533
 
498
534
  Code to review:
499
- //include [CODE_FILE]
500
535
  ```
501
536
 
502
537
  Usage: `aia code_review mycode.rb`
@@ -516,7 +551,7 @@ Please clean up and structure these meeting notes.
516
551
  #### Documentation Generator
517
552
  ```bash
518
553
  # ~/.prompts/document.txt
519
- //config model = gpt-4
554
+ //config model = gpt-4o-mini
520
555
  //shell find [PROJECT_DIR] -name "*.rb" | head -10
521
556
 
522
557
  Generate documentation for the Ruby project shown above.
@@ -525,48 +560,62 @@ Include: API references, usage examples, and setup instructions.
525
560
 
526
561
  ### Executable Prompts
527
562
 
528
- Create reusable executable prompts:
563
+ The `--exec` flag is used to create executable prompts. If it is not present on the shebang line then the prompt file will be treated like any other context file. That means that the file will be included as context in the prompt but no dynamic content integration or directives will be processed. All other AIA options are, well, optional. All you need is an initial prompt ID and the --exec flag.
564
+
565
+ In the example below the option `--no-out_file` is used to direct the output from the LLM processing of the prompt to STDOUT. This way the executable prompts can be good citizens on the *nix command line receiving piped in input via STDIN and send its output to STDOUT.
566
+
567
+ Create executable prompts:
529
568
 
530
569
  **weather_report** (make executable with `chmod +x`):
531
570
  ```bash
532
- #!/usr/bin/env aia run --no-out_file
533
- # Get current weather for a city
571
+ #!/usr/bin/env aia run --no-out_file --exec
572
+ # Get current storm activity for the east and south coast of the US
573
+
574
+ Summarize the tropical storm outlook fpr the Atlantic, Caribbean Sea and Gulf of America.
534
575
 
535
- What's the current weather in [CITY]?
536
- Include temperature, conditions, and 3-day forecast.
537
- Format as a brief, readable summary.
576
+ //webpage https://www.nhc.noaa.gov/text/refresh/MIATWOAT+shtml/201724_MIATWOAT.shtml
538
577
  ```
539
578
 
540
579
  Usage:
541
580
  ```bash
542
581
  ./weather_report
543
- # Prompts for city, outputs to stdout
544
-
545
- ./weather_report | glow # Render with glow
582
+ ./weather_report | glow # Render the markdown with glow
546
583
  ```
547
584
 
548
585
  ### Tips from the Author
549
586
 
550
- **Most Versatile Prompt:**
587
+ #### The run Prompt
588
+ ```bash
589
+ # ~/.prompts/run.txt
590
+ # Desc: A configuration only prompt file for use with executable prompts
591
+ # Put whatever you want here to setup the configuration desired.
592
+ # You could also add a system prompt to preface your intended prompt
593
+ ```
594
+
595
+ Usage: `echo "What is the meaning of life?" | aia run`
596
+
597
+ #### The Ad Hoc One-shot Prompt
551
598
  ```bash
552
599
  # ~/.prompts/ad_hoc.txt
553
600
  [WHAT_NOW_HUMAN]
554
601
  ```
555
- Usage: `aia ad_hoc` - perfect for any quick question without cluttering shell history.
602
+ Usage: `aia ad_hoc` - perfect for any quick one-shot question without cluttering shell history.
556
603
 
557
- **Recommended Shell Setup:**
604
+ #### Recommended Shell Setup
558
605
  ```bash
559
606
  # ~/.bashrc_aia
560
607
  export AIA_PROMPTS_DIR=~/.prompts
561
608
  export AIA_OUT_FILE=./temp.md
562
609
  export AIA_MODEL=gpt-4o-mini
563
- export AIA_VERBOSE=true # Shows spinner while waiting
610
+ export AIA_VERBOSE=true # Shows spinner while waiting for LLM response
564
611
 
565
612
  alias chat='aia --chat --terse'
566
- alias ask='aia ad_hoc'
613
+ ask() { echo "$1" | aia run --no-out_file; }
567
614
  ```
568
615
 
569
- **Prompt Organization:**
616
+ The `chat` alias and the `ask` function (shown above in HASH) are two powerful tools for interacting with the AI assistant. The `chat` alias allows you to engage in an interactive conversation with the AI assistant, while the `ask` function allows you to ask a question and receive a response. Later in this document the `run` prompt ID is discussed. Besides using the run prompt ID here its also used in making executable prompt files.
617
+
618
+ #### Prompt Directory Organization
570
619
  ```
571
620
  ~/.prompts/
572
621
  ├── daily/ # Daily workflow prompts
@@ -611,10 +660,6 @@ AIA executes shell commands and Ruby code embedded in prompts. This provides pow
611
660
  # Set restrictive permissions on prompts directory
612
661
  chmod 700 ~/.prompts
613
662
  chmod 600 ~/.prompts/*.txt
614
-
615
- # Use separate prompts directory for shared/untrusted prompts
616
- export AIA_PROMPTS_DIR_SHARED=~/shared-prompts
617
- chmod 755 ~/shared-prompts
618
663
  ```
619
664
 
620
665
  ## Troubleshooting
data/examples/headlines CHANGED
@@ -1,21 +1,30 @@
1
- #!/usr/bin/env aia run --no-out_file
2
- # File: examples/headlines
1
+ #!/usr/bin/env aia run --no-out_file --exec
2
+ # NOTE: the --exec option is REQUIRED to run this executable prompt file
3
+ # This option signals that the contents of this file are to be appended
4
+ # to the contents of the given prompt ID file. In this case it is the
5
+ # "run" prompt ID's text file.
6
+ #
7
+ # All other AIA options are, well, optional. The --no-out_file is
8
+ # used here to cause the response to this executable prompt to be
9
+ # sent to STDOUT like a good little *nix CLI tool. Its not necessary.
10
+ # if you do not use it, the output will go to the default out_file.
11
+ # You could also specify a specific file to write the output to built
12
+ # but it is more convential to use the *nix STDOUT redirect "> output.md"
13
+ #
3
14
  # Desc: retrieves the news.google.com website
4
15
  # extracts and formats the headlines
5
- # and prints them to the console
16
+ # and prints them to STDOUT
17
+ #
18
+ # Method:
19
+ # There are several ways you can accomplish this task using
20
+ # the shell or ERB integration. For this example lets use
21
+ # a built-in directive.
6
22
 
7
- //config shell = true
8
- # //config
23
+ Extract and summarize the headlines from the following markdown:
9
24
 
10
- # Puts the webpage into index.html
11
- # //shell wget2 https://news.google.com
25
+ //webpage https://news.google.com
12
26
 
13
- $(wget2 https://news.google.com)
27
+ __END__
14
28
 
15
-
16
- # Lets hear the headlines as well as read them.
17
- //config speak = true
18
-
19
- Extract and summarize the headlines from the following text:
20
-
21
- $(html2text index.html)
29
+ The //webpage directive makes use of the website https://pure.md
30
+ to convert any given URL to a markdown file.
@@ -1,5 +1,6 @@
1
1
  # experiments/ai_misc/coding_agent_with_ruby_llm/tools/run_shell_command.rb
2
2
 
3
+ require "io/console"
3
4
  require "ruby_llm/tool"
4
5
 
5
6
  module Tools
@@ -8,10 +9,21 @@ module Tools
8
9
  param :command, desc: "The command to execute"
9
10
 
10
11
  def execute(command:)
11
- puts "AI wants to execute the following shell command: '#{command}'"
12
- print "Do you want to execute it? (y/n) "
13
- response = gets.chomp
14
- return { error: "User declined to execute the command" } unless response == "y"
12
+ print "\n\n"
13
+ puts "AI wants to execute the following shell command:"
14
+ puts "="*command.size
15
+ puts command
16
+ puts "="*command.size
17
+ print "\n\n"
18
+
19
+ sleep 0.5
20
+ print "Execute the command? (y/N):"
21
+ allowed = STDIN.getch == "y"
22
+
23
+ unless allowed
24
+ print "Command aborted" + " "*30 if defined?(AIA)
25
+ return { error: "User declined to execute the command" }
26
+ end
15
27
 
16
28
  `#{command}`
17
29
  rescue => e
@@ -62,7 +62,7 @@ module AIA
62
62
 
63
63
  # Only output to STDOUT if we're in chat mode
64
64
 
65
- if AIA.chat? || 'STDOUT' == AIA.config.out_file.upcase
65
+ if AIA.chat? || AIA.config.out_file.nil? || 'STDOUT' == AIA.config.out_file.upcase
66
66
  print "\nAI:\n "
67
67
  puts response
68
68
  else
data/lib/aia/config.rb CHANGED
@@ -124,6 +124,17 @@ module AIA
124
124
  remaining_args = config.remaining_args.dup
125
125
  config.remaining_args = nil
126
126
 
127
+ # Check for STDIN content
128
+ stdin_content = nil
129
+ if !STDIN.tty? && !STDIN.closed?
130
+ begin
131
+ stdin_content = STDIN.read
132
+ STDIN.reopen('/dev/tty') # Reopen STDIN for interactive use
133
+ rescue => _
134
+ # If we can't reopen, continue without error
135
+ end
136
+ end
137
+
127
138
  # Is first remaining argument a prompt ID?
128
139
  unless remaining_args.empty?
129
140
  maybe_id = remaining_args.first
@@ -134,6 +145,11 @@ module AIA
134
145
  end
135
146
  end
136
147
 
148
+ # Store STDIN content for later processing in session.rb
149
+ if stdin_content && !stdin_content.strip.empty?
150
+ config.stdin_content = stdin_content
151
+ end
152
+
137
153
  unless remaining_args.empty?
138
154
  bad_files = remaining_args.reject { |filename| AIA.good_file?(filename) }
139
155
  if bad_files.any?
@@ -141,9 +157,21 @@ module AIA
141
157
  exit 1
142
158
  end
143
159
 
144
- config.context_files = remaining_args
160
+ config.context_files ||= []
161
+ config.context_files += remaining_args
162
+ end
163
+
164
+ # Check if the last context file is an executable prompt
165
+ if config.executable_prompt &&
166
+ config.context_files &&
167
+ !config.context_files.empty?
168
+ config.executable_prompt_file = config.context_files.pop
145
169
  end
146
170
 
171
+ # TODO: Consider that if there is no prompt ID but there is an executable prompt
172
+ # then maybe that is all that is needed.
173
+
174
+
147
175
  if config.prompt_id.nil? && !config.chat && !config.fuzzy
148
176
  STDERR.puts "Error: A prompt ID is required unless using --chat, --fuzzy, or providing context files. Use -h or --help for help."
149
177
  exit 1
@@ -325,10 +353,68 @@ module AIA
325
353
  end
326
354
  end
327
355
 
356
+ opts.on('--available_models [QUERY]', 'List (then exit) available models that match the optional query - a comma separated list of AND components like: openai,mini') do |query|
357
+
358
+ # SMELL: mostly duplications the code in the vailable_models directive
359
+ # assumes that the adapter is for the ruby_llm gem
360
+ # should this be moved to the Utilities class as a common method?
361
+
362
+ if query.nil?
363
+ query = []
364
+ else
365
+ query = query.split(',')
366
+ end
367
+
368
+ header = "\nAvailable LLMs"
369
+ header += " for #{query.join(' and ')}" if query
370
+
371
+ puts header + ':'
372
+ puts
373
+
374
+ q1 = query.select{|q| q.include?('_to_')}.map{|q| ':'==q[0] ? q[1...] : q}
375
+ q2 = query.reject{|q| q.include?('_to_')}
376
+
377
+
378
+ # query = nil
379
+ counter = 0
380
+
381
+ RubyLLM.models.all.each do |llm|
382
+ inputs = llm.modalities.input.join(',')
383
+ outputs = llm.modalities.output.join(',')
384
+ entry = "- #{llm.id} (#{llm.provider}) #{inputs} to #{outputs}"
385
+
386
+ if query.nil? || query.empty?
387
+ counter += 1
388
+ puts entry
389
+ next
390
+ end
391
+
392
+ show_it = true
393
+ q1.each{|q| show_it &&= llm.modalities.send("#{q}?")}
394
+ q2.each{|q| show_it &&= entry.include?(q)}
395
+
396
+ if show_it
397
+ counter += 1
398
+ puts entry
399
+ end
400
+ end
401
+
402
+ puts if counter > 0
403
+ puts "#{counter} LLMs matching your query"
404
+ puts
405
+
406
+ exit
407
+ end
408
+
328
409
  opts.on("-m MODEL", "--model MODEL", "Name of the LLM model to use") do |model|
329
410
  config.model = model
330
411
  end
331
412
 
413
+ opts.on("-x", "--[no-]exec", "Used to designate an executable prompt file") do |value|
414
+ config.executable_prompt = value
415
+ end
416
+
417
+
332
418
  opts.on("--terse", "Adds a special instruction to the prompt asking the AI to keep responses short and to the point") do
333
419
  config.terse = true
334
420
  end
@@ -383,7 +469,13 @@ module AIA
383
469
  end
384
470
 
385
471
  opts.on("-o", "--[no-]out_file [FILE]", "Output file (default: temp.md)") do |file|
386
- config.out_file = file ? File.expand_path(file, Dir.pwd) : 'temp.md'
472
+ if file == false # --no-out_file was used
473
+ config.out_file = nil
474
+ elsif file.nil? # No argument provided
475
+ config.out_file = 'temp.md'
476
+ else # File name provided
477
+ config.out_file = File.expand_path(file, Dir.pwd)
478
+ end
387
479
  end
388
480
 
389
481
  opts.on("-a", "--[no-]append", "Append to output file instead of overwriting") do |append|
@@ -422,8 +514,8 @@ module AIA
422
514
  config.debug = $DEBUG_ME = false
423
515
  end
424
516
 
425
- opts.on("-v", "--verbose", "Be verbose") do
426
- config.verbose = true
517
+ opts.on("-v", "--[no-]verbose", "Be verbose") do |value|
518
+ config.verbose = value
427
519
  end
428
520
 
429
521
  opts.on("--speak", "Simple implementation. Uses the speech model to convert text to audio, then plays the audio. Fun with --chat. Supports configuration of speech model and voice.") do
@@ -1,6 +1,8 @@
1
1
  # lib/aia/directive_processor.rb
2
2
 
3
+ require 'active_support/all'
3
4
  require 'faraday'
5
+ require 'word_wrapper' # Pure ruby word wrapping
4
6
 
5
7
  module AIA
6
8
  class DirectiveProcessor
@@ -145,7 +147,7 @@ module AIA
145
147
  end
146
148
 
147
149
  desc "Specify the next prompt ID to process after this one"
148
- def next(args = [])
150
+ def next(args = [], context_manager=nil)
149
151
  if args.empty?
150
152
  ap AIA.config.next
151
153
  else
@@ -154,8 +156,33 @@ module AIA
154
156
  ''
155
157
  end
156
158
 
159
+ desc "Show a list of tools and their description"
160
+ def tools(args = [], context_manager=nil)
161
+ indent = 4
162
+ spaces = " "*indent
163
+ width = TTY::Screen.width - indent - 2
164
+
165
+ if !AIA.config.tools.empty?
166
+ puts
167
+ puts "Available Tools"
168
+ puts "==============="
169
+
170
+ AIA.config.tools.split(',').map(&:strip).each do |tool|
171
+ klass = tool.constantize
172
+ puts "\n#{klass.name}"
173
+ puts "-"*klass.name.size
174
+ puts WordWrapper::MinimumRaggedness.new(width, klass.description).wrap.split("\n").map{|s| spaces+s+"\n"}.join
175
+ end
176
+ else
177
+ puts "No tools configured"
178
+ end
179
+ puts
180
+
181
+ ''
182
+ end
183
+
157
184
  desc "Specify a sequence pf prompt IDs to process after this one"
158
- def pipeline(args = [])
185
+ def pipeline(args = [], context_manager=nil)
159
186
  if args.empty?
160
187
  ap AIA.config.pipeline
161
188
  else
@@ -299,6 +326,11 @@ module AIA
299
326
  desc "All Available models or query on [partial LLM or provider name] Examples: //llms ; //llms openai ; //llms claude"
300
327
  def available_models( args=nil, context_manager=nil)
301
328
  query = args
329
+
330
+ if 1 == query.size
331
+ query = query.first.split(',')
332
+ end
333
+
302
334
  header = "\nAvailable LLMs"
303
335
  header += " for #{query.join(' and ')}" if query
304
336
 
@@ -74,6 +74,8 @@ module AIA
74
74
  exit 1
75
75
  end
76
76
 
77
+ return unless @chat.model.supports_functions?
78
+
77
79
  if !AIA.config.tool_paths.empty? && !@chat.model.supports?(:function_calling)
78
80
  STDERR.puts "ERROR: The model #{@model} does not support tools"
79
81
  exit 1
data/lib/aia/session.rb CHANGED
@@ -41,7 +41,7 @@ module AIA
41
41
  @directive_processor = DirectiveProcessor.new
42
42
  @chat_processor = ChatProcessorService.new(@ui_presenter, @directive_processor)
43
43
 
44
- if AIA.config.out_file && !AIA.append? && File.exist?(AIA.config.out_file)
44
+ if AIA.config.out_file && !AIA.config.out_file.nil? && !AIA.append? && File.exist?(AIA.config.out_file)
45
45
  File.open(AIA.config.out_file, 'w') {} # Truncate the file
46
46
  end
47
47
  end
@@ -111,8 +111,17 @@ module AIA
111
111
  prompt.text << TERSE_PROMPT
112
112
  end
113
113
 
114
- prompt.save
115
- # Substitute variables and get final prompt text
114
+ if AIA.config.stdin_content && !AIA.config.stdin_content.strip.empty?
115
+ prompt.text << "\n\n" << AIA.config.stdin_content
116
+ end
117
+
118
+ if AIA.config.executable_prompt_file
119
+ prompt.text << "\n\n" << File.read(AIA.config.executable_prompt_file)
120
+ .lines[1..]
121
+ .join
122
+ end
123
+
124
+ # Substitute variables, execute dynamic content and get final prompt text
116
125
  prompt_text = prompt.to_s
117
126
 
118
127
  # Add context files if any
@@ -26,7 +26,7 @@ module AIA
26
26
  puts "\nAI: "
27
27
  format_chat_response(response)
28
28
 
29
- if AIA.config.out_file
29
+ if AIA.config.out_file && !AIA.config.out_file.nil?
30
30
  File.open(AIA.config.out_file, 'a') do |file|
31
31
  file.puts "\nAI: "
32
32
  format_chat_response(response, file)
data/lib/aia.rb CHANGED
@@ -6,8 +6,6 @@
6
6
 
7
7
  require 'ruby_llm'
8
8
  require 'ruby_llm/mcp'
9
- require 'shared_tools'
10
- require 'shared_tools/ruby_llm'
11
9
  require 'prompt_manager'
12
10
 
13
11
 
@@ -41,6 +39,10 @@ require_relative 'aia/session'
41
39
  module AIA
42
40
  at_exit do
43
41
  STDERR.puts "Exiting AIA application..."
42
+ # Clean up temporary STDIN file if it exists
43
+ if @config&.stdin_temp_file && File.exist?(@config.stdin_temp_file)
44
+ File.unlink(@config.stdin_temp_file)
45
+ end
44
46
  end
45
47
 
46
48
  @config = nil
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.6
4
+ version: 0.9.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dewayne VanHoozer
@@ -10,7 +10,7 @@ cert_chain: []
10
10
  date: 1980-01-02 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
- name: amazing_print
13
+ name: activesupport
14
14
  requirement: !ruby/object:Gem::Requirement
15
15
  requirements:
16
16
  - - ">="
@@ -24,7 +24,7 @@ dependencies:
24
24
  - !ruby/object:Gem::Version
25
25
  version: '0'
26
26
  - !ruby/object:Gem::Dependency
27
- name: faraday
27
+ name: amazing_print
28
28
  requirement: !ruby/object:Gem::Requirement
29
29
  requirements:
30
30
  - - ">="
@@ -38,49 +38,49 @@ dependencies:
38
38
  - !ruby/object:Gem::Version
39
39
  version: '0'
40
40
  - !ruby/object:Gem::Dependency
41
- name: prompt_manager
41
+ name: faraday
42
42
  requirement: !ruby/object:Gem::Requirement
43
43
  requirements:
44
44
  - - ">="
45
45
  - !ruby/object:Gem::Version
46
- version: 0.5.6
46
+ version: '0'
47
47
  type: :runtime
48
48
  prerelease: false
49
49
  version_requirements: !ruby/object:Gem::Requirement
50
50
  requirements:
51
51
  - - ">="
52
52
  - !ruby/object:Gem::Version
53
- version: 0.5.6
53
+ version: '0'
54
54
  - !ruby/object:Gem::Dependency
55
- name: ruby_llm
55
+ name: prompt_manager
56
56
  requirement: !ruby/object:Gem::Requirement
57
57
  requirements:
58
58
  - - ">="
59
59
  - !ruby/object:Gem::Version
60
- version: 1.3.1
60
+ version: 0.5.6
61
61
  type: :runtime
62
62
  prerelease: false
63
63
  version_requirements: !ruby/object:Gem::Requirement
64
64
  requirements:
65
65
  - - ">="
66
66
  - !ruby/object:Gem::Version
67
- version: 1.3.1
67
+ version: 0.5.6
68
68
  - !ruby/object:Gem::Dependency
69
- name: ruby_llm-mcp
69
+ name: ruby_llm
70
70
  requirement: !ruby/object:Gem::Requirement
71
71
  requirements:
72
72
  - - ">="
73
73
  - !ruby/object:Gem::Version
74
- version: '0'
74
+ version: 1.3.1
75
75
  type: :runtime
76
76
  prerelease: false
77
77
  version_requirements: !ruby/object:Gem::Requirement
78
78
  requirements:
79
79
  - - ">="
80
80
  - !ruby/object:Gem::Version
81
- version: '0'
81
+ version: 1.3.1
82
82
  - !ruby/object:Gem::Dependency
83
- name: reline
83
+ name: ruby_llm-mcp
84
84
  requirement: !ruby/object:Gem::Requirement
85
85
  requirements:
86
86
  - - ">="
@@ -94,7 +94,7 @@ dependencies:
94
94
  - !ruby/object:Gem::Version
95
95
  version: '0'
96
96
  - !ruby/object:Gem::Dependency
97
- name: shared_tools
97
+ name: reline
98
98
  requirement: !ruby/object:Gem::Requirement
99
99
  requirements:
100
100
  - - ">="