aia 1.1.0 → 2.0.0.0.pre.alpha
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 +4 -4
- data/.envrc +5 -1
- data/.loki +231 -0
- data/.quality/flay_baseline.txt +1 -0
- data/.quality/flog_baseline.txt +29 -0
- data/.quality/reek_baseline.txt +80 -0
- data/.rubocop.yml +116 -0
- data/.version +1 -1
- data/CHANGELOG.md +266 -42
- data/IMPLEMENTATION_PLAN.md +506 -0
- data/README.md +266 -238
- data/Rakefile +118 -5
- data/architecture_review.md +314 -0
- data/bin/aia +16 -0
- data/docs/AGENTS.md +40 -0
- data/docs/advanced-prompting.md +67 -3
- data/docs/cli-reference.md +312 -56
- data/docs/configuration.md +130 -19
- data/docs/contributing.md +56 -2
- data/docs/directives-reference.md +593 -78
- data/docs/faq.md +85 -3
- data/docs/guides/available-models.md +1 -1
- data/docs/guides/basic-usage.md +6 -6
- data/docs/guides/chat.md +40 -16
- data/docs/guides/crew.md +239 -0
- data/docs/guides/executable-prompts.md +1 -1
- data/docs/guides/index.md +1 -0
- data/docs/guides/models.md +15 -0
- data/docs/index.md +29 -2
- data/docs/installation.md +44 -17
- data/docs/mcp-integration.md +40 -0
- data/docs/prompt_management.md +85 -86
- data/docs/security.md +47 -0
- data/docs/special_projects_guide.md +386 -0
- data/docs/tools-and-mcp-examples.md +23 -0
- data/docs/workflows-and-pipelines.md +84 -7
- data/examples/.gitignore +1 -0
- data/examples/00_setup_aia.sh +27 -44
- data/examples/11_multi_model.sh +4 -14
- data/examples/12_token_usage.sh +3 -12
- data/examples/18_tools.sh +10 -2
- data/examples/22_chat_mode.sh +0 -10
- data/examples/23_verify.sh +139 -0
- data/examples/24_decompose.sh +139 -0
- data/examples/25_spawn.sh +139 -0
- data/examples/26_debate.sh +97 -0
- data/examples/27_mention_routing.sh +157 -0
- data/examples/28_model_switching.sh +106 -0
- data/examples/29_agent_harness.sh +177 -0
- data/examples/README.md +65 -0
- data/examples/advanced_multi_robot_capabilities_without_examples.md +106 -0
- data/examples/aia_config.yml +1 -1
- data/examples/aia_config_orchestrator.yml +45 -0
- data/examples/common.sh +19 -0
- data/examples/context/tech_stack.md +2 -2
- data/examples/prompts_dir/project_summary +2 -2
- data/examples/prompts_dir/roles/orchestrator.md +21 -0
- data/examples/requirements/sinatra_taskflow_app.md +139 -0
- data/examples/rules/01_classify_ruby.rb +16 -0
- data/examples/rules/02_prefer_claude_for_code.rb +19 -0
- data/examples/rules/03_gate_prompt_length.rb +19 -0
- data/examples/rules/04_tool_selection.rb +41 -0
- data/examples/rules/README.md +30 -0
- data/examples/run_all.sh +48 -15
- data/examples/tools/word_count_tool.rb +1 -1
- data/lib/AGENTS.md +57 -0
- data/lib/aia/chat_loop.rb +306 -159
- data/lib/aia/config/cli_parser.rb +174 -111
- data/lib/aia/config/defaults.yml +62 -33
- data/lib/aia/config/mcp_parser.rb +39 -46
- data/lib/aia/config/model_spec.rb +34 -2
- data/lib/aia/config/validator.rb +121 -138
- data/lib/aia/config.rb +110 -145
- data/lib/aia/content_extractor.rb +153 -0
- data/lib/aia/cost_calculator.rb +38 -0
- data/lib/aia/crew.rb +164 -0
- data/lib/aia/debate_handler.rb +166 -0
- data/lib/aia/delegate_handler.rb +112 -0
- data/lib/aia/directive.rb +33 -18
- data/lib/aia/directive_processor.rb +16 -7
- data/lib/aia/directives/configuration_directives.rb +160 -20
- data/lib/aia/directives/context_directives.rb +38 -26
- data/lib/aia/directives/execution_directives.rb +136 -4
- data/lib/aia/directives/model_directives.rb +76 -34
- data/lib/aia/directives/trakflow_directives.rb +44 -0
- data/lib/aia/directives/utility_directives.rb +203 -6
- data/lib/aia/directives/web_and_file_directives.rb +96 -60
- data/lib/aia/errors.rb +15 -0
- data/lib/aia/fact_asserter.rb +27 -0
- data/lib/aia/fzf.rb +9 -31
- data/lib/aia/handler_context.rb +17 -0
- data/lib/aia/handler_protocol.rb +19 -0
- data/lib/aia/history_transfer.rb +55 -0
- data/lib/aia/input_collector.rb +3 -3
- data/lib/aia/layered_orchestrator.rb +448 -0
- data/lib/aia/logger.rb +24 -4
- data/lib/aia/mcp_config_normalizer.rb +35 -0
- data/lib/aia/mcp_connection_manager.rb +305 -0
- data/lib/aia/mcp_discovery.rb +44 -0
- data/lib/aia/mcp_grouper.rb +33 -0
- data/lib/aia/mcp_utility.rb +57 -0
- data/lib/aia/mention_router.rb +260 -0
- data/lib/aia/model_alias_registry.rb +97 -0
- data/lib/aia/model_switch_handler.rb +100 -0
- data/lib/aia/network_builder.rb +155 -0
- data/lib/aia/network_memory_manager.rb +55 -0
- data/lib/aia/patches/ruby_llm_streaming_error.rb +43 -0
- data/lib/aia/patches/ruby_llm_tool_error.rb +96 -0
- data/lib/aia/pipeline_orchestrator.rb +262 -0
- data/lib/aia/plugin_loader.rb +170 -0
- data/lib/aia/plugin_monitor.rb +208 -0
- data/lib/aia/prompt_decomposer.rb +157 -0
- data/lib/aia/prompt_handler.rb +19 -39
- data/lib/aia/robot_builder.rb +51 -0
- data/lib/aia/robot_factory.rb +334 -0
- data/lib/aia/robot_namer.rb +116 -0
- data/lib/aia/session.rb +83 -17
- data/lib/aia/session_tracker.rb +209 -0
- data/lib/aia/similarity_scorer.rb +39 -0
- data/lib/aia/skill_utils.rb +105 -1
- data/lib/aia/spawn_handler.rb +129 -0
- data/lib/aia/spawn_spec_parser.rb +65 -0
- data/lib/aia/special_mode_handler.rb +302 -0
- data/lib/aia/startup_coordinator.rb +150 -0
- data/lib/aia/streaming_runner.rb +169 -0
- data/lib/aia/system_prompt_assembler.rb +88 -0
- data/lib/aia/task_coordinator.rb +202 -0
- data/lib/aia/task_decomposer.rb +57 -0
- data/lib/aia/task_executor.rb +51 -0
- data/lib/aia/tfidf_math.rb +27 -0
- data/lib/aia/tool_filter/tfidf.rb +116 -0
- data/lib/aia/tool_filter/wordnet_expander.rb +127 -0
- data/lib/aia/tool_filter.rb +82 -0
- data/lib/aia/tool_filter_registry.rb +30 -0
- data/lib/aia/tool_filter_strategy.rb +143 -0
- data/lib/aia/tool_loader.rb +210 -0
- data/lib/aia/tool_utility.rb +30 -0
- data/lib/aia/tools/delegate_to_foreman_tool.rb +70 -0
- data/lib/aia/tools/recruit_robot_tool.rb +60 -0
- data/lib/aia/tools/reskill_robot_tool.rb +44 -0
- data/lib/aia/tools/task_board_tool.rb +114 -0
- data/lib/aia/trakflow_bridge.rb +173 -0
- data/lib/aia/turn_state.rb +94 -0
- data/lib/aia/ui_presenter.rb +166 -198
- data/lib/aia/utility.rb +134 -87
- data/lib/aia/{history_manager.rb → variable_input_collector.rb} +8 -9
- data/lib/aia/verification_network.rb +58 -0
- data/lib/aia.rb +108 -63
- data/mkdocs.yml +1 -0
- metadata +179 -56
- data/justfile +0 -215
- data/lib/aia/adapter/chat_execution.rb +0 -242
- data/lib/aia/adapter/error_handler.rb +0 -68
- data/lib/aia/adapter/gem_activator.rb +0 -57
- data/lib/aia/adapter/mcp_connector.rb +0 -274
- data/lib/aia/adapter/modality_handlers.rb +0 -167
- data/lib/aia/adapter/model_registry.rb +0 -81
- data/lib/aia/adapter/multi_model_chat.rb +0 -218
- data/lib/aia/adapter/provider_configurator.rb +0 -59
- data/lib/aia/adapter/tool_filter.rb +0 -85
- data/lib/aia/adapter/tool_loader.rb +0 -90
- data/lib/aia/chat_processor_service.rb +0 -164
- data/lib/aia/prompt_pipeline.rb +0 -183
- data/lib/aia/ruby_llm_adapter.rb +0 -95
- data/lib/extensions/openstruct_merge.rb +0 -48
- data/lib/extensions/ruby_llm/.irbrc +0 -56
- data/lib/extensions/ruby_llm/modalities.rb +0 -36
- data/lib/extensions/ruby_llm/provider_fix.rb +0 -79
- data/lib/refinements/string.rb +0 -16
- data/main.just +0 -76
|
@@ -11,6 +11,7 @@ require_relative 'model_spec'
|
|
|
11
11
|
require_relative '../skill_utils'
|
|
12
12
|
|
|
13
13
|
module AIA
|
|
14
|
+
# rubocop:disable Metrics/ModuleLength
|
|
14
15
|
module CLIParser
|
|
15
16
|
class << self
|
|
16
17
|
# Parse CLI arguments and return a hash of overrides
|
|
@@ -23,8 +24,8 @@ module AIA
|
|
|
23
24
|
parser = create_option_parser(options)
|
|
24
25
|
parser.parse!
|
|
25
26
|
rescue OptionParser::InvalidOption, OptionParser::MissingArgument => e
|
|
26
|
-
|
|
27
|
-
|
|
27
|
+
$stderr.puts "ERROR: #{e.message}"
|
|
28
|
+
$stderr.puts " use --help for usage report"
|
|
28
29
|
exit 1
|
|
29
30
|
end
|
|
30
31
|
|
|
@@ -51,8 +52,8 @@ module AIA
|
|
|
51
52
|
end
|
|
52
53
|
|
|
53
54
|
def setup_banner(opts)
|
|
54
|
-
opts.banner = "Usage: aia [options] [PROMPT_ID] [CONTEXT_FILE]*\n"
|
|
55
|
-
"
|
|
55
|
+
opts.banner = "Usage: aia [options] [PROMPT_ID] [CONTEXT_FILE]*\n " \
|
|
56
|
+
"aia [options] --chat [PROMPT_ID] [CONTEXT_FILE]*"
|
|
56
57
|
end
|
|
57
58
|
|
|
58
59
|
def setup_mode_options(opts, options)
|
|
@@ -64,14 +65,34 @@ module AIA
|
|
|
64
65
|
|
|
65
66
|
opts.on("-f", "--fuzzy", "Use fuzzy matching for prompt search") do
|
|
66
67
|
unless system("which fzf > /dev/null 2>&1")
|
|
67
|
-
|
|
68
|
+
$stderr.puts "Error: 'fzf' is not installed. Please install 'fzf' to use the --fuzzy option."
|
|
68
69
|
exit 1
|
|
69
70
|
end
|
|
70
71
|
options[:fuzzy] = true
|
|
71
72
|
end
|
|
72
73
|
|
|
73
|
-
opts.on("--
|
|
74
|
-
|
|
74
|
+
opts.on("--expert-routing", "Route each prompt to a specialist robot based on domain classification") do
|
|
75
|
+
options[:expert_routing] = true
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
opts.on("--track-pipeline", "Track pipeline execution in TrakFlow") do
|
|
79
|
+
options[:track_pipeline] = true
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
opts.on("--concurrent-auto", "Automatically parallelize independent MCP servers") do
|
|
83
|
+
options[:concurrent_auto] = true
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
opts.on("-A", "--[no-]auto-tool-filter", "Use TF-IDF similarity-based tool filtering (default: on)") do |v|
|
|
87
|
+
options[:auto_tool_filter] = v
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
opts.on("--load", "Load persisted tool filter databases from ~/.config/aia/") do
|
|
91
|
+
options[:tool_filter_load] = true
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
opts.on("--save", "Save tool filter databases to ~/.config/aia/") do
|
|
95
|
+
options[:tool_filter_save] = true
|
|
75
96
|
end
|
|
76
97
|
end
|
|
77
98
|
|
|
@@ -82,8 +103,10 @@ module AIA
|
|
|
82
103
|
list_available_models(query)
|
|
83
104
|
end
|
|
84
105
|
|
|
85
|
-
opts.on("-m MODEL", "--model MODEL",
|
|
86
|
-
|
|
106
|
+
opts.on("-m MODEL", "--model MODEL",
|
|
107
|
+
"Set LLM model(s). Format: MODEL[=ROLE][,MODEL[=ROLE]]... " \
|
|
108
|
+
"Multiple models run in parallel; use --consensus to synthesize results") do |model_string|
|
|
109
|
+
options[:models] = (options[:models] || []) + parse_models_with_roles(model_string)
|
|
87
110
|
end
|
|
88
111
|
|
|
89
112
|
opts.on("--[no-]consensus", "Enable/disable consensus mode for multi-model responses") do |consensus|
|
|
@@ -112,13 +135,13 @@ module AIA
|
|
|
112
135
|
end
|
|
113
136
|
|
|
114
137
|
opts.on("-o", "--[no-]output [FILE]", "Write response to FILE (default: temp.md; --no-output to disable)") do |file|
|
|
115
|
-
if file == false
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
138
|
+
options[:output] = if file == false
|
|
139
|
+
nil
|
|
140
|
+
elsif file.nil?
|
|
141
|
+
'temp.md'
|
|
142
|
+
else
|
|
143
|
+
File.expand_path(file, Dir.pwd)
|
|
144
|
+
end
|
|
122
145
|
end
|
|
123
146
|
|
|
124
147
|
opts.on("-a", "--[no-]append", "Append to output file instead of overwriting") do |append|
|
|
@@ -141,6 +164,10 @@ module AIA
|
|
|
141
164
|
options[:prompts_dir] = dir
|
|
142
165
|
end
|
|
143
166
|
|
|
167
|
+
opts.on("--plugins-dir DIR", "Set directory containing AIA plugin files") do |dir|
|
|
168
|
+
options[:plugins_dir] = dir
|
|
169
|
+
end
|
|
170
|
+
|
|
144
171
|
opts.on("--roles-prefix PREFIX", "Set subdirectory name for role files (default: roles)") do |prefix|
|
|
145
172
|
options[:roles_prefix] = prefix
|
|
146
173
|
end
|
|
@@ -149,6 +176,19 @@ module AIA
|
|
|
149
176
|
options[:role] = role
|
|
150
177
|
end
|
|
151
178
|
|
|
179
|
+
opts.on("--skills-dir DIR", "Set directory containing skill subdirectories") do |dir|
|
|
180
|
+
options[:skills_dir] = dir
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
opts.on("-s", "--skill SKILL_IDS", "Append skill(s) to prompt; comma-separated IDs or paths") do |skill_ids|
|
|
184
|
+
options[:skills] ||= []
|
|
185
|
+
options[:skills] += skill_ids.split(',').map(&:strip).reject(&:empty?)
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
opts.on("--list-skills", "List available skills and exit") do
|
|
189
|
+
options[:list_skills] = true
|
|
190
|
+
end
|
|
191
|
+
|
|
152
192
|
opts.on("-n", "--next PROMPT_ID", "Set next prompt to process") do |next_prompt|
|
|
153
193
|
options[:pipeline] ||= []
|
|
154
194
|
options[:pipeline] << next_prompt
|
|
@@ -159,32 +199,9 @@ module AIA
|
|
|
159
199
|
options[:pipeline] += pipeline.split(',').map(&:strip)
|
|
160
200
|
end
|
|
161
201
|
|
|
162
|
-
|
|
163
202
|
opts.on("--system-prompt PROMPT_ID", "Set system prompt for chat sessions") do |prompt_id|
|
|
164
203
|
options[:system_prompt] = prompt_id
|
|
165
204
|
end
|
|
166
|
-
|
|
167
|
-
opts.on('--regex PATTERN', '[DEPRECATED] Parameter regex (PM v1.0.0 uses ERB parameters)') do |pattern|
|
|
168
|
-
warn "Warning: --regex is deprecated. PM v1.0.0 uses ERB parameters (<%= param %>)."
|
|
169
|
-
options[:parameter_regex] = pattern
|
|
170
|
-
end
|
|
171
|
-
|
|
172
|
-
opts.on("--skills-dir DIR", "Set directory containing skill subdirectories") do |dir|
|
|
173
|
-
options[:skills_dir] = dir
|
|
174
|
-
end
|
|
175
|
-
|
|
176
|
-
opts.on("--skills-prefix PREFIX", "Set subdirectory name for skill files (default: skills)") do |prefix|
|
|
177
|
-
options[:skills_prefix] = prefix
|
|
178
|
-
end
|
|
179
|
-
|
|
180
|
-
opts.on("-s", "--skill SKILL_IDS", "Prepend skill(s) to prompt (comma-separated IDs or paths)") do |ids|
|
|
181
|
-
options[:skills] ||= []
|
|
182
|
-
options[:skills] += ids.split(',').map(&:strip)
|
|
183
|
-
end
|
|
184
|
-
|
|
185
|
-
opts.on("--list-skills", "List available skills and exit") do
|
|
186
|
-
options[:list_skills] = true
|
|
187
|
-
end
|
|
188
205
|
end
|
|
189
206
|
|
|
190
207
|
def setup_ai_parameters(opts, options)
|
|
@@ -194,7 +211,7 @@ module AIA
|
|
|
194
211
|
options[:temperature] = temp
|
|
195
212
|
end
|
|
196
213
|
|
|
197
|
-
opts.on("--max-tokens TOKENS", Integer, "Set maximum tokens for text generation (default:
|
|
214
|
+
opts.on("--max-tokens TOKENS", Integer, "Set maximum tokens for text generation (default: 32767)") do |tokens|
|
|
198
215
|
options[:max_tokens] = tokens
|
|
199
216
|
end
|
|
200
217
|
|
|
@@ -218,10 +235,22 @@ module AIA
|
|
|
218
235
|
options[:speak] = true
|
|
219
236
|
end
|
|
220
237
|
|
|
221
|
-
opts.on("--voice VOICE", "Set voice for speech output
|
|
238
|
+
opts.on("--voice VOICE", "Set voice for speech output") do |voice|
|
|
222
239
|
options[:voice] = voice
|
|
223
240
|
end
|
|
224
241
|
|
|
242
|
+
opts.on("--speak-command CMD", "Command used for TTS (default: say)") do |cmd|
|
|
243
|
+
options[:speak_command] = cmd
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
opts.on("--paint", "Generate an image from the prompt instead of a text response") do
|
|
247
|
+
options[:paint] = true
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
opts.on("--im", "--image-model MODEL", "Set image model for generation (default: dall-e-3)") do |model|
|
|
251
|
+
options[:image_model] = model
|
|
252
|
+
end
|
|
253
|
+
|
|
225
254
|
opts.on("--is", "--image-size SIZE", "Set image size for generation (default: 1024x1024)") do |size|
|
|
226
255
|
options[:image_size] = size
|
|
227
256
|
end
|
|
@@ -238,6 +267,10 @@ module AIA
|
|
|
238
267
|
def setup_tool_options(opts, options)
|
|
239
268
|
opts.separator "\nTool & Extension Options:"
|
|
240
269
|
|
|
270
|
+
opts.on('--allow-ruby-eval', 'Enable /ruby directive (executes arbitrary Ruby code with full process privileges)') do
|
|
271
|
+
options[:allow_ruby_eval] = true
|
|
272
|
+
end
|
|
273
|
+
|
|
241
274
|
opts.on("--rq LIBS", "--require LIBS", "Require Ruby libraries for Ruby directive") do |libs|
|
|
242
275
|
options[:require_libs] ||= []
|
|
243
276
|
options[:require_libs] += libs.split(',')
|
|
@@ -264,11 +297,17 @@ module AIA
|
|
|
264
297
|
|
|
265
298
|
def setup_utility_options(opts, options)
|
|
266
299
|
opts.separator "\nUtility Options:"
|
|
300
|
+
setup_logging_options(opts, options)
|
|
301
|
+
setup_output_options(opts, options)
|
|
302
|
+
setup_mcp_options(opts, options)
|
|
303
|
+
setup_meta_options(opts, options)
|
|
304
|
+
end
|
|
267
305
|
|
|
306
|
+
def setup_logging_options(opts, options)
|
|
268
307
|
opts.on("--log-level LEVEL", "Set log level (debug|info|warn|error|fatal)") do |level|
|
|
269
308
|
level = level.downcase
|
|
270
309
|
unless %w[debug info warn error fatal].include?(level)
|
|
271
|
-
|
|
310
|
+
$stderr.puts "ERROR: Invalid log level '#{level}'. Must be one of: debug, info, warn, error, fatal"
|
|
272
311
|
exit 1
|
|
273
312
|
end
|
|
274
313
|
options[:log_level_override] = level
|
|
@@ -296,6 +335,21 @@ module AIA
|
|
|
296
335
|
opts.on("-v", "--[no-]verbose", "Enable verbose output") do |value|
|
|
297
336
|
options[:verbose] = value
|
|
298
337
|
end
|
|
338
|
+
end
|
|
339
|
+
|
|
340
|
+
def setup_output_options(opts, options)
|
|
341
|
+
opts.on("--[no-]thinking", "Show raw thinking/reasoning blocks in output (default: off)") do |v|
|
|
342
|
+
options[:thinking] = v
|
|
343
|
+
end
|
|
344
|
+
|
|
345
|
+
opts.on("--tokens", "Display token usage and elapsed response time after each turn") do
|
|
346
|
+
options[:tokens] = true
|
|
347
|
+
end
|
|
348
|
+
|
|
349
|
+
opts.on("--cost", "Display cost calculations and elapsed time (implies --tokens)") do
|
|
350
|
+
options[:cost] = true
|
|
351
|
+
options[:tokens] = true
|
|
352
|
+
end
|
|
299
353
|
|
|
300
354
|
opts.on("--refresh DAYS", Integer, "Set refresh interval (days) for cached models list (default: 7)") do |days|
|
|
301
355
|
options[:refresh] = days || 0
|
|
@@ -308,16 +362,9 @@ module AIA
|
|
|
308
362
|
opts.on("--completion SHELL", "Generate shell completion script (bash|zsh|fish) and exit") do |shell|
|
|
309
363
|
options[:completion] = shell
|
|
310
364
|
end
|
|
365
|
+
end
|
|
311
366
|
|
|
312
|
-
|
|
313
|
-
options[:tokens] = true
|
|
314
|
-
end
|
|
315
|
-
|
|
316
|
-
opts.on("--cost", "Display cost calculations (implies --tokens)") do
|
|
317
|
-
options[:cost] = true
|
|
318
|
-
options[:tokens] = true # --cost implies --tokens
|
|
319
|
-
end
|
|
320
|
-
|
|
367
|
+
def setup_mcp_options(opts, options)
|
|
321
368
|
opts.on("--mcp FILE", "Load MCP server(s) from JSON file (repeatable)") do |file|
|
|
322
369
|
options[:mcp_files] ||= []
|
|
323
370
|
options[:mcp_files] << file
|
|
@@ -340,47 +387,55 @@ module AIA
|
|
|
340
387
|
options[:mcp_skip] ||= []
|
|
341
388
|
options[:mcp_skip] += names.split(',').map(&:strip)
|
|
342
389
|
end
|
|
390
|
+
end
|
|
343
391
|
|
|
392
|
+
def setup_meta_options(opts, _options)
|
|
344
393
|
opts.on("--version", "Show version and exit") do
|
|
345
394
|
puts AIA::VERSION
|
|
346
395
|
exit
|
|
347
396
|
end
|
|
348
397
|
|
|
349
398
|
opts.on("-h", "--help", "Show this help and exit") do
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
AIA - Your AI Assistant (v#{AIA::VERSION})
|
|
353
|
-
- Manage AI prompts with embedded directives
|
|
354
|
-
- Integrate with shell and Ruby (ERB) processing
|
|
355
|
-
- Run batch processes and prompt pipelines
|
|
356
|
-
- Engage in interactive chat sessions
|
|
357
|
-
- Use custom tools and MCP servers
|
|
358
|
-
|
|
359
|
-
HELP
|
|
360
|
-
|
|
361
|
-
puts opts
|
|
362
|
-
|
|
363
|
-
puts <<~EXTRA
|
|
364
|
-
|
|
365
|
-
Explore Further:
|
|
366
|
-
- AIA GitHub Repository: https://github.com/MadBomber/aia
|
|
367
|
-
- AIA Documentation: https://madbomber.github.io/aia
|
|
368
|
-
- AIA Changelog: https://github.com/MadBomber/aia/blob/main/CHANGELOG.md
|
|
369
|
-
- AIA Examples: https://github.com/MadBomber/aia/tree/main/examples
|
|
370
|
-
- Report an Issue: https://github.com/MadBomber/aia/issues
|
|
371
|
-
- RubyLLM Documentation: https://rubyllm.com
|
|
372
|
-
- RubyLLM Tool Docs: https://rubyllm.com/guides/tools
|
|
373
|
-
- PromptManager Docs: https://madbomber.github.io/prompt_manager
|
|
374
|
-
- ERB Documentation: https://docs.ruby-lang.org/en/master/ERB.html
|
|
375
|
-
- MCP Specification: https://modelcontextprotocol.io
|
|
376
|
-
- MCP Client Docs: https://github.com/patvice/ruby_llm-mcp/blob/main/README.md
|
|
377
|
-
|
|
378
|
-
EXTRA
|
|
379
|
-
|
|
399
|
+
print_help(opts)
|
|
380
400
|
exit
|
|
381
401
|
end
|
|
382
402
|
end
|
|
383
403
|
|
|
404
|
+
def print_help(opts)
|
|
405
|
+
puts <<~HELP
|
|
406
|
+
|
|
407
|
+
AIA - Your AI Assistant (v#{AIA::VERSION})
|
|
408
|
+
- Manage AI prompts with embedded directives
|
|
409
|
+
- Integrate with shell and Ruby (ERB) processing
|
|
410
|
+
- Run batch processes and prompt pipelines
|
|
411
|
+
- Engage in interactive chat sessions
|
|
412
|
+
- Use custom tools and MCP servers
|
|
413
|
+
- Compare the same prompt across multiple models (--model m1,m2,m3 [--consensus])
|
|
414
|
+
- Measure response time and token usage with --tokens; add cost with --cost
|
|
415
|
+
- Benchmark concurrent vs. serial performance (/decompose reports speedup metrics)
|
|
416
|
+
|
|
417
|
+
HELP
|
|
418
|
+
|
|
419
|
+
puts opts
|
|
420
|
+
|
|
421
|
+
puts <<~EXTRA
|
|
422
|
+
|
|
423
|
+
Explore Further:
|
|
424
|
+
- AIA GitHub Repository: https://github.com/MadBomber/aia
|
|
425
|
+
- AIA Documentation: https://madbomber.github.io/aia
|
|
426
|
+
- AIA Changelog: https://github.com/MadBomber/aia/blob/main/CHANGELOG.md
|
|
427
|
+
- AIA Examples: https://github.com/MadBomber/aia/tree/main/examples
|
|
428
|
+
- Report an Issue: https://github.com/MadBomber/aia/issues
|
|
429
|
+
- RubyLLM Documentation: https://rubyllm.com
|
|
430
|
+
- RubyLLM Tool Docs: https://rubyllm.com/guides/tools
|
|
431
|
+
- PromptManager Docs: https://madbomber.github.io/prompt_manager
|
|
432
|
+
- ERB Documentation: https://docs.ruby-lang.org/en/master/ERB.html
|
|
433
|
+
- MCP Specification: https://modelcontextprotocol.io
|
|
434
|
+
- MCP Client Docs: https://github.com/patvice/ruby_llm-mcp/blob/main/README.md
|
|
435
|
+
|
|
436
|
+
EXTRA
|
|
437
|
+
end
|
|
438
|
+
|
|
384
439
|
# Parse model string into array of ModelSpec-compatible hashes
|
|
385
440
|
#
|
|
386
441
|
# @param model_string [String] comma-separated models with optional roles
|
|
@@ -389,6 +444,7 @@ module AIA
|
|
|
389
444
|
models = []
|
|
390
445
|
model_counts = Hash.new(0)
|
|
391
446
|
|
|
447
|
+
# rubocop:disable Metrics/BlockLength
|
|
392
448
|
model_string.split(',').each do |spec|
|
|
393
449
|
spec.strip!
|
|
394
450
|
|
|
@@ -424,6 +480,7 @@ module AIA
|
|
|
424
480
|
}
|
|
425
481
|
end
|
|
426
482
|
end
|
|
483
|
+
# rubocop:enable Metrics/BlockLength
|
|
427
484
|
|
|
428
485
|
models
|
|
429
486
|
end
|
|
@@ -433,10 +490,11 @@ module AIA
|
|
|
433
490
|
expanded = File.expand_path(role_id)
|
|
434
491
|
expanded += '.md' if File.extname(expanded).empty?
|
|
435
492
|
raise ArgumentError, "Role file not found: #{expanded}" unless File.exist?(expanded)
|
|
493
|
+
|
|
436
494
|
return
|
|
437
495
|
end
|
|
438
496
|
|
|
439
|
-
prompts_dir = ENV.fetch('AIA_PROMPTS__DIR', File.join(
|
|
497
|
+
prompts_dir = ENV.fetch('AIA_PROMPTS__DIR', File.join(Dir.home, '.prompts'))
|
|
440
498
|
roles_prefix = ENV.fetch('AIA_PROMPTS__ROLES_PREFIX', 'roles')
|
|
441
499
|
|
|
442
500
|
unless role_id.start_with?(roles_prefix)
|
|
@@ -445,26 +503,25 @@ module AIA
|
|
|
445
503
|
|
|
446
504
|
role_file_path = File.join(prompts_dir, "#{role_id}.md")
|
|
447
505
|
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
error_msg = "Role file not found: #{role_file_path}\n\n"
|
|
506
|
+
return if File.exist?(role_file_path)
|
|
507
|
+
available_roles = list_available_role_names(prompts_dir, roles_prefix)
|
|
452
508
|
|
|
453
|
-
|
|
454
|
-
error_msg += "No roles directory found at #{File.join(prompts_dir, roles_prefix)}\n"
|
|
455
|
-
error_msg += "Create the directory and add role files to use this feature."
|
|
456
|
-
else
|
|
457
|
-
error_msg += "Available roles:\n"
|
|
458
|
-
error_msg += available_roles.map { |r| " - #{r}" }.join("\n")
|
|
459
|
-
error_msg += "\n\nCreate the role file or use an existing role."
|
|
460
|
-
end
|
|
509
|
+
error_msg = "Role file not found: #{role_file_path}\n\n"
|
|
461
510
|
|
|
462
|
-
|
|
511
|
+
if available_roles.empty?
|
|
512
|
+
error_msg += "No roles directory found at #{File.join(prompts_dir, roles_prefix)}\n"
|
|
513
|
+
error_msg += "Create the directory and add role files to use this feature."
|
|
514
|
+
else
|
|
515
|
+
error_msg += "Available roles:\n"
|
|
516
|
+
error_msg += available_roles.map { |r| " - #{r}" }.join("\n")
|
|
517
|
+
error_msg += "\n\nCreate the role file or use an existing role."
|
|
463
518
|
end
|
|
519
|
+
|
|
520
|
+
raise ArgumentError, error_msg
|
|
464
521
|
end
|
|
465
522
|
|
|
466
523
|
def list_available_roles
|
|
467
|
-
prompts_dir = ENV.fetch('AIA_PROMPTS__DIR', File.join(
|
|
524
|
+
prompts_dir = ENV.fetch('AIA_PROMPTS__DIR', File.join(Dir.home, '.prompts'))
|
|
468
525
|
roles_prefix = ENV.fetch('AIA_PROMPTS__ROLES_PREFIX', 'roles')
|
|
469
526
|
roles_dir = File.join(prompts_dir, roles_prefix)
|
|
470
527
|
|
|
@@ -484,13 +541,16 @@ module AIA
|
|
|
484
541
|
|
|
485
542
|
roles.each do |role_id|
|
|
486
543
|
role_file = File.join(roles_dir, "#{role_id}.md")
|
|
487
|
-
|
|
544
|
+
front_matter = AIA::SkillUtils.parse_front_matter(role_file)
|
|
488
545
|
|
|
489
546
|
puts "## #{role_id}"
|
|
490
547
|
puts
|
|
491
548
|
puts "| Key | Value |"
|
|
492
549
|
puts "|-----|-------|"
|
|
493
|
-
|
|
550
|
+
front_matter.each do |key, value|
|
|
551
|
+
safe_value = value.to_s.gsub('|', '\\|')
|
|
552
|
+
puts "| #{key} | #{safe_value} |"
|
|
553
|
+
end
|
|
494
554
|
puts
|
|
495
555
|
end
|
|
496
556
|
end
|
|
@@ -500,19 +560,21 @@ module AIA
|
|
|
500
560
|
return [] unless Dir.exist?(roles_dir)
|
|
501
561
|
|
|
502
562
|
Dir.glob("**/*.md", base: roles_dir)
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
563
|
+
.map { |f| f.chomp('.md') }
|
|
564
|
+
.reject { |f| f.split('/').any? { |part| part.start_with?('_') } }
|
|
565
|
+
.sort
|
|
506
566
|
end
|
|
507
567
|
|
|
568
|
+
# rubocop:disable Metrics/AbcSize
|
|
508
569
|
def list_available_models(query)
|
|
509
570
|
require 'ruby_llm'
|
|
510
571
|
|
|
511
|
-
if query.nil?
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
572
|
+
query = if query.nil?
|
|
573
|
+
[]
|
|
574
|
+
else
|
|
575
|
+
query.split(',')
|
|
576
|
+
end
|
|
577
|
+
# rubocop:enable Metrics/AbcSize
|
|
516
578
|
|
|
517
579
|
header = "\nAvailable LLMs"
|
|
518
580
|
header += " for #{query.join(' and ')}" if query.any?
|
|
@@ -546,28 +608,29 @@ module AIA
|
|
|
546
608
|
end
|
|
547
609
|
end
|
|
548
610
|
|
|
549
|
-
puts if counter
|
|
611
|
+
puts if counter.positive?
|
|
550
612
|
puts "#{counter} LLMs matching your query"
|
|
551
613
|
puts
|
|
552
614
|
|
|
553
615
|
exit
|
|
554
616
|
end
|
|
617
|
+
# rubocop:enable Metrics/ModuleLength
|
|
555
618
|
|
|
556
619
|
def process_tools_paths(path_list)
|
|
557
620
|
paths = []
|
|
558
621
|
|
|
559
622
|
if path_list.empty?
|
|
560
|
-
|
|
623
|
+
$stderr.puts "No list of paths for --tools option"
|
|
561
624
|
exit 1
|
|
562
625
|
end
|
|
563
626
|
|
|
564
627
|
path_list.split(',').map(&:strip).uniq.each do |a_path|
|
|
565
628
|
if File.exist?(a_path)
|
|
566
629
|
if File.file?(a_path)
|
|
567
|
-
if
|
|
630
|
+
if File.extname(a_path) == '.rb'
|
|
568
631
|
paths << a_path
|
|
569
632
|
else
|
|
570
|
-
|
|
633
|
+
$stderr.puts "file should have *.rb extension: #{a_path}"
|
|
571
634
|
exit 1
|
|
572
635
|
end
|
|
573
636
|
elsif File.directory?(a_path)
|
|
@@ -575,7 +638,7 @@ module AIA
|
|
|
575
638
|
paths += rb_files
|
|
576
639
|
end
|
|
577
640
|
else
|
|
578
|
-
|
|
641
|
+
$stderr.puts "file/dir path is not valid: #{a_path}"
|
|
579
642
|
exit 1
|
|
580
643
|
end
|
|
581
644
|
end
|
data/lib/aia/config/defaults.yml
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# AIA Configuration Schema and Defaults
|
|
1
|
+
# AIA v2 Configuration Schema and Defaults
|
|
2
2
|
#
|
|
3
3
|
# This file is the SINGLE SOURCE OF TRUTH for AIA configuration.
|
|
4
4
|
# All attributes must be declared here to be recognized.
|
|
@@ -28,8 +28,8 @@ defaults:
|
|
|
28
28
|
# ---------------------------------------------------------------------------
|
|
29
29
|
llm:
|
|
30
30
|
temperature: 0.7
|
|
31
|
-
max_tokens:
|
|
32
|
-
top_p:
|
|
31
|
+
max_tokens: 32767
|
|
32
|
+
top_p: ~ # nil by default — some models reject requests with both temperature AND top_p
|
|
33
33
|
frequency_penalty: 0.0
|
|
34
34
|
presence_penalty: 0.0
|
|
35
35
|
|
|
@@ -65,13 +65,11 @@ defaults:
|
|
|
65
65
|
roles_prefix: roles
|
|
66
66
|
#
|
|
67
67
|
skills: []
|
|
68
|
-
skills_prefix: skills
|
|
69
68
|
#
|
|
70
69
|
tool: ~
|
|
71
70
|
tools_prefix: tools
|
|
72
71
|
#
|
|
73
72
|
system_prompt: ~
|
|
74
|
-
parameter_regex: ~
|
|
75
73
|
|
|
76
74
|
roles:
|
|
77
75
|
dir: ~/.prompts/roles
|
|
@@ -96,10 +94,10 @@ defaults:
|
|
|
96
94
|
# Env: AIA_AUDIO__VOICE, AIA_AUDIO__SPEAK_COMMAND, etc.
|
|
97
95
|
# ---------------------------------------------------------------------------
|
|
98
96
|
audio:
|
|
99
|
-
voice:
|
|
100
|
-
speak_command:
|
|
101
|
-
speech_model:
|
|
102
|
-
transcription_model:
|
|
97
|
+
voice: ~
|
|
98
|
+
speak_command: say
|
|
99
|
+
speech_model: ~
|
|
100
|
+
transcription_model: ~
|
|
103
101
|
|
|
104
102
|
# ---------------------------------------------------------------------------
|
|
105
103
|
# Image Configuration
|
|
@@ -145,26 +143,31 @@ defaults:
|
|
|
145
143
|
tokens: false
|
|
146
144
|
no_mcp: false
|
|
147
145
|
speak: false
|
|
148
|
-
terse: false # DEPRECATED: no longer used
|
|
149
146
|
shell: true
|
|
150
147
|
erb: true
|
|
151
148
|
clear: false
|
|
152
149
|
consensus: false
|
|
150
|
+
track_pipeline: false
|
|
151
|
+
expert_routing: false
|
|
152
|
+
auto_tool_filter: true
|
|
153
|
+
tool_filter_load: false
|
|
154
|
+
tool_filter_save: false
|
|
155
|
+
allow_ruby_eval: false
|
|
156
|
+
paint: false
|
|
157
|
+
thinking: false
|
|
158
|
+
|
|
159
|
+
# ---------------------------------------------------------------------------
|
|
160
|
+
# Tool Filter Configuration
|
|
161
|
+
# Access: AIA.config.tool_filter.timeout_s
|
|
162
|
+
# Env: AIA_TOOL_FILTER__TIMEOUT_S
|
|
163
|
+
# ---------------------------------------------------------------------------
|
|
164
|
+
tool_filter:
|
|
165
|
+
timeout_s: 10
|
|
153
166
|
|
|
154
167
|
# ---------------------------------------------------------------------------
|
|
155
168
|
# Logger Configuration
|
|
156
169
|
# Access: AIA.config.logger.aia.file, AIA.config.logger.llm.level, etc.
|
|
157
170
|
# Env: AIA_LOGGER__AIA__FILE, AIA_LOGGER__LLM__LEVEL, etc.
|
|
158
|
-
#
|
|
159
|
-
# Configures logging for three systems:
|
|
160
|
-
# aia: AIA application logging
|
|
161
|
-
# llm: RubyLLM gem logging
|
|
162
|
-
# mcp: RubyLLM::MCP gem logging
|
|
163
|
-
#
|
|
164
|
-
# file: STDOUT, STDERR, or a file path (e.g., ~/.aia/aia.log)
|
|
165
|
-
# All three loggers can write to the same file safely.
|
|
166
|
-
# level: debug, info, warn, error, fatal
|
|
167
|
-
# flush: true = immediate write (no buffering), false = buffered writes
|
|
168
171
|
# ---------------------------------------------------------------------------
|
|
169
172
|
logger:
|
|
170
173
|
aia:
|
|
@@ -190,7 +193,6 @@ defaults:
|
|
|
190
193
|
# Model Registry Configuration
|
|
191
194
|
# Access: AIA.config.registry.refresh
|
|
192
195
|
# Env: AIA_REGISTRY__REFRESH
|
|
193
|
-
# Note: last_refresh is derived from models.json file modification time
|
|
194
196
|
# ---------------------------------------------------------------------------
|
|
195
197
|
registry:
|
|
196
198
|
refresh: 7 # days between refreshes (0 = disable periodic refresh)
|
|
@@ -204,14 +206,6 @@ defaults:
|
|
|
204
206
|
# ---------------------------------------------------------------------------
|
|
205
207
|
# MCP Servers Configuration
|
|
206
208
|
# Access: AIA.config.mcp_servers (array of server configs)
|
|
207
|
-
#
|
|
208
|
-
# Example:
|
|
209
|
-
# mcp_servers:
|
|
210
|
-
# - name: my-server
|
|
211
|
-
# command: /path/to/server
|
|
212
|
-
# args: []
|
|
213
|
-
# env: {}
|
|
214
|
-
# timeout: 8000
|
|
215
209
|
# ---------------------------------------------------------------------------
|
|
216
210
|
mcp_servers: []
|
|
217
211
|
mcp_use: ~
|
|
@@ -219,15 +213,50 @@ defaults:
|
|
|
219
213
|
|
|
220
214
|
# ---------------------------------------------------------------------------
|
|
221
215
|
# Paths Configuration
|
|
222
|
-
# Access: AIA.config.paths.aia_dir, AIA.config.paths.config_file
|
|
216
|
+
# Access: AIA.config.paths.aia_dir, AIA.config.paths.config_file, AIA.config.paths.plugins_dir
|
|
223
217
|
# Env: AIA_PATHS__AIA_DIR, AIA_PATHS__CONFIG_FILE
|
|
224
|
-
#
|
|
225
|
-
# Note: MywayConfig uses XDG Base Directory Specification by default.
|
|
226
|
-
# User config is loaded from ~/.config/aia/aia.yml
|
|
218
|
+
# Special-case env: AIA_PLUGINS_DIR
|
|
227
219
|
# ---------------------------------------------------------------------------
|
|
228
220
|
paths:
|
|
229
221
|
aia_dir: ~/.config/aia
|
|
230
222
|
config_file: ~/.config/aia/aia.yml
|
|
223
|
+
plugins_dir: ~
|
|
224
|
+
|
|
225
|
+
# ---------------------------------------------------------------------------
|
|
226
|
+
# Model Aliases (user-defined aliases override defaults)
|
|
227
|
+
# Access: AIA.config.model_aliases
|
|
228
|
+
# ---------------------------------------------------------------------------
|
|
229
|
+
model_aliases: {}
|
|
230
|
+
|
|
231
|
+
# ---------------------------------------------------------------------------
|
|
232
|
+
# Model Switch History Mode
|
|
233
|
+
# Controls conversation history transfer when switching models mid-chat.
|
|
234
|
+
# Values: clean (fresh start), replay (replay messages), summarize (summary)
|
|
235
|
+
# Access: AIA.config.model_switch_history
|
|
236
|
+
# ---------------------------------------------------------------------------
|
|
237
|
+
model_switch_history: clean
|
|
238
|
+
|
|
239
|
+
# ---------------------------------------------------------------------------
|
|
240
|
+
# Concurrency Configuration
|
|
241
|
+
# Controls automatic MCP server parallelization.
|
|
242
|
+
# Access: AIA.config.concurrency.auto, etc.
|
|
243
|
+
# ---------------------------------------------------------------------------
|
|
244
|
+
concurrency:
|
|
245
|
+
auto: false
|
|
246
|
+
independent_servers: []
|
|
247
|
+
threshold: 2
|
|
248
|
+
mcp_timeout: 120
|
|
249
|
+
|
|
250
|
+
# ---------------------------------------------------------------------------
|
|
251
|
+
# Rules Configuration (Enhanced Multi-KB in v2)
|
|
252
|
+
# Access: AIA.config.rules.dir, AIA.config.rules.enabled, etc.
|
|
253
|
+
# Env: AIA_RULES__DIR, AIA_RULES__ENABLED
|
|
254
|
+
# ---------------------------------------------------------------------------
|
|
255
|
+
rules:
|
|
256
|
+
dir: ~/.config/aia/rules
|
|
257
|
+
enabled: true
|
|
258
|
+
store: memory
|
|
259
|
+
db_path: ~/.config/aia/rules.db
|
|
231
260
|
|
|
232
261
|
# ---------------------------------------------------------------------------
|
|
233
262
|
# Context Files (set at runtime)
|