agentic 0.1.0 → 0.2.0

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 (130) hide show
  1. checksums.yaml +4 -4
  2. data/.agentic.yml +2 -0
  3. data/.architecture/decisions/ArchitecturalFeatureBuilder.md +136 -0
  4. data/.architecture/decisions/ArchitectureConsiderations.md +200 -0
  5. data/.architecture/decisions/adr_001_observer_pattern_implementation.md +196 -0
  6. data/.architecture/decisions/adr_002_plan_orchestrator.md +320 -0
  7. data/.architecture/decisions/adr_003_plan_orchestrator_interface.md +179 -0
  8. data/.architecture/decisions/adrs/ADR-001-dependency-management.md +147 -0
  9. data/.architecture/decisions/adrs/ADR-002-system-boundaries.md +162 -0
  10. data/.architecture/decisions/adrs/ADR-003-content-safety.md +158 -0
  11. data/.architecture/decisions/adrs/ADR-004-agent-permissions.md +161 -0
  12. data/.architecture/decisions/adrs/ADR-005-adaptation-engine.md +127 -0
  13. data/.architecture/decisions/adrs/ADR-006-extension-system.md +273 -0
  14. data/.architecture/decisions/adrs/ADR-007-learning-system.md +156 -0
  15. data/.architecture/decisions/adrs/ADR-008-prompt-generation.md +325 -0
  16. data/.architecture/decisions/adrs/ADR-009-task-failure-handling.md +353 -0
  17. data/.architecture/decisions/adrs/ADR-010-task-input-handling.md +251 -0
  18. data/.architecture/decisions/adrs/ADR-011-task-observable-pattern.md +391 -0
  19. data/.architecture/decisions/adrs/ADR-012-task-output-handling.md +205 -0
  20. data/.architecture/decisions/adrs/ADR-013-architecture-alignment.md +211 -0
  21. data/.architecture/decisions/adrs/ADR-014-agent-capability-registry.md +80 -0
  22. data/.architecture/decisions/adrs/ADR-015-persistent-agent-store.md +100 -0
  23. data/.architecture/decisions/adrs/ADR-016-agent-assembly-engine.md +117 -0
  24. data/.architecture/decisions/adrs/ADR-017-streaming-observability.md +171 -0
  25. data/.architecture/decisions/capability_tools_distinction.md +150 -0
  26. data/.architecture/decisions/cli_command_structure.md +61 -0
  27. data/.architecture/implementation/agent_self_assembly_implementation.md +267 -0
  28. data/.architecture/implementation/agent_self_assembly_summary.md +138 -0
  29. data/.architecture/members.yml +187 -0
  30. data/.architecture/planning/self_implementation_exercise.md +295 -0
  31. data/.architecture/planning/session_compaction_rule.md +43 -0
  32. data/.architecture/planning/streaming_observability_feature.md +223 -0
  33. data/.architecture/principles.md +151 -0
  34. data/.architecture/recalibration/0-2-0.md +92 -0
  35. data/.architecture/recalibration/agent_self_assembly.md +238 -0
  36. data/.architecture/recalibration/cli_command_structure.md +91 -0
  37. data/.architecture/recalibration/implementation_roadmap_0-2-0.md +301 -0
  38. data/.architecture/recalibration/progress_tracking_0-2-0.md +114 -0
  39. data/.architecture/recalibration_process.md +127 -0
  40. data/.architecture/reviews/0-2-0.md +181 -0
  41. data/.architecture/reviews/cli_command_duplication.md +98 -0
  42. data/.architecture/templates/adr.md +105 -0
  43. data/.architecture/templates/implementation_roadmap.md +125 -0
  44. data/.architecture/templates/progress_tracking.md +89 -0
  45. data/.architecture/templates/recalibration_plan.md +70 -0
  46. data/.architecture/templates/version_comparison.md +124 -0
  47. data/.claude/settings.local.json +13 -0
  48. data/.claude-sessions/001-task-class-architecture-implementation.md +129 -0
  49. data/.claude-sessions/002-plan-orchestrator-interface-review.md +105 -0
  50. data/.claude-sessions/architecture-governance-implementation.md +37 -0
  51. data/.claude-sessions/architecture-review-session.md +27 -0
  52. data/ArchitecturalFeatureBuilder.md +136 -0
  53. data/ArchitectureConsiderations.md +229 -0
  54. data/CHANGELOG.md +57 -2
  55. data/CLAUDE.md +111 -0
  56. data/CONTRIBUTING.md +286 -0
  57. data/MAINTAINING.md +301 -0
  58. data/README.md +582 -28
  59. data/docs/agent_capabilities_api.md +259 -0
  60. data/docs/artifact_extension_points.md +757 -0
  61. data/docs/artifact_generation_architecture.md +323 -0
  62. data/docs/artifact_implementation_plan.md +596 -0
  63. data/docs/artifact_integration_points.md +345 -0
  64. data/docs/artifact_verification_strategies.md +581 -0
  65. data/docs/streaming_observability_architecture.md +510 -0
  66. data/exe/agentic +6 -1
  67. data/lefthook.yml +5 -0
  68. data/lib/agentic/adaptation_engine.rb +124 -0
  69. data/lib/agentic/agent.rb +181 -4
  70. data/lib/agentic/agent_assembly_engine.rb +442 -0
  71. data/lib/agentic/agent_capability_registry.rb +260 -0
  72. data/lib/agentic/agent_config.rb +63 -0
  73. data/lib/agentic/agent_specification.rb +46 -0
  74. data/lib/agentic/capabilities/examples.rb +530 -0
  75. data/lib/agentic/capabilities.rb +14 -0
  76. data/lib/agentic/capability_provider.rb +146 -0
  77. data/lib/agentic/capability_specification.rb +118 -0
  78. data/lib/agentic/cli/agent.rb +31 -0
  79. data/lib/agentic/cli/capabilities.rb +191 -0
  80. data/lib/agentic/cli/config.rb +134 -0
  81. data/lib/agentic/cli/execution_observer.rb +796 -0
  82. data/lib/agentic/cli.rb +1068 -0
  83. data/lib/agentic/default_agent_provider.rb +35 -0
  84. data/lib/agentic/errors/llm_error.rb +184 -0
  85. data/lib/agentic/execution_plan.rb +53 -0
  86. data/lib/agentic/execution_result.rb +91 -0
  87. data/lib/agentic/expected_answer_format.rb +46 -0
  88. data/lib/agentic/extension/domain_adapter.rb +109 -0
  89. data/lib/agentic/extension/plugin_manager.rb +163 -0
  90. data/lib/agentic/extension/protocol_handler.rb +116 -0
  91. data/lib/agentic/extension.rb +45 -0
  92. data/lib/agentic/factory_methods.rb +9 -1
  93. data/lib/agentic/generation_stats.rb +61 -0
  94. data/lib/agentic/learning/README.md +84 -0
  95. data/lib/agentic/learning/capability_optimizer.rb +613 -0
  96. data/lib/agentic/learning/execution_history_store.rb +251 -0
  97. data/lib/agentic/learning/pattern_recognizer.rb +500 -0
  98. data/lib/agentic/learning/strategy_optimizer.rb +706 -0
  99. data/lib/agentic/learning.rb +131 -0
  100. data/lib/agentic/llm_assisted_composition_strategy.rb +188 -0
  101. data/lib/agentic/llm_client.rb +215 -15
  102. data/lib/agentic/llm_config.rb +65 -1
  103. data/lib/agentic/llm_response.rb +163 -0
  104. data/lib/agentic/logger.rb +1 -1
  105. data/lib/agentic/observable.rb +51 -0
  106. data/lib/agentic/persistent_agent_store.rb +385 -0
  107. data/lib/agentic/plan_execution_result.rb +129 -0
  108. data/lib/agentic/plan_orchestrator.rb +464 -0
  109. data/lib/agentic/plan_orchestrator_config.rb +57 -0
  110. data/lib/agentic/retry_config.rb +63 -0
  111. data/lib/agentic/retry_handler.rb +125 -0
  112. data/lib/agentic/structured_outputs.rb +1 -1
  113. data/lib/agentic/task.rb +193 -0
  114. data/lib/agentic/task_definition.rb +39 -0
  115. data/lib/agentic/task_execution_result.rb +92 -0
  116. data/lib/agentic/task_failure.rb +66 -0
  117. data/lib/agentic/task_output_schemas.rb +112 -0
  118. data/lib/agentic/task_planner.rb +54 -19
  119. data/lib/agentic/task_result.rb +48 -0
  120. data/lib/agentic/ui.rb +244 -0
  121. data/lib/agentic/verification/critic_framework.rb +116 -0
  122. data/lib/agentic/verification/llm_verification_strategy.rb +60 -0
  123. data/lib/agentic/verification/schema_verification_strategy.rb +47 -0
  124. data/lib/agentic/verification/verification_hub.rb +62 -0
  125. data/lib/agentic/verification/verification_result.rb +50 -0
  126. data/lib/agentic/verification/verification_strategy.rb +26 -0
  127. data/lib/agentic/version.rb +1 -1
  128. data/lib/agentic.rb +74 -2
  129. data/plugins/README.md +41 -0
  130. metadata +245 -6
@@ -0,0 +1,260 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "singleton"
4
+
5
+ module Agentic
6
+ # Central registry for agent capabilities
7
+ # @attr_reader [Hash] capabilities The registered capabilities by name and version
8
+ # @attr_reader [Hash] providers The registered capability providers by name and version
9
+ class AgentCapabilityRegistry
10
+ include Singleton
11
+
12
+ attr_reader :capabilities, :providers
13
+
14
+ def initialize
15
+ @capabilities = {}
16
+ @providers = {}
17
+ @capability_versions = {}
18
+ end
19
+
20
+ # Register a capability with the registry
21
+ # @param capability [CapabilitySpecification] The capability to register
22
+ # @param provider [CapabilityProvider] The provider of the capability
23
+ # @return [CapabilitySpecification] The registered capability
24
+ def register(capability, provider)
25
+ validate_capability!(capability)
26
+
27
+ # Store by name and version
28
+ @capabilities[capability.name] ||= {}
29
+ @capabilities[capability.name][capability.version] = capability
30
+
31
+ # Track the provider
32
+ @providers[capability.name] ||= {}
33
+ @providers[capability.name][capability.version] = provider
34
+
35
+ # Update version tracking
36
+ update_version_tracking(capability)
37
+
38
+ # Log the registration
39
+ Agentic.logger.info("Registered capability: #{capability.name} v#{capability.version}")
40
+
41
+ capability
42
+ end
43
+
44
+ # Get a capability by name and version
45
+ # @param name [String] The name of the capability
46
+ # @param version [String, nil] The version of the capability, or nil for latest
47
+ # @return [CapabilitySpecification, nil] The capability or nil if not found
48
+ def get(name, version = nil)
49
+ return nil unless @capabilities[name]
50
+
51
+ if version.nil?
52
+ # Get the latest version
53
+ version = get_latest_version(name)
54
+ return nil unless version
55
+ end
56
+
57
+ @capabilities[name][version]
58
+ end
59
+
60
+ # Get the provider for a capability
61
+ # @param name [String] The name of the capability
62
+ # @param version [String, nil] The version of the capability, or nil for latest
63
+ # @return [CapabilityProvider, nil] The provider or nil if not found
64
+ def get_provider(name, version = nil)
65
+ return nil unless @providers[name]
66
+
67
+ if version.nil?
68
+ # Get the latest version
69
+ version = get_latest_version(name)
70
+ return nil unless version
71
+ end
72
+
73
+ @providers[name][version]
74
+ end
75
+
76
+ # Find capabilities matching criteria
77
+ # @param criteria [Hash] The search criteria
78
+ # @return [Array<CapabilitySpecification>] Matching capabilities
79
+ def find(criteria = {})
80
+ # Filter capabilities based on criteria
81
+ results = []
82
+
83
+ @capabilities.each do |name, versions|
84
+ versions.each do |version, capability|
85
+ if matches_criteria?(capability, criteria)
86
+ results << capability
87
+ end
88
+ end
89
+ end
90
+
91
+ results
92
+ end
93
+
94
+ # List all registered capabilities
95
+ # @param include_providers [Boolean] Whether to include providers in the output
96
+ # @return [Hash] Map of capability names to arrays of version strings
97
+ def list(include_providers: false)
98
+ result = {}
99
+
100
+ @capabilities.each do |name, versions|
101
+ result[name] = {
102
+ versions: versions.keys,
103
+ latest: get_latest_version(name)
104
+ }
105
+
106
+ if include_providers
107
+ result[name][:providers] = {}
108
+ versions.each do |version, _|
109
+ result[name][:providers][version] = @providers[name][version] if @providers[name][version]
110
+ end
111
+ end
112
+ end
113
+
114
+ result
115
+ end
116
+
117
+ # Compose capabilities into a new capability
118
+ # @param name [String] The name of the composed capability
119
+ # @param description [String] Description of the composed capability
120
+ # @param version [String] The version of the composed capability
121
+ # @param capabilities [Array<Hash>] The capabilities to compose
122
+ # @param compose_fn [Proc] The function to use for composition
123
+ # @return [CapabilitySpecification] The composed capability
124
+ def compose(name, description, version, capabilities, compose_fn)
125
+ # Get the individual capabilities
126
+ capability_instances = []
127
+ capability_providers = []
128
+
129
+ capabilities.each do |cap_spec|
130
+ cap_name = cap_spec[:name]
131
+ cap_version = cap_spec[:version]
132
+
133
+ capability = get(cap_name, cap_version)
134
+ raise "Capability not found: #{cap_name} v#{cap_version}" unless capability
135
+
136
+ provider = get_provider(cap_name, cap_version)
137
+ raise "Provider not found for capability: #{cap_name} v#{cap_version}" unless provider
138
+
139
+ capability_instances << capability
140
+ capability_providers << provider
141
+ end
142
+
143
+ # Create the composed capability
144
+ dependencies = capabilities.map do |cap_spec|
145
+ {
146
+ name: cap_spec[:name],
147
+ version: cap_spec[:version] || get_latest_version(cap_spec[:name])
148
+ }
149
+ end
150
+
151
+ composed_capability = CapabilitySpecification.new(
152
+ name: name,
153
+ description: description,
154
+ version: version,
155
+ dependencies: dependencies
156
+ )
157
+
158
+ # Create the composed provider
159
+ composed_provider = CapabilityProvider.new(
160
+ capability: composed_capability,
161
+ implementation: lambda do |inputs|
162
+ # Call the composition function with the individual providers and inputs
163
+ compose_fn.call(capability_providers, inputs)
164
+ end
165
+ )
166
+
167
+ # Register the composed capability
168
+ register(composed_capability, composed_provider)
169
+ end
170
+
171
+ # Clear all registered capabilities
172
+ # @return [void]
173
+ def clear
174
+ @capabilities = {}
175
+ @providers = {}
176
+ @capability_versions = {}
177
+ end
178
+
179
+ private
180
+
181
+ def validate_capability!(capability)
182
+ # Validate the capability specification
183
+ raise "Capability must be a CapabilitySpecification" unless capability.is_a?(CapabilitySpecification)
184
+ raise "Capability name cannot be empty" if capability.name.nil? || capability.name.empty?
185
+ raise "Capability version cannot be empty" if capability.version.nil? || capability.version.empty?
186
+ end
187
+
188
+ def update_version_tracking(capability)
189
+ # Update version tracking for the capability
190
+ @capability_versions[capability.name] ||= []
191
+ @capability_versions[capability.name] << capability.version
192
+ @capability_versions[capability.name].uniq!
193
+ end
194
+
195
+ def get_latest_version(name)
196
+ # Get the latest version of a capability
197
+ return nil unless @capability_versions[name] && !@capability_versions[name].empty?
198
+
199
+ # Sort versions semantically
200
+ # For now, just sort by splitting into parts and comparing numerically
201
+ @capability_versions[name].max do |a, b|
202
+ a_parts = a.split(".").map(&:to_i)
203
+ b_parts = b.split(".").map(&:to_i)
204
+
205
+ # Compare major version
206
+ major_comparison = a_parts[0] <=> b_parts[0]
207
+ next major_comparison unless major_comparison == 0
208
+
209
+ # Compare minor version
210
+ minor_comparison = a_parts[1] <=> b_parts[1]
211
+ next minor_comparison unless minor_comparison == 0
212
+
213
+ # Compare patch version
214
+ a_parts[2] <=> b_parts[2]
215
+ end
216
+ end
217
+
218
+ def matches_criteria?(capability, criteria)
219
+ # Check if a capability matches the given criteria
220
+ criteria.all? do |key, value|
221
+ case key
222
+ when :name, "name"
223
+ capability.name == value
224
+ when :version, "version"
225
+ capability.version == value
226
+ when :min_version, "min_version"
227
+ compare_versions(capability.version, value) >= 0
228
+ when :max_version, "max_version"
229
+ compare_versions(capability.version, value) <= 0
230
+ when :has_input, "has_input"
231
+ capability.inputs.key?(value.to_sym) || capability.inputs.key?(value.to_s)
232
+ when :has_output, "has_output"
233
+ capability.outputs.key?(value.to_sym) || capability.outputs.key?(value.to_s)
234
+ when :has_dependency, "has_dependency"
235
+ capability.dependencies.any? { |dep| dep[:name] == value || dep["name"] == value }
236
+ else
237
+ # For other criteria, check if the capability responds to the method
238
+ capability.respond_to?(key) && capability.send(key) == value
239
+ end
240
+ end
241
+ end
242
+
243
+ def compare_versions(version_a, version_b)
244
+ # Compare two version strings
245
+ a_parts = version_a.split(".").map(&:to_i)
246
+ b_parts = version_b.split(".").map(&:to_i)
247
+
248
+ # Compare major version
249
+ major_comparison = a_parts[0] <=> b_parts[0]
250
+ return major_comparison unless major_comparison == 0
251
+
252
+ # Compare minor version
253
+ minor_comparison = a_parts[1] <=> b_parts[1]
254
+ return minor_comparison unless minor_comparison == 0
255
+
256
+ # Compare patch version
257
+ a_parts[2] <=> b_parts[2]
258
+ end
259
+ end
260
+ end
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Agentic
4
+ # Configuration object for an Agent
5
+ class AgentConfig
6
+ # @return [String] The name of the agent
7
+ attr_accessor :name
8
+
9
+ # @return [String] The role of the agent
10
+ attr_accessor :role
11
+
12
+ # @return [String] The backstory or additional context for the agent
13
+ attr_accessor :backstory
14
+
15
+ # @return [Array<String>] The tools available to the agent
16
+ attr_accessor :tools
17
+
18
+ # @return [LlmConfig] The LLM configuration for the agent
19
+ attr_accessor :llm_config
20
+
21
+ # @return [Hash] Additional options for the agent
22
+ attr_accessor :options
23
+
24
+ # Initializes a new agent configuration
25
+ # @param name [String] The name of the agent
26
+ # @param role [String] The role of the agent
27
+ # @param backstory [String, nil] The backstory or additional context for the agent
28
+ # @param tools [Array<String>] The tools available to the agent
29
+ # @param llm_config [LlmConfig, nil] The LLM configuration for the agent
30
+ # @param options [Hash] Additional options for the agent
31
+ def initialize(
32
+ name:,
33
+ role:,
34
+ backstory: nil,
35
+ tools: [],
36
+ llm_config: nil,
37
+ options: {}
38
+ )
39
+ @name = name
40
+ @role = role
41
+ @backstory = backstory
42
+ @tools = tools
43
+ @llm_config = llm_config || LlmConfig.new
44
+ @options = options
45
+ end
46
+
47
+ # Returns a hash representation of the agent configuration
48
+ # @return [Hash] The agent configuration as a hash
49
+ def to_h
50
+ {
51
+ name: @name,
52
+ role: @role,
53
+ backstory: @backstory,
54
+ tools: @tools,
55
+ llm_config: {
56
+ model: @llm_config.model,
57
+ temperature: @llm_config.temperature
58
+ },
59
+ options: @options
60
+ }
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Agentic
4
+ # Value object representing requirements for an agent
5
+ class AgentSpecification
6
+ # @return [String] The name of the agent
7
+ attr_reader :name
8
+
9
+ # @return [String] A description of the agent
10
+ attr_reader :description
11
+
12
+ # @return [String] Instructions for the agent
13
+ attr_reader :instructions
14
+
15
+ # Initializes a new agent specification
16
+ # @param name [String] The name of the agent
17
+ # @param description [String] A description of the agent
18
+ # @param instructions [String] Instructions for the agent
19
+ def initialize(name:, description:, instructions:)
20
+ @name = name
21
+ @description = description
22
+ @instructions = instructions
23
+ end
24
+
25
+ # Returns a serializable representation of the agent specification
26
+ # @return [Hash] The agent specification as a hash
27
+ def to_h
28
+ {
29
+ "name" => @name,
30
+ "description" => @description,
31
+ "instructions" => @instructions
32
+ }
33
+ end
34
+
35
+ # Creates an AgentSpecification from a hash
36
+ # @param hash [Hash] The hash representation
37
+ # @return [AgentSpecification] A new agent specification
38
+ def self.from_hash(hash)
39
+ new(
40
+ name: hash["name"],
41
+ description: hash["description"],
42
+ instructions: hash["instructions"]
43
+ )
44
+ end
45
+ end
46
+ end