aia 1.1.1 → 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.
Files changed (169) hide show
  1. checksums.yaml +4 -4
  2. data/.envrc +5 -1
  3. data/.loki +231 -0
  4. data/.quality/flay_baseline.txt +1 -0
  5. data/.quality/flog_baseline.txt +29 -0
  6. data/.quality/reek_baseline.txt +80 -0
  7. data/.rubocop.yml +116 -0
  8. data/.version +1 -1
  9. data/CHANGELOG.md +259 -50
  10. data/IMPLEMENTATION_PLAN.md +506 -0
  11. data/README.md +266 -238
  12. data/Rakefile +118 -5
  13. data/architecture_review.md +314 -0
  14. data/bin/aia +16 -0
  15. data/docs/AGENTS.md +40 -0
  16. data/docs/advanced-prompting.md +67 -3
  17. data/docs/cli-reference.md +312 -56
  18. data/docs/configuration.md +130 -19
  19. data/docs/contributing.md +56 -2
  20. data/docs/directives-reference.md +593 -78
  21. data/docs/faq.md +85 -3
  22. data/docs/guides/available-models.md +1 -1
  23. data/docs/guides/basic-usage.md +6 -6
  24. data/docs/guides/chat.md +40 -16
  25. data/docs/guides/crew.md +239 -0
  26. data/docs/guides/executable-prompts.md +1 -1
  27. data/docs/guides/index.md +1 -0
  28. data/docs/guides/models.md +15 -0
  29. data/docs/index.md +29 -2
  30. data/docs/installation.md +44 -17
  31. data/docs/mcp-integration.md +40 -0
  32. data/docs/prompt_management.md +85 -86
  33. data/docs/security.md +47 -0
  34. data/docs/special_projects_guide.md +386 -0
  35. data/docs/tools-and-mcp-examples.md +23 -0
  36. data/docs/workflows-and-pipelines.md +84 -7
  37. data/examples/.gitignore +1 -0
  38. data/examples/00_setup_aia.sh +27 -44
  39. data/examples/11_multi_model.sh +4 -14
  40. data/examples/12_token_usage.sh +3 -12
  41. data/examples/18_tools.sh +10 -2
  42. data/examples/22_chat_mode.sh +0 -10
  43. data/examples/23_verify.sh +139 -0
  44. data/examples/24_decompose.sh +139 -0
  45. data/examples/25_spawn.sh +139 -0
  46. data/examples/26_debate.sh +97 -0
  47. data/examples/27_mention_routing.sh +157 -0
  48. data/examples/28_model_switching.sh +106 -0
  49. data/examples/29_agent_harness.sh +177 -0
  50. data/examples/README.md +65 -0
  51. data/examples/advanced_multi_robot_capabilities_without_examples.md +106 -0
  52. data/examples/aia_config.yml +1 -1
  53. data/examples/aia_config_orchestrator.yml +45 -0
  54. data/examples/common.sh +18 -6
  55. data/examples/context/tech_stack.md +2 -2
  56. data/examples/prompts_dir/roles/orchestrator.md +21 -0
  57. data/examples/requirements/sinatra_taskflow_app.md +139 -0
  58. data/examples/rules/01_classify_ruby.rb +16 -0
  59. data/examples/rules/02_prefer_claude_for_code.rb +19 -0
  60. data/examples/rules/03_gate_prompt_length.rb +19 -0
  61. data/examples/rules/04_tool_selection.rb +41 -0
  62. data/examples/rules/README.md +30 -0
  63. data/examples/run_all.sh +48 -15
  64. data/examples/tools/word_count_tool.rb +1 -1
  65. data/lib/AGENTS.md +57 -0
  66. data/lib/aia/chat_loop.rb +304 -164
  67. data/lib/aia/config/cli_parser.rb +174 -111
  68. data/lib/aia/config/defaults.yml +62 -33
  69. data/lib/aia/config/mcp_parser.rb +39 -46
  70. data/lib/aia/config/model_spec.rb +34 -2
  71. data/lib/aia/config/validator.rb +108 -142
  72. data/lib/aia/config.rb +110 -145
  73. data/lib/aia/content_extractor.rb +153 -0
  74. data/lib/aia/cost_calculator.rb +38 -0
  75. data/lib/aia/crew.rb +164 -0
  76. data/lib/aia/debate_handler.rb +166 -0
  77. data/lib/aia/delegate_handler.rb +112 -0
  78. data/lib/aia/directive.rb +33 -18
  79. data/lib/aia/directive_processor.rb +16 -7
  80. data/lib/aia/directives/configuration_directives.rb +160 -20
  81. data/lib/aia/directives/context_directives.rb +38 -26
  82. data/lib/aia/directives/execution_directives.rb +136 -4
  83. data/lib/aia/directives/model_directives.rb +76 -34
  84. data/lib/aia/directives/trakflow_directives.rb +44 -0
  85. data/lib/aia/directives/utility_directives.rb +203 -6
  86. data/lib/aia/directives/web_and_file_directives.rb +96 -60
  87. data/lib/aia/errors.rb +15 -0
  88. data/lib/aia/fact_asserter.rb +27 -0
  89. data/lib/aia/fzf.rb +9 -31
  90. data/lib/aia/handler_context.rb +17 -0
  91. data/lib/aia/handler_protocol.rb +19 -0
  92. data/lib/aia/history_transfer.rb +55 -0
  93. data/lib/aia/input_collector.rb +3 -3
  94. data/lib/aia/layered_orchestrator.rb +448 -0
  95. data/lib/aia/logger.rb +24 -4
  96. data/lib/aia/mcp_config_normalizer.rb +35 -0
  97. data/lib/aia/mcp_connection_manager.rb +305 -0
  98. data/lib/aia/mcp_discovery.rb +44 -0
  99. data/lib/aia/mcp_grouper.rb +33 -0
  100. data/lib/aia/mcp_utility.rb +57 -0
  101. data/lib/aia/mention_router.rb +260 -0
  102. data/lib/aia/model_alias_registry.rb +97 -0
  103. data/lib/aia/model_switch_handler.rb +100 -0
  104. data/lib/aia/network_builder.rb +155 -0
  105. data/lib/aia/network_memory_manager.rb +55 -0
  106. data/lib/aia/patches/ruby_llm_streaming_error.rb +43 -0
  107. data/lib/aia/patches/ruby_llm_tool_error.rb +96 -0
  108. data/lib/aia/pipeline_orchestrator.rb +262 -0
  109. data/lib/aia/plugin_loader.rb +170 -0
  110. data/lib/aia/plugin_monitor.rb +208 -0
  111. data/lib/aia/prompt_decomposer.rb +157 -0
  112. data/lib/aia/prompt_handler.rb +19 -39
  113. data/lib/aia/robot_builder.rb +51 -0
  114. data/lib/aia/robot_factory.rb +334 -0
  115. data/lib/aia/robot_namer.rb +116 -0
  116. data/lib/aia/session.rb +83 -17
  117. data/lib/aia/session_tracker.rb +209 -0
  118. data/lib/aia/similarity_scorer.rb +39 -0
  119. data/lib/aia/skill_utils.rb +105 -1
  120. data/lib/aia/spawn_handler.rb +129 -0
  121. data/lib/aia/spawn_spec_parser.rb +65 -0
  122. data/lib/aia/special_mode_handler.rb +302 -0
  123. data/lib/aia/startup_coordinator.rb +150 -0
  124. data/lib/aia/streaming_runner.rb +169 -0
  125. data/lib/aia/system_prompt_assembler.rb +88 -0
  126. data/lib/aia/task_coordinator.rb +202 -0
  127. data/lib/aia/task_decomposer.rb +57 -0
  128. data/lib/aia/task_executor.rb +51 -0
  129. data/lib/aia/tfidf_math.rb +27 -0
  130. data/lib/aia/tool_filter/tfidf.rb +116 -0
  131. data/lib/aia/tool_filter/wordnet_expander.rb +127 -0
  132. data/lib/aia/tool_filter.rb +82 -0
  133. data/lib/aia/tool_filter_registry.rb +30 -0
  134. data/lib/aia/tool_filter_strategy.rb +143 -0
  135. data/lib/aia/tool_loader.rb +210 -0
  136. data/lib/aia/tool_utility.rb +30 -0
  137. data/lib/aia/tools/delegate_to_foreman_tool.rb +70 -0
  138. data/lib/aia/tools/recruit_robot_tool.rb +60 -0
  139. data/lib/aia/tools/reskill_robot_tool.rb +44 -0
  140. data/lib/aia/tools/task_board_tool.rb +114 -0
  141. data/lib/aia/trakflow_bridge.rb +173 -0
  142. data/lib/aia/turn_state.rb +94 -0
  143. data/lib/aia/ui_presenter.rb +166 -198
  144. data/lib/aia/utility.rb +134 -87
  145. data/lib/aia/{history_manager.rb → variable_input_collector.rb} +8 -9
  146. data/lib/aia/verification_network.rb +58 -0
  147. data/lib/aia.rb +108 -63
  148. data/mkdocs.yml +1 -0
  149. metadata +179 -56
  150. data/justfile +0 -215
  151. data/lib/aia/adapter/chat_execution.rb +0 -242
  152. data/lib/aia/adapter/error_handler.rb +0 -68
  153. data/lib/aia/adapter/gem_activator.rb +0 -57
  154. data/lib/aia/adapter/mcp_connector.rb +0 -274
  155. data/lib/aia/adapter/modality_handlers.rb +0 -167
  156. data/lib/aia/adapter/model_registry.rb +0 -81
  157. data/lib/aia/adapter/multi_model_chat.rb +0 -218
  158. data/lib/aia/adapter/provider_configurator.rb +0 -59
  159. data/lib/aia/adapter/tool_filter.rb +0 -85
  160. data/lib/aia/adapter/tool_loader.rb +0 -90
  161. data/lib/aia/chat_processor_service.rb +0 -178
  162. data/lib/aia/prompt_pipeline.rb +0 -183
  163. data/lib/aia/ruby_llm_adapter.rb +0 -95
  164. data/lib/extensions/openstruct_merge.rb +0 -48
  165. data/lib/extensions/ruby_llm/.irbrc +0 -56
  166. data/lib/extensions/ruby_llm/modalities.rb +0 -36
  167. data/lib/extensions/ruby_llm/provider_fix.rb +0 -79
  168. data/lib/refinements/string.rb +0 -16
  169. data/main.just +0 -76
@@ -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 AIA's config system.
6
+ # to the nested transport format expected by robot_lab.
7
7
  #
8
- # Supports two JSON formats:
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,10 @@ 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
37
48
  def parse_files(file_paths)
38
49
  return [] if file_paths.nil? || file_paths.empty?
39
50
 
@@ -43,7 +54,7 @@ module AIA
43
54
  expanded_path = File.expand_path(file_path)
44
55
 
45
56
  unless File.exist?(expanded_path)
46
- warn "Warning: MCP config file not found: #{file_path}"
57
+ $stderr.puts "Warning: MCP config file not found: #{file_path}"
47
58
  next
48
59
  end
49
60
 
@@ -52,9 +63,9 @@ module AIA
52
63
  parsed = JSON.parse(json_content)
53
64
  servers.concat(convert_to_config_format(parsed, file_path))
54
65
  rescue JSON::ParserError => e
55
- warn "Warning: Invalid JSON in MCP config file '#{file_path}': #{e.message}"
66
+ $stderr.puts "Warning: Invalid JSON in MCP config file '#{file_path}': #{e.message}"
56
67
  rescue StandardError => e
57
- warn "Warning: Error reading MCP config file '#{file_path}': #{e.message}"
68
+ $stderr.puts "Warning: Error reading MCP config file '#{file_path}': #{e.message}"
58
69
  end
59
70
  end
60
71
 
@@ -76,43 +87,32 @@ module AIA
76
87
  end
77
88
  end
78
89
 
79
- # Convert mcpServers format to config format
90
+ # Convert mcpServers format to robot_lab nested transport format
80
91
  #
81
92
  # @param mcp_servers [Hash] the mcpServers hash from JSON
82
93
  # @return [Array<Hash>] array of server configurations
83
94
  def convert_mcp_servers_format(mcp_servers)
84
95
  mcp_servers.map do |name, config|
85
- server = { name: name }
86
-
87
- if config['command']
88
- server[:command] = config['command']
89
- end
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
96
+ transport = { type: config['type'] || 'stdio' }
97
+ transport[:command] = config['command'] if config['command']
98
+ transport[:args] = Array(config['args']) if config['args']
99
+ transport[:env] = config['env'] if config['env']
100
+ transport[:url] = config['url'] if config['url']
101
+ transport[:headers] = config['headers'] if config['headers']
98
102
 
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
103
+ server = { name: name, transport: transport }
104
+ server[:timeout] = config['timeout'].to_i if config['timeout']
106
105
 
107
- if config['headers']
108
- server[:headers] = config['headers']
109
- end
106
+ # Preserve routing metadata for KBS/AIA
107
+ server[:topics] = Array(config['topics']) if config['topics']
108
+ server[:independent] = config['independent'] unless config['independent'].nil?
109
+ server[:group] = config['group'] if config['group']
110
110
 
111
111
  server
112
112
  end
113
113
  end
114
114
 
115
- # Convert simple format to config format
115
+ # Convert simple format to robot_lab nested transport format
116
116
  #
117
117
  # @param parsed [Hash] parsed JSON with type and command
118
118
  # @param file_path [String] file path for deriving server name
@@ -121,28 +121,21 @@ module AIA
121
121
  # Derive name from filename (e.g., "filesystem.json" -> "filesystem")
122
122
  name = File.basename(file_path, '.*')
123
123
 
124
- server = { name: name }
124
+ transport = { type: parsed['type'] || 'stdio' }
125
125
 
126
126
  if parsed['command'].is_a?(Array)
127
127
  # Command is an array: first element is command, rest are args
128
- server[:command] = parsed['command'].first
129
- server[:args] = parsed['command'][1..] || []
128
+ transport[:command] = parsed['command'].first
129
+ transport[:args] = parsed['command'][1..] || []
130
130
  elsif parsed['command']
131
- server[:command] = parsed['command']
132
- server[:args] = parsed['args'] || []
131
+ transport[:command] = parsed['command']
132
+ transport[:args] = parsed['args'] || []
133
133
  end
134
134
 
135
- if parsed['env']
136
- server[:env] = parsed['env']
137
- end
138
-
139
- if parsed['timeout']
140
- server[:timeout] = parsed['timeout'].to_i
141
- end
135
+ transport[:env] = parsed['env'] if parsed['env']
142
136
 
143
- if parsed['type']
144
- server[:type] = parsed['type']
145
- end
137
+ server = { name: name, transport: transport }
138
+ server[:timeout] = parsed['timeout'].to_i if parsed['timeout']
146
139
 
147
140
  [server]
148
141
  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