a2a-ruby 1.0.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 (128) hide show
  1. checksums.yaml +7 -0
  2. data/.rspec +3 -0
  3. data/.rubocop.yml +137 -0
  4. data/.simplecov +46 -0
  5. data/.yardopts +10 -0
  6. data/CHANGELOG.md +33 -0
  7. data/CODE_OF_CONDUCT.md +128 -0
  8. data/CONTRIBUTING.md +165 -0
  9. data/Gemfile +43 -0
  10. data/Guardfile +34 -0
  11. data/LICENSE.txt +21 -0
  12. data/PUBLISHING_CHECKLIST.md +214 -0
  13. data/README.md +171 -0
  14. data/Rakefile +165 -0
  15. data/docs/agent_execution.md +309 -0
  16. data/docs/api_reference.md +792 -0
  17. data/docs/configuration.md +780 -0
  18. data/docs/events.md +475 -0
  19. data/docs/getting_started.md +668 -0
  20. data/docs/integration.md +262 -0
  21. data/docs/server_apps.md +621 -0
  22. data/docs/troubleshooting.md +765 -0
  23. data/lib/a2a/client/api_methods.rb +263 -0
  24. data/lib/a2a/client/auth/api_key.rb +161 -0
  25. data/lib/a2a/client/auth/interceptor.rb +288 -0
  26. data/lib/a2a/client/auth/jwt.rb +189 -0
  27. data/lib/a2a/client/auth/oauth2.rb +146 -0
  28. data/lib/a2a/client/auth.rb +137 -0
  29. data/lib/a2a/client/base.rb +316 -0
  30. data/lib/a2a/client/config.rb +210 -0
  31. data/lib/a2a/client/connection_pool.rb +233 -0
  32. data/lib/a2a/client/http_client.rb +524 -0
  33. data/lib/a2a/client/json_rpc_handler.rb +136 -0
  34. data/lib/a2a/client/middleware/circuit_breaker_interceptor.rb +245 -0
  35. data/lib/a2a/client/middleware/logging_interceptor.rb +371 -0
  36. data/lib/a2a/client/middleware/rate_limit_interceptor.rb +142 -0
  37. data/lib/a2a/client/middleware/retry_interceptor.rb +161 -0
  38. data/lib/a2a/client/middleware.rb +116 -0
  39. data/lib/a2a/client/performance_tracker.rb +60 -0
  40. data/lib/a2a/configuration/defaults.rb +34 -0
  41. data/lib/a2a/configuration/environment_loader.rb +76 -0
  42. data/lib/a2a/configuration/file_loader.rb +115 -0
  43. data/lib/a2a/configuration/inheritance.rb +101 -0
  44. data/lib/a2a/configuration/validator.rb +180 -0
  45. data/lib/a2a/configuration.rb +201 -0
  46. data/lib/a2a/errors.rb +291 -0
  47. data/lib/a2a/modules.rb +50 -0
  48. data/lib/a2a/monitoring/alerting.rb +490 -0
  49. data/lib/a2a/monitoring/distributed_tracing.rb +398 -0
  50. data/lib/a2a/monitoring/health_endpoints.rb +204 -0
  51. data/lib/a2a/monitoring/metrics_collector.rb +438 -0
  52. data/lib/a2a/monitoring.rb +463 -0
  53. data/lib/a2a/plugin.rb +358 -0
  54. data/lib/a2a/plugin_manager.rb +159 -0
  55. data/lib/a2a/plugins/example_auth.rb +81 -0
  56. data/lib/a2a/plugins/example_middleware.rb +118 -0
  57. data/lib/a2a/plugins/example_transport.rb +76 -0
  58. data/lib/a2a/protocol/agent_card.rb +8 -0
  59. data/lib/a2a/protocol/agent_card_server.rb +584 -0
  60. data/lib/a2a/protocol/capability.rb +496 -0
  61. data/lib/a2a/protocol/json_rpc.rb +254 -0
  62. data/lib/a2a/protocol/message.rb +8 -0
  63. data/lib/a2a/protocol/task.rb +8 -0
  64. data/lib/a2a/rails/a2a_controller.rb +258 -0
  65. data/lib/a2a/rails/controller_helpers.rb +499 -0
  66. data/lib/a2a/rails/engine.rb +167 -0
  67. data/lib/a2a/rails/generators/agent_generator.rb +311 -0
  68. data/lib/a2a/rails/generators/install_generator.rb +209 -0
  69. data/lib/a2a/rails/generators/migration_generator.rb +232 -0
  70. data/lib/a2a/rails/generators/templates/add_a2a_indexes.rb +57 -0
  71. data/lib/a2a/rails/generators/templates/agent_controller.rb +122 -0
  72. data/lib/a2a/rails/generators/templates/agent_controller_spec.rb +160 -0
  73. data/lib/a2a/rails/generators/templates/agent_readme.md +200 -0
  74. data/lib/a2a/rails/generators/templates/create_a2a_push_notification_configs.rb +68 -0
  75. data/lib/a2a/rails/generators/templates/create_a2a_tasks.rb +83 -0
  76. data/lib/a2a/rails/generators/templates/example_agent_controller.rb +228 -0
  77. data/lib/a2a/rails/generators/templates/initializer.rb +108 -0
  78. data/lib/a2a/rails/generators/templates/push_notification_config_model.rb +228 -0
  79. data/lib/a2a/rails/generators/templates/task_model.rb +200 -0
  80. data/lib/a2a/rails/tasks/a2a.rake +228 -0
  81. data/lib/a2a/server/a2a_methods.rb +520 -0
  82. data/lib/a2a/server/agent.rb +537 -0
  83. data/lib/a2a/server/agent_execution/agent_executor.rb +279 -0
  84. data/lib/a2a/server/agent_execution/request_context.rb +219 -0
  85. data/lib/a2a/server/apps/rack_app.rb +311 -0
  86. data/lib/a2a/server/apps/sinatra_app.rb +261 -0
  87. data/lib/a2a/server/default_request_handler.rb +350 -0
  88. data/lib/a2a/server/events/event_consumer.rb +116 -0
  89. data/lib/a2a/server/events/event_queue.rb +226 -0
  90. data/lib/a2a/server/example_agent.rb +248 -0
  91. data/lib/a2a/server/handler.rb +281 -0
  92. data/lib/a2a/server/middleware/authentication_middleware.rb +212 -0
  93. data/lib/a2a/server/middleware/cors_middleware.rb +171 -0
  94. data/lib/a2a/server/middleware/logging_middleware.rb +362 -0
  95. data/lib/a2a/server/middleware/rate_limit_middleware.rb +382 -0
  96. data/lib/a2a/server/middleware.rb +213 -0
  97. data/lib/a2a/server/push_notification_manager.rb +327 -0
  98. data/lib/a2a/server/request_handler.rb +136 -0
  99. data/lib/a2a/server/storage/base.rb +141 -0
  100. data/lib/a2a/server/storage/database.rb +266 -0
  101. data/lib/a2a/server/storage/memory.rb +274 -0
  102. data/lib/a2a/server/storage/redis.rb +320 -0
  103. data/lib/a2a/server/storage.rb +38 -0
  104. data/lib/a2a/server/task_manager.rb +534 -0
  105. data/lib/a2a/transport/grpc.rb +481 -0
  106. data/lib/a2a/transport/http.rb +415 -0
  107. data/lib/a2a/transport/sse.rb +499 -0
  108. data/lib/a2a/types/agent_card.rb +540 -0
  109. data/lib/a2a/types/artifact.rb +99 -0
  110. data/lib/a2a/types/base_model.rb +223 -0
  111. data/lib/a2a/types/events.rb +117 -0
  112. data/lib/a2a/types/message.rb +106 -0
  113. data/lib/a2a/types/part.rb +288 -0
  114. data/lib/a2a/types/push_notification.rb +139 -0
  115. data/lib/a2a/types/security.rb +167 -0
  116. data/lib/a2a/types/task.rb +154 -0
  117. data/lib/a2a/types.rb +88 -0
  118. data/lib/a2a/utils/helpers.rb +245 -0
  119. data/lib/a2a/utils/message_buffer.rb +278 -0
  120. data/lib/a2a/utils/performance.rb +247 -0
  121. data/lib/a2a/utils/rails_detection.rb +97 -0
  122. data/lib/a2a/utils/structured_logger.rb +306 -0
  123. data/lib/a2a/utils/time_helpers.rb +167 -0
  124. data/lib/a2a/utils/validation.rb +8 -0
  125. data/lib/a2a/version.rb +6 -0
  126. data/lib/a2a-rails.rb +58 -0
  127. data/lib/a2a.rb +198 -0
  128. metadata +437 -0
@@ -0,0 +1,233 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "monitor"
4
+
5
+ module A2A
6
+ module Client
7
+ ##
8
+ # Connection pool manager for HTTP clients
9
+ #
10
+ # Manages a pool of HTTP connections to improve performance by reusing
11
+ # connections and avoiding the overhead of establishing new connections
12
+ # for each request.
13
+ #
14
+ class ConnectionPool
15
+ include MonitorMixin
16
+
17
+ # Default pool configuration
18
+ DEFAULT_POOL_SIZE = 5
19
+ DEFAULT_TIMEOUT = 5
20
+ DEFAULT_IDLE_TIMEOUT = 30
21
+
22
+ attr_reader :size, :timeout, :idle_timeout, :created, :checked_out
23
+
24
+ ##
25
+ # Initialize a new connection pool
26
+ #
27
+ # @param size [Integer] Maximum number of connections in the pool
28
+ # @param timeout [Integer] Timeout for checking out a connection
29
+ # @param idle_timeout [Integer] Timeout for idle connections
30
+ # @yield Block that creates a new connection
31
+ def initialize(size: DEFAULT_POOL_SIZE, timeout: DEFAULT_TIMEOUT, idle_timeout: DEFAULT_IDLE_TIMEOUT, &block)
32
+ super()
33
+
34
+ @size = size
35
+ @timeout = timeout
36
+ @idle_timeout = idle_timeout
37
+ @connection_factory = block
38
+ @pool = []
39
+ @checked_out = []
40
+ @created = 0
41
+ @last_cleanup = Time.now
42
+ end
43
+
44
+ ##
45
+ # Check out a connection from the pool
46
+ #
47
+ # @return [Object] A connection from the pool
48
+ # @raise [TimeoutError] If no connection is available within timeout
49
+ def checkout
50
+ synchronize do
51
+ # Try to get an existing connection
52
+ connection = @pool.pop
53
+
54
+ # Create a new connection if pool is empty and we haven't reached the limit
55
+ connection = create_connection if connection.nil? && @created < @size
56
+
57
+ # Wait for a connection to become available
58
+ if connection.nil?
59
+ deadline = Time.now + @timeout
60
+
61
+ while connection.nil? && Time.now < deadline
62
+ ns_wait(0.1) # Wait 100ms
63
+ connection = @pool.pop
64
+ end
65
+
66
+ raise TimeoutError, "Could not checkout connection within #{@timeout}s" if connection.nil?
67
+ end
68
+
69
+ # Mark connection as checked out
70
+ @checked_out << connection
71
+
72
+ # Cleanup idle connections periodically
73
+ cleanup_idle_connections if should_cleanup?
74
+
75
+ connection
76
+ end
77
+ end
78
+
79
+ ##
80
+ # Check in a connection to the pool
81
+ #
82
+ # @param connection [Object] The connection to return to the pool
83
+ def checkin(connection)
84
+ synchronize do
85
+ @checked_out.delete(connection)
86
+
87
+ # Add connection back to pool if it's still valid
88
+ if valid_connection?(connection)
89
+ connection.instance_variable_set(:@last_used, Time.now)
90
+ @pool.push(connection)
91
+ else
92
+ # Connection is invalid, create a new one to replace it
93
+ @created -= 1
94
+ end
95
+ end
96
+ end
97
+
98
+ ##
99
+ # Execute a block with a connection from the pool
100
+ #
101
+ # @yield [connection] Block to execute with the connection
102
+ # @return [Object] Result of the block
103
+ def with_connection
104
+ connection = checkout
105
+ begin
106
+ yield connection
107
+ ensure
108
+ checkin(connection)
109
+ end
110
+ end
111
+
112
+ ##
113
+ # Get pool statistics
114
+ #
115
+ # @return [Hash] Pool statistics
116
+ def stats
117
+ synchronize do
118
+ {
119
+ size: @size,
120
+ created: @created,
121
+ available: @pool.size,
122
+ checked_out: @checked_out.size,
123
+ idle_timeout: @idle_timeout,
124
+ timeout: @timeout
125
+ }
126
+ end
127
+ end
128
+
129
+ ##
130
+ # Close all connections in the pool
131
+ #
132
+ def close_all
133
+ synchronize do
134
+ (@pool + @checked_out).each do |connection|
135
+ close_connection(connection)
136
+ end
137
+
138
+ @pool.clear
139
+ @checked_out.clear
140
+ @created = 0
141
+ end
142
+ end
143
+
144
+ ##
145
+ # Flush idle connections from the pool
146
+ #
147
+ def flush_idle!
148
+ synchronize do
149
+ cleanup_idle_connections
150
+ end
151
+ end
152
+
153
+ private
154
+
155
+ ##
156
+ # Create a new connection
157
+ #
158
+ # @return [Object] New connection
159
+ def create_connection
160
+ return nil unless @connection_factory
161
+
162
+ connection = @connection_factory.call
163
+ connection.instance_variable_set(:@created_at, Time.now)
164
+ connection.instance_variable_set(:@last_used, Time.now)
165
+ @created += 1
166
+
167
+ connection
168
+ end
169
+
170
+ ##
171
+ # Check if a connection is valid
172
+ #
173
+ # @param connection [Object] Connection to validate
174
+ # @return [Boolean] True if connection is valid
175
+ def valid_connection?(connection)
176
+ return false unless connection
177
+
178
+ # Check if connection responds to basic methods
179
+ return false unless connection.respond_to?(:get) || connection.respond_to?(:request)
180
+
181
+ # Check if connection is not too old
182
+ created_at = connection.instance_variable_get(:@created_at)
183
+ return false if created_at && (Time.now - created_at) > (@idle_timeout * 10)
184
+
185
+ true
186
+ rescue StandardError
187
+ false
188
+ end
189
+
190
+ ##
191
+ # Close a connection
192
+ #
193
+ # @param connection [Object] Connection to close
194
+ def close_connection(connection)
195
+ connection.close if connection.respond_to?(:close)
196
+ rescue StandardError
197
+ # Ignore errors when closing connections
198
+ end
199
+
200
+ ##
201
+ # Check if we should run cleanup
202
+ #
203
+ # @return [Boolean] True if cleanup should run
204
+ def should_cleanup?
205
+ Time.now - @last_cleanup > 60 # Cleanup every minute
206
+ end
207
+
208
+ ##
209
+ # Clean up idle connections
210
+ #
211
+ def cleanup_idle_connections
212
+ @last_cleanup = Time.now
213
+ cutoff_time = Time.now - @idle_timeout
214
+
215
+ @pool.reject! do |connection|
216
+ last_used = connection.instance_variable_get(:@last_used)
217
+ if last_used && last_used < cutoff_time
218
+ close_connection(connection)
219
+ @created -= 1
220
+ true
221
+ else
222
+ false
223
+ end
224
+ end
225
+ end
226
+ end
227
+
228
+ ##
229
+ # Timeout error for connection pool operations
230
+ #
231
+ class TimeoutError < StandardError; end
232
+ end
233
+ end