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.
- checksums.yaml +7 -0
- data/.rspec +3 -0
- data/.rubocop.yml +137 -0
- data/.simplecov +46 -0
- data/.yardopts +10 -0
- data/CHANGELOG.md +33 -0
- data/CODE_OF_CONDUCT.md +128 -0
- data/CONTRIBUTING.md +165 -0
- data/Gemfile +43 -0
- data/Guardfile +34 -0
- data/LICENSE.txt +21 -0
- data/PUBLISHING_CHECKLIST.md +214 -0
- data/README.md +171 -0
- data/Rakefile +165 -0
- data/docs/agent_execution.md +309 -0
- data/docs/api_reference.md +792 -0
- data/docs/configuration.md +780 -0
- data/docs/events.md +475 -0
- data/docs/getting_started.md +668 -0
- data/docs/integration.md +262 -0
- data/docs/server_apps.md +621 -0
- data/docs/troubleshooting.md +765 -0
- data/lib/a2a/client/api_methods.rb +263 -0
- data/lib/a2a/client/auth/api_key.rb +161 -0
- data/lib/a2a/client/auth/interceptor.rb +288 -0
- data/lib/a2a/client/auth/jwt.rb +189 -0
- data/lib/a2a/client/auth/oauth2.rb +146 -0
- data/lib/a2a/client/auth.rb +137 -0
- data/lib/a2a/client/base.rb +316 -0
- data/lib/a2a/client/config.rb +210 -0
- data/lib/a2a/client/connection_pool.rb +233 -0
- data/lib/a2a/client/http_client.rb +524 -0
- data/lib/a2a/client/json_rpc_handler.rb +136 -0
- data/lib/a2a/client/middleware/circuit_breaker_interceptor.rb +245 -0
- data/lib/a2a/client/middleware/logging_interceptor.rb +371 -0
- data/lib/a2a/client/middleware/rate_limit_interceptor.rb +142 -0
- data/lib/a2a/client/middleware/retry_interceptor.rb +161 -0
- data/lib/a2a/client/middleware.rb +116 -0
- data/lib/a2a/client/performance_tracker.rb +60 -0
- data/lib/a2a/configuration/defaults.rb +34 -0
- data/lib/a2a/configuration/environment_loader.rb +76 -0
- data/lib/a2a/configuration/file_loader.rb +115 -0
- data/lib/a2a/configuration/inheritance.rb +101 -0
- data/lib/a2a/configuration/validator.rb +180 -0
- data/lib/a2a/configuration.rb +201 -0
- data/lib/a2a/errors.rb +291 -0
- data/lib/a2a/modules.rb +50 -0
- data/lib/a2a/monitoring/alerting.rb +490 -0
- data/lib/a2a/monitoring/distributed_tracing.rb +398 -0
- data/lib/a2a/monitoring/health_endpoints.rb +204 -0
- data/lib/a2a/monitoring/metrics_collector.rb +438 -0
- data/lib/a2a/monitoring.rb +463 -0
- data/lib/a2a/plugin.rb +358 -0
- data/lib/a2a/plugin_manager.rb +159 -0
- data/lib/a2a/plugins/example_auth.rb +81 -0
- data/lib/a2a/plugins/example_middleware.rb +118 -0
- data/lib/a2a/plugins/example_transport.rb +76 -0
- data/lib/a2a/protocol/agent_card.rb +8 -0
- data/lib/a2a/protocol/agent_card_server.rb +584 -0
- data/lib/a2a/protocol/capability.rb +496 -0
- data/lib/a2a/protocol/json_rpc.rb +254 -0
- data/lib/a2a/protocol/message.rb +8 -0
- data/lib/a2a/protocol/task.rb +8 -0
- data/lib/a2a/rails/a2a_controller.rb +258 -0
- data/lib/a2a/rails/controller_helpers.rb +499 -0
- data/lib/a2a/rails/engine.rb +167 -0
- data/lib/a2a/rails/generators/agent_generator.rb +311 -0
- data/lib/a2a/rails/generators/install_generator.rb +209 -0
- data/lib/a2a/rails/generators/migration_generator.rb +232 -0
- data/lib/a2a/rails/generators/templates/add_a2a_indexes.rb +57 -0
- data/lib/a2a/rails/generators/templates/agent_controller.rb +122 -0
- data/lib/a2a/rails/generators/templates/agent_controller_spec.rb +160 -0
- data/lib/a2a/rails/generators/templates/agent_readme.md +200 -0
- data/lib/a2a/rails/generators/templates/create_a2a_push_notification_configs.rb +68 -0
- data/lib/a2a/rails/generators/templates/create_a2a_tasks.rb +83 -0
- data/lib/a2a/rails/generators/templates/example_agent_controller.rb +228 -0
- data/lib/a2a/rails/generators/templates/initializer.rb +108 -0
- data/lib/a2a/rails/generators/templates/push_notification_config_model.rb +228 -0
- data/lib/a2a/rails/generators/templates/task_model.rb +200 -0
- data/lib/a2a/rails/tasks/a2a.rake +228 -0
- data/lib/a2a/server/a2a_methods.rb +520 -0
- data/lib/a2a/server/agent.rb +537 -0
- data/lib/a2a/server/agent_execution/agent_executor.rb +279 -0
- data/lib/a2a/server/agent_execution/request_context.rb +219 -0
- data/lib/a2a/server/apps/rack_app.rb +311 -0
- data/lib/a2a/server/apps/sinatra_app.rb +261 -0
- data/lib/a2a/server/default_request_handler.rb +350 -0
- data/lib/a2a/server/events/event_consumer.rb +116 -0
- data/lib/a2a/server/events/event_queue.rb +226 -0
- data/lib/a2a/server/example_agent.rb +248 -0
- data/lib/a2a/server/handler.rb +281 -0
- data/lib/a2a/server/middleware/authentication_middleware.rb +212 -0
- data/lib/a2a/server/middleware/cors_middleware.rb +171 -0
- data/lib/a2a/server/middleware/logging_middleware.rb +362 -0
- data/lib/a2a/server/middleware/rate_limit_middleware.rb +382 -0
- data/lib/a2a/server/middleware.rb +213 -0
- data/lib/a2a/server/push_notification_manager.rb +327 -0
- data/lib/a2a/server/request_handler.rb +136 -0
- data/lib/a2a/server/storage/base.rb +141 -0
- data/lib/a2a/server/storage/database.rb +266 -0
- data/lib/a2a/server/storage/memory.rb +274 -0
- data/lib/a2a/server/storage/redis.rb +320 -0
- data/lib/a2a/server/storage.rb +38 -0
- data/lib/a2a/server/task_manager.rb +534 -0
- data/lib/a2a/transport/grpc.rb +481 -0
- data/lib/a2a/transport/http.rb +415 -0
- data/lib/a2a/transport/sse.rb +499 -0
- data/lib/a2a/types/agent_card.rb +540 -0
- data/lib/a2a/types/artifact.rb +99 -0
- data/lib/a2a/types/base_model.rb +223 -0
- data/lib/a2a/types/events.rb +117 -0
- data/lib/a2a/types/message.rb +106 -0
- data/lib/a2a/types/part.rb +288 -0
- data/lib/a2a/types/push_notification.rb +139 -0
- data/lib/a2a/types/security.rb +167 -0
- data/lib/a2a/types/task.rb +154 -0
- data/lib/a2a/types.rb +88 -0
- data/lib/a2a/utils/helpers.rb +245 -0
- data/lib/a2a/utils/message_buffer.rb +278 -0
- data/lib/a2a/utils/performance.rb +247 -0
- data/lib/a2a/utils/rails_detection.rb +97 -0
- data/lib/a2a/utils/structured_logger.rb +306 -0
- data/lib/a2a/utils/time_helpers.rb +167 -0
- data/lib/a2a/utils/validation.rb +8 -0
- data/lib/a2a/version.rb +6 -0
- data/lib/a2a-rails.rb +58 -0
- data/lib/a2a.rb +198 -0
- metadata +437 -0
data/lib/a2a/errors.rb
ADDED
@@ -0,0 +1,291 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
##
|
4
|
+
# Exception classes for the A2A Ruby SDK
|
5
|
+
#
|
6
|
+
module A2A
|
7
|
+
module Errors
|
8
|
+
##
|
9
|
+
# Base class for all A2A errors
|
10
|
+
#
|
11
|
+
class A2AError < StandardError
|
12
|
+
attr_reader :code, :data
|
13
|
+
|
14
|
+
def initialize(message = nil, code: nil, data: nil)
|
15
|
+
super(message)
|
16
|
+
@code = code
|
17
|
+
@data = data
|
18
|
+
end
|
19
|
+
|
20
|
+
# Convert to JSON-RPC error format
|
21
|
+
# @return [Hash]
|
22
|
+
def to_json_rpc_error
|
23
|
+
{
|
24
|
+
code: @code,
|
25
|
+
message: message,
|
26
|
+
data: @data
|
27
|
+
}.compact
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
##
|
32
|
+
# Configuration-related errors
|
33
|
+
#
|
34
|
+
class ConfigurationError < A2AError; end
|
35
|
+
|
36
|
+
##
|
37
|
+
# JSON-RPC 2.0 standard errors
|
38
|
+
#
|
39
|
+
|
40
|
+
# Parse error - Invalid JSON was received by the server
|
41
|
+
class ParseError < A2AError
|
42
|
+
def initialize(message = "Parse error", **options)
|
43
|
+
super(message, code: -32_700, **options)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# Invalid Request - The JSON sent is not a valid Request object
|
48
|
+
class InvalidRequest < A2AError
|
49
|
+
def initialize(message = "Invalid Request", **options)
|
50
|
+
super(message, code: -32_600, **options)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# Method not found - The method does not exist / is not available
|
55
|
+
class MethodNotFound < A2AError
|
56
|
+
def initialize(message = "Method not found", **options)
|
57
|
+
super(message, code: -32_601, **options)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# Invalid params - Invalid method parameter(s)
|
62
|
+
class InvalidParams < A2AError
|
63
|
+
def initialize(message = "Invalid params", **options)
|
64
|
+
super(message, code: -32_602, **options)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
# Internal error - Internal JSON-RPC error
|
69
|
+
class InternalError < A2AError
|
70
|
+
def initialize(message = "Internal error", **options)
|
71
|
+
super(message, code: -32_603, **options)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
##
|
76
|
+
# A2A-specific errors (-32001 to -32010)
|
77
|
+
#
|
78
|
+
|
79
|
+
# Task not found
|
80
|
+
class TaskNotFound < A2AError
|
81
|
+
def initialize(message = "Task not found", **options)
|
82
|
+
super(message, code: -32_001, **options)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
# Task cannot be canceled
|
87
|
+
class TaskNotCancelable < A2AError
|
88
|
+
def initialize(message = "Task cannot be canceled", **options)
|
89
|
+
super(message, code: -32_002, **options)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
# Invalid task state
|
94
|
+
class InvalidTaskState < A2AError
|
95
|
+
def initialize(message = "Invalid task state", **options)
|
96
|
+
super(message, code: -32_003, **options)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
# Authentication required
|
101
|
+
class AuthenticationRequired < A2AError
|
102
|
+
def initialize(message = "Authentication required", **options)
|
103
|
+
super(message, code: -32_004, **options)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
# Authorization failed
|
108
|
+
class AuthorizationFailed < A2AError
|
109
|
+
def initialize(message = "Authorization failed", **options)
|
110
|
+
super(message, code: -32_005, **options)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
# Rate limit exceeded
|
115
|
+
class RateLimitExceeded < A2AError
|
116
|
+
def initialize(message = "Rate limit exceeded", **options)
|
117
|
+
super(message, code: -32_006, **options)
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
# Agent unavailable
|
122
|
+
class AgentUnavailable < A2AError
|
123
|
+
def initialize(message = "Agent unavailable", **options)
|
124
|
+
super(message, code: -32_007, **options)
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
# Protocol version mismatch
|
129
|
+
class ProtocolVersionMismatch < A2AError
|
130
|
+
def initialize(message = "Protocol version mismatch", **options)
|
131
|
+
super(message, code: -32_008, **options)
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
# Capability not supported
|
136
|
+
class CapabilityNotSupported < A2AError
|
137
|
+
def initialize(message = "Capability not supported", **options)
|
138
|
+
super(message, code: -32_009, **options)
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
# Resource exhausted
|
143
|
+
class ResourceExhausted < A2AError
|
144
|
+
def initialize(message = "Resource exhausted", **options)
|
145
|
+
super(message, code: -32_010, **options)
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
# Unsupported operation
|
150
|
+
class UnsupportedOperation < A2AError
|
151
|
+
def initialize(message = "Operation not supported", **options)
|
152
|
+
super(message, code: -32_011, **options)
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
# Not found (generic)
|
157
|
+
class NotFound < A2AError
|
158
|
+
def initialize(message = "Not found", **options)
|
159
|
+
super(message, code: -32_404, **options)
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
##
|
164
|
+
# Client-side errors
|
165
|
+
#
|
166
|
+
|
167
|
+
# Base client error
|
168
|
+
class ClientError < A2AError; end
|
169
|
+
|
170
|
+
# HTTP-related errors
|
171
|
+
class HTTPError < ClientError
|
172
|
+
attr_reader :status_code, :response_body
|
173
|
+
|
174
|
+
def initialize(message, status_code: nil, response_body: nil, **options)
|
175
|
+
super(message, **options)
|
176
|
+
@status_code = status_code
|
177
|
+
@response_body = response_body
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
# Timeout errors
|
182
|
+
class TimeoutError < ClientError; end
|
183
|
+
|
184
|
+
# Authentication errors
|
185
|
+
class AuthenticationError < ClientError; end
|
186
|
+
|
187
|
+
# JSON parsing errors
|
188
|
+
class JSONError < ClientError; end
|
189
|
+
|
190
|
+
# Transport errors
|
191
|
+
class TransportError < ClientError; end
|
192
|
+
|
193
|
+
# Server-side errors
|
194
|
+
class ServerError < A2AError
|
195
|
+
attr_reader :error
|
196
|
+
|
197
|
+
def initialize(error = nil, message: nil)
|
198
|
+
@error = error
|
199
|
+
super(message || error&.message || "Server error")
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
##
|
204
|
+
# Utility methods for error handling
|
205
|
+
#
|
206
|
+
module ErrorUtils
|
207
|
+
##
|
208
|
+
# Convert an exception to a JSON-RPC error response
|
209
|
+
#
|
210
|
+
# @param exception [Exception] The exception to convert
|
211
|
+
# @param request_id [String, Integer, nil] The request ID
|
212
|
+
# @return [Hash] JSON-RPC error response
|
213
|
+
def self.exception_to_json_rpc_error(exception, request_id: nil)
|
214
|
+
if exception.is_a?(A2AError)
|
215
|
+
A2A::Protocol::JsonRpc.build_error_response(
|
216
|
+
code: exception.code,
|
217
|
+
message: exception.message,
|
218
|
+
data: exception.data,
|
219
|
+
id: request_id
|
220
|
+
)
|
221
|
+
else
|
222
|
+
# Map standard Ruby exceptions to JSON-RPC errors
|
223
|
+
case exception
|
224
|
+
when ArgumentError
|
225
|
+
A2A::Protocol::JsonRpc.build_error_response(
|
226
|
+
code: A2A::Protocol::JsonRpc::INVALID_PARAMS,
|
227
|
+
message: exception.message,
|
228
|
+
id: request_id
|
229
|
+
)
|
230
|
+
when NoMethodError
|
231
|
+
A2A::Protocol::JsonRpc.build_error_response(
|
232
|
+
code: A2A::Protocol::JsonRpc::METHOD_NOT_FOUND,
|
233
|
+
message: "Method not found",
|
234
|
+
id: request_id
|
235
|
+
)
|
236
|
+
else
|
237
|
+
A2A::Protocol::JsonRpc.build_error_response(
|
238
|
+
code: A2A::Protocol::JsonRpc::INTERNAL_ERROR,
|
239
|
+
message: exception.message,
|
240
|
+
id: request_id
|
241
|
+
)
|
242
|
+
end
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
246
|
+
##
|
247
|
+
# Create an A2A error from a JSON-RPC error code
|
248
|
+
#
|
249
|
+
# @param code [Integer] The error code
|
250
|
+
# @param message [String] The error message
|
251
|
+
# @param data [Object, nil] Additional error data
|
252
|
+
# @return [A2AError] The appropriate error instance
|
253
|
+
def self.from_json_rpc_code(code, message, data: nil)
|
254
|
+
case code
|
255
|
+
when A2A::Protocol::JsonRpc::PARSE_ERROR
|
256
|
+
ParseError.new(message, data: data)
|
257
|
+
when A2A::Protocol::JsonRpc::INVALID_REQUEST
|
258
|
+
InvalidRequest.new(message, data: data)
|
259
|
+
when A2A::Protocol::JsonRpc::METHOD_NOT_FOUND
|
260
|
+
MethodNotFound.new(message, data: data)
|
261
|
+
when A2A::Protocol::JsonRpc::INVALID_PARAMS
|
262
|
+
InvalidParams.new(message, data: data)
|
263
|
+
when A2A::Protocol::JsonRpc::INTERNAL_ERROR
|
264
|
+
InternalError.new(message, data: data)
|
265
|
+
when A2A::Protocol::JsonRpc::TASK_NOT_FOUND
|
266
|
+
TaskNotFound.new(message, data: data)
|
267
|
+
when A2A::Protocol::JsonRpc::TASK_NOT_CANCELABLE
|
268
|
+
TaskNotCancelable.new(message, data: data)
|
269
|
+
when A2A::Protocol::JsonRpc::INVALID_TASK_STATE
|
270
|
+
InvalidTaskState.new(message, data: data)
|
271
|
+
when A2A::Protocol::JsonRpc::AUTHENTICATION_REQUIRED
|
272
|
+
AuthenticationRequired.new(message, data: data)
|
273
|
+
when A2A::Protocol::JsonRpc::AUTHORIZATION_FAILED
|
274
|
+
AuthorizationFailed.new(message, data: data)
|
275
|
+
when A2A::Protocol::JsonRpc::RATE_LIMIT_EXCEEDED
|
276
|
+
RateLimitExceeded.new(message, data: data)
|
277
|
+
when A2A::Protocol::JsonRpc::AGENT_UNAVAILABLE
|
278
|
+
AgentUnavailable.new(message, data: data)
|
279
|
+
when A2A::Protocol::JsonRpc::PROTOCOL_VERSION_MISMATCH
|
280
|
+
ProtocolVersionMismatch.new(message, data: data)
|
281
|
+
when A2A::Protocol::JsonRpc::CAPABILITY_NOT_SUPPORTED
|
282
|
+
CapabilityNotSupported.new(message, data: data)
|
283
|
+
when A2A::Protocol::JsonRpc::RESOURCE_EXHAUSTED
|
284
|
+
ResourceExhausted.new(message, data: data)
|
285
|
+
else
|
286
|
+
A2AError.new(message, code: code, data: data)
|
287
|
+
end
|
288
|
+
end
|
289
|
+
end
|
290
|
+
end
|
291
|
+
end
|
data/lib/a2a/modules.rb
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
##
|
4
|
+
# Module definitions for A2A SDK
|
5
|
+
#
|
6
|
+
# This file defines all the necessary module namespaces to prevent
|
7
|
+
# "uninitialized constant" errors when classes are defined before
|
8
|
+
# their parent modules.
|
9
|
+
#
|
10
|
+
|
11
|
+
module A2A
|
12
|
+
module Types
|
13
|
+
end
|
14
|
+
|
15
|
+
module Server
|
16
|
+
module Middleware
|
17
|
+
end
|
18
|
+
|
19
|
+
module Storage
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
module Client
|
24
|
+
module Auth
|
25
|
+
end
|
26
|
+
|
27
|
+
module Middleware
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
module Transport
|
32
|
+
end
|
33
|
+
|
34
|
+
module Monitoring
|
35
|
+
end
|
36
|
+
|
37
|
+
module Rails
|
38
|
+
module Generators
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
module Utils
|
43
|
+
end
|
44
|
+
|
45
|
+
module Plugins
|
46
|
+
end
|
47
|
+
|
48
|
+
module Errors
|
49
|
+
end
|
50
|
+
end
|