aia 1.1.1 → 2.0.0.0.pre.beta2
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 +9 -1
- data/.loki +11 -0
- data/.reek.yml +160 -0
- data/.rubocop.yml +116 -0
- data/.rubocop_strict.yml +15 -0
- data/.version +1 -1
- data/CHANGELOG.md +269 -55
- data/IMPLEMENTATION_PLAN.md +506 -0
- data/README.md +267 -239
- data/Rakefile +5 -5
- data/_typos.toml +10 -0
- data/aia.gemspec +92 -0
- data/architecture_review.md +314 -0
- data/bin/aia +16 -0
- data/config/aia.yml +13 -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 +18 -6
- data/examples/context/tech_stack.md +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 +263 -167
- data/lib/aia/config/cli_parser.rb +217 -145
- data/lib/aia/config/defaults.yml +62 -33
- data/lib/aia/config/mcp_parser.rb +52 -51
- data/lib/aia/config/model_spec.rb +34 -2
- data/lib/aia/config/validator.rb +171 -216
- data/lib/aia/config.rb +111 -145
- data/lib/aia/content_extractor.rb +155 -0
- data/lib/aia/cost_calculator.rb +39 -0
- data/lib/aia/crew.rb +164 -0
- data/lib/aia/debate_handler.rb +174 -0
- data/lib/aia/delegate_handler.rb +116 -0
- data/lib/aia/directive.rb +43 -26
- data/lib/aia/directive_processor.rb +16 -7
- data/lib/aia/directives/configuration_directives.rb +214 -60
- data/lib/aia/directives/context_directives.rb +67 -52
- data/lib/aia/directives/execution_directives.rb +141 -4
- data/lib/aia/directives/model_directives.rb +163 -141
- data/lib/aia/directives/trakflow_directives.rb +62 -0
- data/lib/aia/directives/utility_directives.rb +227 -30
- data/lib/aia/directives/web_and_file_directives.rb +126 -77
- 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 +471 -0
- data/lib/aia/logger.rb +45 -25
- data/lib/aia/mcp_config_normalizer.rb +35 -0
- data/lib/aia/mcp_connection_manager.rb +315 -0
- data/lib/aia/mcp_discovery.rb +44 -0
- data/lib/aia/mcp_grouper.rb +33 -0
- data/lib/aia/mcp_server_config.rb +30 -0
- data/lib/aia/mcp_utility.rb +60 -0
- data/lib/aia/mention_router.rb +217 -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 +160 -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 +272 -0
- data/lib/aia/plugin_loader.rb +170 -0
- data/lib/aia/plugin_monitor.rb +211 -0
- data/lib/aia/prompt_decomposer.rb +159 -0
- data/lib/aia/prompt_handler.rb +56 -82
- data/lib/aia/robot_builder.rb +51 -0
- data/lib/aia/robot_factory.rb +338 -0
- data/lib/aia/robot_namer.rb +110 -0
- data/lib/aia/session.rb +87 -17
- data/lib/aia/session_tracker.rb +207 -0
- data/lib/aia/similarity_scorer.rb +41 -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 +322 -0
- data/lib/aia/speech.rb +67 -0
- data/lib/aia/startup_coordinator.rb +151 -0
- data/lib/aia/streaming_runner.rb +172 -0
- data/lib/aia/system_prompt_assembler.rb +92 -0
- data/lib/aia/task_coordinator.rb +207 -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/timing.rb +15 -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 +83 -0
- data/lib/aia/tool_filter_registry.rb +30 -0
- data/lib/aia/tool_filter_strategy.rb +146 -0
- data/lib/aia/tool_introspection.rb +17 -0
- data/lib/aia/tool_loader.rb +216 -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 +115 -0
- data/lib/aia/trakflow_bridge.rb +175 -0
- data/lib/aia/turn_state.rb +95 -0
- data/lib/aia/ui_presenter.rb +182 -206
- data/lib/aia/utility.rb +136 -87
- data/lib/aia/{history_manager.rb → variable_input_collector.rb} +9 -9
- data/lib/aia/verification_network.rb +57 -0
- data/lib/aia.rb +124 -63
- data/mkdocs.yml +1 -0
- metadata +187 -58
- 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 -178
- 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
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)
|
|
@@ -3,9 +3,19 @@
|
|
|
3
3
|
# lib/aia/config/mcp_parser.rb
|
|
4
4
|
#
|
|
5
5
|
# Parses MCP server JSON configuration files and converts them
|
|
6
|
-
# to the format expected by
|
|
6
|
+
# to the nested transport format expected by robot_lab.
|
|
7
7
|
#
|
|
8
|
-
#
|
|
8
|
+
# Output format (robot_lab native):
|
|
9
|
+
# {
|
|
10
|
+
# name: "server_name",
|
|
11
|
+
# transport: { type: "stdio", command: "npx", args: [...], env: {...} },
|
|
12
|
+
# timeout: 8000,
|
|
13
|
+
# topics: ["routing"], # AIA routing metadata (optional)
|
|
14
|
+
# independent: false, # AIA concurrency metadata (optional)
|
|
15
|
+
# group: "services" # AIA grouping metadata (optional)
|
|
16
|
+
# }
|
|
17
|
+
#
|
|
18
|
+
# Supports two JSON input formats:
|
|
9
19
|
#
|
|
10
20
|
# 1. Simple format (single server):
|
|
11
21
|
# {
|
|
@@ -31,9 +41,11 @@ module AIA
|
|
|
31
41
|
module McpParser
|
|
32
42
|
class << self
|
|
33
43
|
# Parse MCP server configuration files and return array of server configs
|
|
44
|
+
# in robot_lab's nested transport format.
|
|
34
45
|
#
|
|
35
46
|
# @param file_paths [Array<String>] paths to JSON configuration files
|
|
36
|
-
# @return [Array<Hash>] array of server configurations
|
|
47
|
+
# @return [Array<Hash>] array of server configurations with nested transport
|
|
48
|
+
# :reek:TooManyStatements -- per-file loop with warn-and-continue handling for missing files, bad JSON, and read errors
|
|
37
49
|
def parse_files(file_paths)
|
|
38
50
|
return [] if file_paths.nil? || file_paths.empty?
|
|
39
51
|
|
|
@@ -43,7 +55,7 @@ module AIA
|
|
|
43
55
|
expanded_path = File.expand_path(file_path)
|
|
44
56
|
|
|
45
57
|
unless File.exist?(expanded_path)
|
|
46
|
-
|
|
58
|
+
$stderr.puts "Warning: MCP config file not found: #{file_path}"
|
|
47
59
|
next
|
|
48
60
|
end
|
|
49
61
|
|
|
@@ -52,9 +64,9 @@ module AIA
|
|
|
52
64
|
parsed = JSON.parse(json_content)
|
|
53
65
|
servers.concat(convert_to_config_format(parsed, file_path))
|
|
54
66
|
rescue JSON::ParserError => e
|
|
55
|
-
|
|
67
|
+
$stderr.puts "Warning: Invalid JSON in MCP config file '#{file_path}': #{e.message}"
|
|
56
68
|
rescue StandardError => e
|
|
57
|
-
|
|
69
|
+
$stderr.puts "Warning: Error reading MCP config file '#{file_path}': #{e.message}"
|
|
58
70
|
end
|
|
59
71
|
end
|
|
60
72
|
|
|
@@ -76,43 +88,38 @@ module AIA
|
|
|
76
88
|
end
|
|
77
89
|
end
|
|
78
90
|
|
|
79
|
-
# Convert mcpServers format to
|
|
91
|
+
# Convert mcpServers format to robot_lab nested transport format
|
|
80
92
|
#
|
|
81
93
|
# @param mcp_servers [Hash] the mcpServers hash from JSON
|
|
82
94
|
# @return [Array<Hash>] array of server configurations
|
|
83
95
|
def convert_mcp_servers_format(mcp_servers)
|
|
84
96
|
mcp_servers.map do |name, config|
|
|
85
|
-
server = { name: name }
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
if config['args']
|
|
92
|
-
server[:args] = Array(config['args'])
|
|
93
|
-
end
|
|
94
|
-
|
|
95
|
-
if config['env']
|
|
96
|
-
server[:env] = config['env']
|
|
97
|
-
end
|
|
98
|
-
|
|
99
|
-
if config['timeout']
|
|
100
|
-
server[:timeout] = config['timeout'].to_i
|
|
101
|
-
end
|
|
102
|
-
|
|
103
|
-
if config['url']
|
|
104
|
-
server[:url] = config['url']
|
|
105
|
-
end
|
|
97
|
+
server = { name: name, transport: build_transport(config) }
|
|
98
|
+
server[:timeout] = config['timeout'].to_i if config['timeout']
|
|
99
|
+
server.merge!(routing_metadata(config))
|
|
100
|
+
end
|
|
101
|
+
end
|
|
106
102
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
103
|
+
def build_transport(config)
|
|
104
|
+
transport = { type: config['type'] || 'stdio' }
|
|
105
|
+
transport[:command] = config['command'] if config['command']
|
|
106
|
+
transport[:args] = Array(config['args']) if config['args']
|
|
107
|
+
transport[:env] = config['env'] if config['env']
|
|
108
|
+
transport[:url] = config['url'] if config['url']
|
|
109
|
+
transport[:headers] = config['headers'] if config['headers']
|
|
110
|
+
transport
|
|
111
|
+
end
|
|
110
112
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
+
# Routing metadata preserved for KBS/AIA
|
|
114
|
+
def routing_metadata(config)
|
|
115
|
+
meta = {}
|
|
116
|
+
meta[:topics] = Array(config['topics']) if config['topics']
|
|
117
|
+
meta[:independent] = config['independent'] unless config['independent'].nil?
|
|
118
|
+
meta[:group] = config['group'] if config['group']
|
|
119
|
+
meta
|
|
113
120
|
end
|
|
114
121
|
|
|
115
|
-
# Convert simple format to
|
|
122
|
+
# Convert simple format to robot_lab nested transport format
|
|
116
123
|
#
|
|
117
124
|
# @param parsed [Hash] parsed JSON with type and command
|
|
118
125
|
# @param file_path [String] file path for deriving server name
|
|
@@ -121,28 +128,22 @@ module AIA
|
|
|
121
128
|
# Derive name from filename (e.g., "filesystem.json" -> "filesystem")
|
|
122
129
|
name = File.basename(file_path, '.*')
|
|
123
130
|
|
|
124
|
-
|
|
131
|
+
transport = { type: parsed['type'] || 'stdio' }
|
|
125
132
|
|
|
126
|
-
|
|
133
|
+
command = parsed['command']
|
|
134
|
+
if command.is_a?(Array)
|
|
127
135
|
# Command is an array: first element is command, rest are args
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
elsif
|
|
131
|
-
|
|
132
|
-
|
|
136
|
+
transport[:command] = command.first
|
|
137
|
+
transport[:args] = command[1..] || []
|
|
138
|
+
elsif command
|
|
139
|
+
transport[:command] = command
|
|
140
|
+
transport[:args] = parsed['args'] || []
|
|
133
141
|
end
|
|
134
142
|
|
|
135
|
-
if parsed['env']
|
|
136
|
-
server[:env] = parsed['env']
|
|
137
|
-
end
|
|
143
|
+
transport[:env] = parsed['env'] if parsed['env']
|
|
138
144
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
end
|
|
142
|
-
|
|
143
|
-
if parsed['type']
|
|
144
|
-
server[:type] = parsed['type']
|
|
145
|
-
end
|
|
145
|
+
server = { name: name, transport: transport }
|
|
146
|
+
server[:timeout] = parsed['timeout'].to_i if parsed['timeout']
|
|
146
147
|
|
|
147
148
|
[server]
|
|
148
149
|
end
|
|
@@ -13,7 +13,15 @@
|
|
|
13
13
|
|
|
14
14
|
module AIA
|
|
15
15
|
class ModelSpec
|
|
16
|
-
attr_accessor :name, :role, :instance, :internal_id
|
|
16
|
+
attr_accessor :name, :role, :instance, :internal_id, :provider
|
|
17
|
+
|
|
18
|
+
# Provider prefixes that map to RubyLLM provider slugs.
|
|
19
|
+
# 'lms' is stored as-is; RobotFactory maps it to the openai provider
|
|
20
|
+
# with a custom API base so it doesn't conflict with real OpenAI models.
|
|
21
|
+
PROVIDER_ALIASES = {
|
|
22
|
+
'ollama' => 'ollama',
|
|
23
|
+
'lms' => 'lms'
|
|
24
|
+
}.freeze
|
|
17
25
|
|
|
18
26
|
def initialize(hash = {})
|
|
19
27
|
hash = hash.transform_keys(&:to_sym) if hash.respond_to?(:transform_keys)
|
|
@@ -22,6 +30,10 @@ module AIA
|
|
|
22
30
|
@role = hash[:role]
|
|
23
31
|
@instance = hash[:instance] || 1
|
|
24
32
|
@internal_id = hash[:internal_id] || @name
|
|
33
|
+
@provider = hash[:provider]
|
|
34
|
+
|
|
35
|
+
# Extract provider from name if prefixed (e.g., "ollama/llama3" or "lms/my-model")
|
|
36
|
+
extract_provider_from_name! unless @provider
|
|
25
37
|
end
|
|
26
38
|
|
|
27
39
|
def to_h
|
|
@@ -29,7 +41,8 @@ module AIA
|
|
|
29
41
|
name: @name,
|
|
30
42
|
role: @role,
|
|
31
43
|
instance: @instance,
|
|
32
|
-
internal_id: @internal_id
|
|
44
|
+
internal_id: @internal_id,
|
|
45
|
+
provider: @provider
|
|
33
46
|
}
|
|
34
47
|
end
|
|
35
48
|
|
|
@@ -63,5 +76,24 @@ module AIA
|
|
|
63
76
|
def duplicate?
|
|
64
77
|
@instance > 1
|
|
65
78
|
end
|
|
79
|
+
|
|
80
|
+
# Check if this model uses a local provider
|
|
81
|
+
def local_provider?
|
|
82
|
+
!@provider.nil?
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
private
|
|
86
|
+
|
|
87
|
+
# Extract provider prefix from model name.
|
|
88
|
+
# "ollama/llama3:latest" => provider: "ollama", name: "llama3:latest"
|
|
89
|
+
# "lms/my-model" => provider: "openai", name: "my-model"
|
|
90
|
+
def extract_provider_from_name!
|
|
91
|
+
return unless @name&.include?('/')
|
|
92
|
+
|
|
93
|
+
prefix, rest = @name.split('/', 2)
|
|
94
|
+
return unless PROVIDER_ALIASES.key?(prefix)
|
|
95
|
+
@provider = PROVIDER_ALIASES[prefix]
|
|
96
|
+
@name = rest
|
|
97
|
+
end
|
|
66
98
|
end
|
|
67
99
|
end
|