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.
Files changed (175) hide show
  1. checksums.yaml +4 -4
  2. data/.envrc +9 -1
  3. data/.loki +11 -0
  4. data/.reek.yml +160 -0
  5. data/.rubocop.yml +116 -0
  6. data/.rubocop_strict.yml +15 -0
  7. data/.version +1 -1
  8. data/CHANGELOG.md +269 -55
  9. data/IMPLEMENTATION_PLAN.md +506 -0
  10. data/README.md +267 -239
  11. data/Rakefile +5 -5
  12. data/_typos.toml +10 -0
  13. data/aia.gemspec +92 -0
  14. data/architecture_review.md +314 -0
  15. data/bin/aia +16 -0
  16. data/config/aia.yml +13 -0
  17. data/docs/AGENTS.md +40 -0
  18. data/docs/advanced-prompting.md +67 -3
  19. data/docs/cli-reference.md +312 -56
  20. data/docs/configuration.md +130 -19
  21. data/docs/contributing.md +56 -2
  22. data/docs/directives-reference.md +593 -78
  23. data/docs/faq.md +85 -3
  24. data/docs/guides/available-models.md +1 -1
  25. data/docs/guides/basic-usage.md +6 -6
  26. data/docs/guides/chat.md +40 -16
  27. data/docs/guides/crew.md +239 -0
  28. data/docs/guides/executable-prompts.md +1 -1
  29. data/docs/guides/index.md +1 -0
  30. data/docs/guides/models.md +15 -0
  31. data/docs/index.md +29 -2
  32. data/docs/installation.md +44 -17
  33. data/docs/mcp-integration.md +40 -0
  34. data/docs/prompt_management.md +85 -86
  35. data/docs/security.md +47 -0
  36. data/docs/special_projects_guide.md +386 -0
  37. data/docs/tools-and-mcp-examples.md +23 -0
  38. data/docs/workflows-and-pipelines.md +84 -7
  39. data/examples/.gitignore +1 -0
  40. data/examples/00_setup_aia.sh +27 -44
  41. data/examples/11_multi_model.sh +4 -14
  42. data/examples/12_token_usage.sh +3 -12
  43. data/examples/18_tools.sh +10 -2
  44. data/examples/22_chat_mode.sh +0 -10
  45. data/examples/23_verify.sh +139 -0
  46. data/examples/24_decompose.sh +139 -0
  47. data/examples/25_spawn.sh +139 -0
  48. data/examples/26_debate.sh +97 -0
  49. data/examples/27_mention_routing.sh +157 -0
  50. data/examples/28_model_switching.sh +106 -0
  51. data/examples/29_agent_harness.sh +177 -0
  52. data/examples/README.md +65 -0
  53. data/examples/advanced_multi_robot_capabilities_without_examples.md +106 -0
  54. data/examples/aia_config.yml +1 -1
  55. data/examples/aia_config_orchestrator.yml +45 -0
  56. data/examples/common.sh +18 -6
  57. data/examples/context/tech_stack.md +2 -2
  58. data/examples/prompts_dir/roles/orchestrator.md +21 -0
  59. data/examples/requirements/sinatra_taskflow_app.md +139 -0
  60. data/examples/rules/01_classify_ruby.rb +16 -0
  61. data/examples/rules/02_prefer_claude_for_code.rb +19 -0
  62. data/examples/rules/03_gate_prompt_length.rb +19 -0
  63. data/examples/rules/04_tool_selection.rb +41 -0
  64. data/examples/rules/README.md +30 -0
  65. data/examples/run_all.sh +48 -15
  66. data/examples/tools/word_count_tool.rb +1 -1
  67. data/lib/AGENTS.md +57 -0
  68. data/lib/aia/chat_loop.rb +263 -167
  69. data/lib/aia/config/cli_parser.rb +217 -145
  70. data/lib/aia/config/defaults.yml +62 -33
  71. data/lib/aia/config/mcp_parser.rb +52 -51
  72. data/lib/aia/config/model_spec.rb +34 -2
  73. data/lib/aia/config/validator.rb +171 -216
  74. data/lib/aia/config.rb +111 -145
  75. data/lib/aia/content_extractor.rb +155 -0
  76. data/lib/aia/cost_calculator.rb +39 -0
  77. data/lib/aia/crew.rb +164 -0
  78. data/lib/aia/debate_handler.rb +174 -0
  79. data/lib/aia/delegate_handler.rb +116 -0
  80. data/lib/aia/directive.rb +43 -26
  81. data/lib/aia/directive_processor.rb +16 -7
  82. data/lib/aia/directives/configuration_directives.rb +214 -60
  83. data/lib/aia/directives/context_directives.rb +67 -52
  84. data/lib/aia/directives/execution_directives.rb +141 -4
  85. data/lib/aia/directives/model_directives.rb +163 -141
  86. data/lib/aia/directives/trakflow_directives.rb +62 -0
  87. data/lib/aia/directives/utility_directives.rb +227 -30
  88. data/lib/aia/directives/web_and_file_directives.rb +126 -77
  89. data/lib/aia/errors.rb +15 -0
  90. data/lib/aia/fact_asserter.rb +27 -0
  91. data/lib/aia/fzf.rb +9 -31
  92. data/lib/aia/handler_context.rb +17 -0
  93. data/lib/aia/handler_protocol.rb +19 -0
  94. data/lib/aia/history_transfer.rb +55 -0
  95. data/lib/aia/input_collector.rb +3 -3
  96. data/lib/aia/layered_orchestrator.rb +471 -0
  97. data/lib/aia/logger.rb +45 -25
  98. data/lib/aia/mcp_config_normalizer.rb +35 -0
  99. data/lib/aia/mcp_connection_manager.rb +315 -0
  100. data/lib/aia/mcp_discovery.rb +44 -0
  101. data/lib/aia/mcp_grouper.rb +33 -0
  102. data/lib/aia/mcp_server_config.rb +30 -0
  103. data/lib/aia/mcp_utility.rb +60 -0
  104. data/lib/aia/mention_router.rb +217 -0
  105. data/lib/aia/model_alias_registry.rb +97 -0
  106. data/lib/aia/model_switch_handler.rb +100 -0
  107. data/lib/aia/network_builder.rb +160 -0
  108. data/lib/aia/network_memory_manager.rb +55 -0
  109. data/lib/aia/patches/ruby_llm_streaming_error.rb +43 -0
  110. data/lib/aia/patches/ruby_llm_tool_error.rb +96 -0
  111. data/lib/aia/pipeline_orchestrator.rb +272 -0
  112. data/lib/aia/plugin_loader.rb +170 -0
  113. data/lib/aia/plugin_monitor.rb +211 -0
  114. data/lib/aia/prompt_decomposer.rb +159 -0
  115. data/lib/aia/prompt_handler.rb +56 -82
  116. data/lib/aia/robot_builder.rb +51 -0
  117. data/lib/aia/robot_factory.rb +338 -0
  118. data/lib/aia/robot_namer.rb +110 -0
  119. data/lib/aia/session.rb +87 -17
  120. data/lib/aia/session_tracker.rb +207 -0
  121. data/lib/aia/similarity_scorer.rb +41 -0
  122. data/lib/aia/skill_utils.rb +105 -1
  123. data/lib/aia/spawn_handler.rb +129 -0
  124. data/lib/aia/spawn_spec_parser.rb +65 -0
  125. data/lib/aia/special_mode_handler.rb +322 -0
  126. data/lib/aia/speech.rb +67 -0
  127. data/lib/aia/startup_coordinator.rb +151 -0
  128. data/lib/aia/streaming_runner.rb +172 -0
  129. data/lib/aia/system_prompt_assembler.rb +92 -0
  130. data/lib/aia/task_coordinator.rb +207 -0
  131. data/lib/aia/task_decomposer.rb +57 -0
  132. data/lib/aia/task_executor.rb +51 -0
  133. data/lib/aia/tfidf_math.rb +27 -0
  134. data/lib/aia/timing.rb +15 -0
  135. data/lib/aia/tool_filter/tfidf.rb +116 -0
  136. data/lib/aia/tool_filter/wordnet_expander.rb +127 -0
  137. data/lib/aia/tool_filter.rb +83 -0
  138. data/lib/aia/tool_filter_registry.rb +30 -0
  139. data/lib/aia/tool_filter_strategy.rb +146 -0
  140. data/lib/aia/tool_introspection.rb +17 -0
  141. data/lib/aia/tool_loader.rb +216 -0
  142. data/lib/aia/tool_utility.rb +30 -0
  143. data/lib/aia/tools/delegate_to_foreman_tool.rb +70 -0
  144. data/lib/aia/tools/recruit_robot_tool.rb +60 -0
  145. data/lib/aia/tools/reskill_robot_tool.rb +44 -0
  146. data/lib/aia/tools/task_board_tool.rb +115 -0
  147. data/lib/aia/trakflow_bridge.rb +175 -0
  148. data/lib/aia/turn_state.rb +95 -0
  149. data/lib/aia/ui_presenter.rb +182 -206
  150. data/lib/aia/utility.rb +136 -87
  151. data/lib/aia/{history_manager.rb → variable_input_collector.rb} +9 -9
  152. data/lib/aia/verification_network.rb +57 -0
  153. data/lib/aia.rb +124 -63
  154. data/mkdocs.yml +1 -0
  155. metadata +187 -58
  156. data/justfile +0 -215
  157. data/lib/aia/adapter/chat_execution.rb +0 -242
  158. data/lib/aia/adapter/error_handler.rb +0 -68
  159. data/lib/aia/adapter/gem_activator.rb +0 -57
  160. data/lib/aia/adapter/mcp_connector.rb +0 -274
  161. data/lib/aia/adapter/modality_handlers.rb +0 -167
  162. data/lib/aia/adapter/model_registry.rb +0 -81
  163. data/lib/aia/adapter/multi_model_chat.rb +0 -218
  164. data/lib/aia/adapter/provider_configurator.rb +0 -59
  165. data/lib/aia/adapter/tool_filter.rb +0 -85
  166. data/lib/aia/adapter/tool_loader.rb +0 -90
  167. data/lib/aia/chat_processor_service.rb +0 -178
  168. data/lib/aia/prompt_pipeline.rb +0 -183
  169. data/lib/aia/ruby_llm_adapter.rb +0 -95
  170. data/lib/extensions/openstruct_merge.rb +0 -48
  171. data/lib/extensions/ruby_llm/.irbrc +0 -56
  172. data/lib/extensions/ruby_llm/modalities.rb +0 -36
  173. data/lib/extensions/ruby_llm/provider_fix.rb +0 -79
  174. data/lib/refinements/string.rb +0 -16
  175. data/main.just +0 -76
@@ -0,0 +1,175 @@
1
+ # frozen_string_literal: true
2
+
3
+ # lib/aia/trakflow_bridge.rb
4
+ #
5
+ # Bridge between AIA and TrakFlow task tracking.
6
+ # Uses the trak_flow gem directly as a Ruby library —
7
+ # no MCP server or LLM intermediation needed.
8
+
9
+ require "trak_flow"
10
+
11
+ module AIA
12
+ class TrakFlowBridge
13
+ def initialize
14
+ @db = connect_database
15
+ end
16
+
17
+ # Whether a TrakFlow project is initialized and the database is accessible.
18
+ #
19
+ # @return [Boolean]
20
+ def available?
21
+ !@db.nil?
22
+ end
23
+
24
+ # Create a TrakFlow plan from a pipeline of prompt IDs.
25
+ # Each step blocks the next, enforcing sequential execution.
26
+ #
27
+ # @param pipeline [Array<String>] prompt IDs in pipeline order
28
+ # @return [String, nil] summary of created plan
29
+ # :reek:TooManyStatements -- plan build: one child task per pipeline step, chained by blocking dependencies
30
+ def create_plan_from_pipeline(pipeline)
31
+ return nil unless available?
32
+
33
+ plan_title = "Pipeline: #{pipeline.join(' → ')}"
34
+ plan = TrakFlow::Models::Task.new(title: plan_title, plan: true, type: "task")
35
+ plan = @db.create_task(plan)
36
+
37
+ prev_step = nil
38
+ pipeline.each_with_index do |prompt_id, i|
39
+ step = @db.create_child_task(plan.id, {
40
+ title: "Step #{i + 1}: #{prompt_id}",
41
+ type: "task"
42
+ })
43
+
44
+ if prev_step
45
+ @db.add_dependency(TrakFlow::Models::Dependency.new(
46
+ source_id: prev_step.id,
47
+ target_id: step.id,
48
+ type: "blocks"
49
+ ))
50
+ end
51
+
52
+ prev_step = step
53
+ end
54
+
55
+ "Plan '#{plan_title}' created with #{pipeline.size} steps."
56
+ rescue StandardError => e
57
+ $stderr.puts "Warning: TrakFlow plan creation failed: #{e.message}"
58
+ nil
59
+ end
60
+
61
+ # Update a task's status in TrakFlow.
62
+ #
63
+ # @param step_name [String] task title to find
64
+ # @param status [Symbol] :started, :completed, or :failed
65
+ # @param reason [String, nil] reason for failure
66
+ def update_step_status(step_name, status, reason: nil)
67
+ return unless available?
68
+
69
+ task = find_task_by_title(step_name)
70
+ return unless task
71
+
72
+ case status
73
+ when :started
74
+ task.status = "in_progress"
75
+ when :completed
76
+ task.close!(reason: reason || "Completed")
77
+ when :failed
78
+ task.status = "blocked"
79
+ task.append_trace("blocked", reason) if reason
80
+ else
81
+ return
82
+ end
83
+
84
+ @db.update_task(task)
85
+ rescue StandardError => e
86
+ $stderr.puts "Warning: TrakFlow status update failed: #{e.message}"
87
+ end
88
+
89
+ # List ready tasks (tasks with no open blockers).
90
+ #
91
+ # @return [String, nil] formatted list of ready tasks
92
+ def check_ready_tasks
93
+ return nil unless available?
94
+
95
+ tasks = @db.ready_tasks
96
+ return nil if tasks.empty?
97
+
98
+ lines = tasks.map { |t| " - [#{t.id}] #{t.title} (#{t.status})" }
99
+ "Ready tasks (#{tasks.size}):\n#{lines.join("\n")}"
100
+ rescue StandardError => e
101
+ $stderr.puts "Warning: TrakFlow ready tasks query failed: #{e.message}"
102
+ nil
103
+ end
104
+
105
+ # Get a summary of the current TrakFlow project state.
106
+ #
107
+ # @return [String, nil] project summary
108
+ def project_summary
109
+ return nil unless available?
110
+
111
+ all = @db.list_tasks({})
112
+ by_status = all.group_by(&:status)
113
+
114
+ lines = ["TrakFlow Project Summary (#{all.size} tasks):"]
115
+ by_status.sort.each do |status, tasks|
116
+ lines << " #{status}: #{tasks.size}"
117
+ end
118
+
119
+ ready = @db.ready_tasks
120
+ lines << " ready (unblocked): #{ready.size}" unless ready.empty?
121
+
122
+ lines.join("\n")
123
+ rescue StandardError => e
124
+ $stderr.puts "Warning: TrakFlow summary failed: #{e.message}"
125
+ nil
126
+ end
127
+
128
+ # Create a task in TrakFlow.
129
+ #
130
+ # @param title [String] task title
131
+ # @param description [String, nil] task description
132
+ # @param labels [Array<String>] labels to attach
133
+ # @return [String, nil] confirmation message
134
+ def create_task(title, description: nil, labels: [])
135
+ return nil unless available?
136
+
137
+ task = TrakFlow::Models::Task.new(
138
+ title: title,
139
+ description: description,
140
+ type: "task"
141
+ )
142
+ task = @db.create_task(task)
143
+
144
+ labels.each do |label_name|
145
+ @db.add_label(TrakFlow::Models::Label.new(task_id: task.id, name: label_name))
146
+ end
147
+
148
+ "Task created: [#{task.id}] #{title}"
149
+ rescue StandardError => e
150
+ $stderr.puts "Warning: TrakFlow task creation failed: #{e.message}"
151
+ nil
152
+ end
153
+
154
+ attr_reader :db
155
+
156
+ private
157
+
158
+ # Connect to the TrakFlow database if a project is initialized.
159
+ def connect_database
160
+ return nil unless TrakFlow.initialized?
161
+
162
+ db = TrakFlow::Storage::Database.new(TrakFlow.database_path)
163
+ db.connect
164
+ db
165
+ rescue StandardError
166
+ nil
167
+ end
168
+
169
+ # Find a task by its title (partial match).
170
+ def find_task_by_title(title)
171
+ tasks = @db.list_tasks(title: title)
172
+ tasks.first
173
+ end
174
+ end
175
+ end
@@ -0,0 +1,95 @@
1
+ # frozen_string_literal: true
2
+
3
+ # lib/aia/turn_state.rb
4
+ #
5
+ # Request-scoped state object for inter-component signaling.
6
+ # Replaces ad-hoc instance variable flags on AIA.config.
7
+ #
8
+ # Only one special mode may be requested per turn (mutual exclusion).
9
+ # Use TurnState#request(mode, **opts) to enqueue a mode — this clears
10
+ # all other force_* flags before setting the new one. Assigning the
11
+ # attr_accessors directly bypasses mutual exclusion (for backward compat
12
+ # and direct test assertions).
13
+
14
+ module AIA
15
+ # :reek:TooManyInstanceVariables -- one boolean flag per exclusive mode plus spawn/mcp details; a Hash would lose the attr_accessor API
16
+ class TurnState
17
+ # Exclusive mode flags — only one may be active at a time via #request.
18
+ EXCLUSIVE_MODES = %i[
19
+ verify decompose concurrent_mcp debate delegate spawn orchestrate
20
+ ].freeze
21
+
22
+ attr_accessor :force_verify, :force_decompose, :force_concurrent_mcp,
23
+ :force_debate, :force_delegate, :force_spawn, :spawn_type,
24
+ :spawn_spec, :force_orchestrate, :active_mcp_servers
25
+
26
+ def initialize
27
+ clear!
28
+ end
29
+
30
+ # Request a special mode for this turn.
31
+ # Clears all other exclusive force_* flags before activating the new mode,
32
+ # enforcing mutual exclusion at the point of enqueue.
33
+ #
34
+ # @param mode [Symbol] one of EXCLUSIVE_MODES
35
+ # @param type [String, nil] specialist type (only relevant for :spawn)
36
+ # @raise [ArgumentError] if mode is not one of EXCLUSIVE_MODES
37
+ def request(mode, type: nil)
38
+ unless EXCLUSIVE_MODES.include?(mode)
39
+ raise ArgumentError, "Unknown TurnState mode: #{mode.inspect}. Valid: #{EXCLUSIVE_MODES.join(', ')}"
40
+ end
41
+
42
+ clear_exclusive_flags!
43
+
44
+ case mode
45
+ when :verify then @force_verify = true
46
+ when :decompose then @force_decompose = true
47
+ when :concurrent_mcp then @force_concurrent_mcp = true
48
+ when :debate then @force_debate = true
49
+ when :delegate then @force_delegate = true
50
+ when :spawn then @force_spawn = true
51
+ @spawn_type = type
52
+ when :orchestrate then @force_orchestrate = true
53
+ end
54
+ end
55
+
56
+ def clear!
57
+ @force_verify = false
58
+ @force_decompose = false
59
+ @force_concurrent_mcp = false
60
+ @force_debate = false
61
+ @force_delegate = false
62
+ @force_spawn = false
63
+ @spawn_type = nil
64
+ @spawn_spec = nil
65
+ @force_orchestrate = false
66
+ @active_mcp_servers = nil
67
+ end
68
+
69
+ # Returns which exclusive mode is currently active, or nil if none.
70
+ def active_mode
71
+ return :verify if @force_verify
72
+ return :decompose if @force_decompose
73
+ return :concurrent_mcp if @force_concurrent_mcp
74
+ return :debate if @force_debate
75
+ return :delegate if @force_delegate
76
+ return :spawn if @force_spawn
77
+ return :orchestrate if @force_orchestrate
78
+ nil
79
+ end
80
+
81
+ private
82
+
83
+ def clear_exclusive_flags!
84
+ @force_verify = false
85
+ @force_decompose = false
86
+ @force_concurrent_mcp = false
87
+ @force_debate = false
88
+ @force_delegate = false
89
+ @force_spawn = false
90
+ @spawn_type = nil
91
+ @spawn_spec = nil
92
+ @force_orchestrate = false
93
+ end
94
+ end
95
+ end