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,537 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../protocol/capability"
4
+
5
+ module A2A
6
+ module Server
7
+ ##
8
+ # Agent DSL for defining A2A-compatible methods and capabilities
9
+ #
10
+ # This module provides a DSL for defining agent methods that can be called
11
+ # via the A2A protocol. It includes method registration, capability definition,
12
+ # parameter validation, and middleware support.
13
+ #
14
+ # @example Basic agent definition
15
+ # class MyAgent
16
+ # include A2A::Server::Agent
17
+ #
18
+ # a2a_method "greet" do |params|
19
+ # { message: "Hello, #{params['name']}!" }
20
+ # end
21
+ #
22
+ # a2a_capability "greeting" do
23
+ # method "greet"
24
+ # description "Greet a user by name"
25
+ # input_schema type: "object", properties: { name: { type: "string" } }
26
+ # output_schema type: "object", properties: { message: { type: "string" } }
27
+ # end
28
+ # end
29
+ #
30
+ module Agent
31
+ def self.included(base)
32
+ base.extend(ClassMethods)
33
+
34
+ # Initialize class-level storage for A2A methods and capabilities
35
+ if defined?(ActiveSupport) && base.respond_to?(:class_attribute)
36
+ # Use ActiveSupport's class_attribute if available
37
+ base.class_attribute :_a2a_methods, default: {}
38
+ base.class_attribute :_a2a_capabilities, default: A2A::Protocol::CapabilityRegistry.new
39
+ base.class_attribute :_a2a_config, default: {}
40
+ base.class_attribute :_a2a_middleware, default: []
41
+ else
42
+ # Fallback implementation without ActiveSupport
43
+ base.instance_variable_set(:@_a2a_methods, {})
44
+ base.instance_variable_set(:@_a2a_capabilities, A2A::Protocol::CapabilityRegistry.new)
45
+ base.instance_variable_set(:@_a2a_config, {})
46
+ base.instance_variable_set(:@_a2a_middleware, [])
47
+
48
+ # Define accessor methods
49
+ base.define_singleton_method(:_a2a_methods) { @_a2a_methods }
50
+ base.define_singleton_method(:_a2a_capabilities) { @_a2a_capabilities }
51
+ base.define_singleton_method(:_a2a_config) { @_a2a_config }
52
+ base.define_singleton_method(:_a2a_middleware) { @_a2a_middleware }
53
+ end
54
+ end
55
+
56
+ module ClassMethods
57
+ ##
58
+ # Define an A2A method that can be called via JSON-RPC
59
+ #
60
+ # @param name [String] The method name
61
+ # @param options [Hash] Method options
62
+ # @option options [Boolean] :streaming Whether the method supports streaming
63
+ # @option options [Boolean] :async Whether the method supports async execution
64
+ # @option options [Array<String>] :security Required security schemes
65
+ # @option options [Hash] :metadata Additional method metadata
66
+ # @yield [params, context] The method implementation block
67
+ # @yieldparam params [Hash] The method parameters
68
+ # @yieldparam context [A2A::Server::Context] The request context
69
+ # @yieldreturn [Object] The method result
70
+ #
71
+ # @example Define a simple method
72
+ # a2a_method "echo" do |params|
73
+ # { message: params['message'] }
74
+ # end
75
+ #
76
+ # @example Define a streaming method
77
+ # a2a_method "stream_data", streaming: true do |params, context|
78
+ # Enumerator.new do |yielder|
79
+ # 10.times do |i|
80
+ # yielder << { count: i }
81
+ # sleep 0.1
82
+ # end
83
+ # end
84
+ # end
85
+ #
86
+ def a2a_method(name, **options, &block)
87
+ if name.nil? || (respond_to?(:empty?) && empty?) || (is_a?(String) && strip.empty?)
88
+ raise ArgumentError,
89
+ "Method name is required"
90
+ end
91
+ raise ArgumentError, "Method block is required" unless block_given?
92
+
93
+ method_name = name.to_s
94
+
95
+ _a2a_methods[method_name] = {
96
+ handler: block,
97
+ options: options.dup,
98
+ streaming: options[:streaming] || false,
99
+ async: options[:async] || false,
100
+ security: options[:security] || [],
101
+ metadata: options[:metadata] || {}
102
+ }
103
+ end
104
+
105
+ ##
106
+ # Define a capability using the DSL
107
+ #
108
+ # @param name [String] The capability name
109
+ # @yield Block for capability definition
110
+ #
111
+ # @example Define a capability
112
+ # a2a_capability "text_analysis" do
113
+ # method "analyze_text"
114
+ # description "Analyze text for sentiment and topics"
115
+ # input_schema type: "object", properties: { text: { type: "string" } }
116
+ # output_schema type: "object", properties: { sentiment: { type: "string" } }
117
+ # tags ["nlp", "analysis"]
118
+ # streaming_supported true
119
+ # end
120
+ #
121
+ def a2a_capability(name, &block)
122
+ if name.nil? || (respond_to?(:empty?) && empty?) || (is_a?(String) && strip.empty?)
123
+ raise ArgumentError,
124
+ "Capability name is required"
125
+ end
126
+ raise ArgumentError, "Capability block is required" unless block_given?
127
+
128
+ builder = CapabilityBuilder.new(name.to_s)
129
+ builder.instance_eval(&block)
130
+ capability = builder.build
131
+
132
+ _a2a_capabilities.register(capability)
133
+ capability
134
+ end
135
+
136
+ ##
137
+ # Configure the agent
138
+ #
139
+ # @param options [Hash] Configuration options
140
+ # @option options [String] :name Agent name
141
+ # @option options [String] :description Agent description
142
+ # @option options [String] :version Agent version
143
+ # @option options [Array<String>] :default_input_modes Default input modes
144
+ # @option options [Array<String>] :default_output_modes Default output modes
145
+ # @option options [Hash] :metadata Additional metadata
146
+ #
147
+ # @example Configure agent
148
+ # a2a_config name: "My Agent",
149
+ # description: "A helpful agent",
150
+ # version: "1.0.0"
151
+ #
152
+ def a2a_config(**options)
153
+ _a2a_config.merge!(options)
154
+ end
155
+
156
+ ##
157
+ # Add middleware to the agent
158
+ #
159
+ # @param middleware_class [Class] The middleware class
160
+ # @param options [Hash] Middleware options
161
+ #
162
+ # @example Add authentication middleware
163
+ # a2a_middleware AuthenticationMiddleware, required: true
164
+ #
165
+ def a2a_middleware(middleware_class, **options)
166
+ _a2a_middleware << { class: middleware_class, options: options }
167
+ end
168
+
169
+ ##
170
+ # Get all registered A2A methods
171
+ #
172
+ # @return [Hash] Hash of method name to method definition
173
+ def a2a_method_registry
174
+ _a2a_methods.dup
175
+ end
176
+
177
+ ##
178
+ # Get the capability registry
179
+ #
180
+ # @return [A2A::Protocol::CapabilityRegistry] The capability registry
181
+ def a2a_capability_registry
182
+ _a2a_capabilities
183
+ end
184
+
185
+ ##
186
+ # Check if a method is registered
187
+ #
188
+ # @param name [String] The method name
189
+ # @return [Boolean] True if the method is registered
190
+ def a2a_method_registered?(name)
191
+ _a2a_methods.key?(name.to_s)
192
+ end
193
+
194
+ ##
195
+ # Get method definition
196
+ #
197
+ # @param name [String] The method name
198
+ # @return [Hash, nil] The method definition or nil if not found
199
+ def a2a_method_definition(name)
200
+ _a2a_methods[name.to_s]
201
+ end
202
+ end
203
+
204
+ ##
205
+ # Handle an A2A JSON-RPC request
206
+ #
207
+ # @param request [A2A::Protocol::Request] The JSON-RPC request
208
+ # @param context [A2A::Server::Context, nil] The request context
209
+ # @return [Hash] The JSON-RPC response
210
+ def handle_a2a_request(request, context: nil)
211
+ method_name = request.method
212
+ method_def = self.class.a2a_method_definition(method_name)
213
+
214
+ raise A2A::Errors::MethodNotFound, "Method '#{method_name}' not found" unless method_def
215
+
216
+ # Create context if not provided
217
+ context ||= A2A::Server::Context.new(request: request)
218
+
219
+ # Validate security requirements
220
+ validate_security_requirements(method_def, context)
221
+
222
+ # Execute with middleware chain
223
+ result = execute_with_middleware(method_def, request.params, context)
224
+
225
+ # Build response
226
+ A2A::Protocol::JsonRpc.build_response(result: result, id: request.id) unless request.notification?
227
+ rescue A2A::Errors::A2AError => e
228
+ # Return error response for A2A errors
229
+ unless request.notification?
230
+ A2A::Protocol::JsonRpc.build_error_response(
231
+ code: e.code,
232
+ message: e.message,
233
+ data: e.data,
234
+ id: request.id
235
+ )
236
+ end
237
+ rescue StandardError => e
238
+ # Convert other errors to internal errors
239
+ unless request.notification?
240
+ A2A::Protocol::JsonRpc.build_error_response(
241
+ code: A2A::Protocol::JsonRpc::INTERNAL_ERROR,
242
+ message: e.message,
243
+ id: request.id
244
+ )
245
+ end
246
+ end
247
+
248
+ ##
249
+ # Execute a method with the middleware chain
250
+ #
251
+ # @param method_def [Hash] The method definition
252
+ # @param params [Hash] The method parameters
253
+ # @param context [A2A::Server::Context] The request context
254
+ # @return [Object] The method result
255
+ def execute_with_middleware(method_def, params, context)
256
+ # Build middleware chain
257
+ middleware_chain = build_middleware_chain(method_def, context)
258
+
259
+ # Execute the chain
260
+ middleware_chain.call(params) do
261
+ # Execute the actual method
262
+ execute_method(method_def, params, context)
263
+ end
264
+ end
265
+
266
+ ##
267
+ # Execute the actual method implementation
268
+ #
269
+ # @param method_def [Hash] The method definition
270
+ # @param params [Hash] The method parameters
271
+ # @param context [A2A::Server::Context] The request context
272
+ # @return [Object] The method result
273
+ def execute_method(method_def, params, context)
274
+ handler = method_def[:handler]
275
+
276
+ # Call the handler with appropriate parameters
277
+ case handler.arity
278
+ when 0
279
+ instance_exec(&handler)
280
+ when 1
281
+ instance_exec(params, &handler)
282
+ when 2
283
+ instance_exec(params, context, &handler)
284
+ else
285
+ # For methods with more parameters, pass params and context
286
+ instance_exec(params, context, &handler)
287
+ end
288
+ end
289
+
290
+ private
291
+
292
+ ##
293
+ # Validate security requirements for a method
294
+ #
295
+ # @param method_def [Hash] The method definition
296
+ # @param context [A2A::Server::Context] The request context
297
+ # @raise [A2A::Errors::AuthenticationRequired] If authentication is required but missing
298
+ # @raise [A2A::Errors::AuthorizationFailed] If authorization fails
299
+ def validate_security_requirements(method_def, context)
300
+ security_requirements = method_def[:security] || []
301
+ return if security_requirements.empty?
302
+
303
+ # Check if any required security scheme is satisfied
304
+ satisfied = security_requirements.any? do |scheme|
305
+ context.authenticated_with?(scheme)
306
+ end
307
+
308
+ return if satisfied
309
+
310
+ if context.authenticated?
311
+ raise A2A::Errors::AuthorizationFailed, "Method requires one of: #{security_requirements.join(', ')}"
312
+ end
313
+
314
+ raise A2A::Errors::AuthenticationRequired,
315
+ "Method requires authentication with: #{security_requirements.join(', ')}"
316
+ end
317
+
318
+ ##
319
+ # Build the middleware chain for method execution
320
+ #
321
+ # @param method_def [Hash] The method definition
322
+ # @param context [A2A::Server::Context] The request context
323
+ # @return [Proc] The middleware chain
324
+ def build_middleware_chain(_method_def, context)
325
+ # Combine class-level and method-level middleware
326
+ all_middleware = self.class._a2a_middleware.dup
327
+
328
+ # Build the chain from the inside out
329
+ chain = ->(_params, &block) { block.call }
330
+
331
+ all_middleware.reverse_each do |middleware_def|
332
+ middleware_class = middleware_def[:class]
333
+ middleware_options = middleware_def[:options]
334
+
335
+ # Create middleware instance
336
+ middleware = middleware_class.new(**middleware_options)
337
+
338
+ # Wrap the current chain
339
+ current_chain = chain
340
+ chain = lambda do |params, &block|
341
+ middleware.call(params, context) do
342
+ current_chain.call(params, &block)
343
+ end
344
+ end
345
+ end
346
+
347
+ chain
348
+ end
349
+ end
350
+
351
+ ##
352
+ # Builder class for capability DSL
353
+ #
354
+ class CapabilityBuilder
355
+ def initialize(name)
356
+ @name = name
357
+ @attributes = {}
358
+ end
359
+
360
+ ##
361
+ # Set the method name for this capability
362
+ #
363
+ # @param method_name [String, Symbol] The A2A method name
364
+ def method(method_name)
365
+ @attributes[:method] = method_name.to_s
366
+ end
367
+
368
+ ##
369
+ # Set the capability description
370
+ #
371
+ # @param desc [String] The description
372
+ def description(desc)
373
+ @attributes[:description] = desc
374
+ end
375
+
376
+ ##
377
+ # Set the input schema
378
+ #
379
+ # @param schema [Hash] The JSON Schema for input validation
380
+ def input_schema(schema)
381
+ @attributes[:input_schema] = schema
382
+ end
383
+
384
+ ##
385
+ # Set the output schema
386
+ #
387
+ # @param schema [Hash] The JSON Schema for output validation
388
+ def output_schema(schema)
389
+ @attributes[:output_schema] = schema
390
+ end
391
+
392
+ ##
393
+ # Set capability tags
394
+ #
395
+ # @param tag_list [Array<String>] List of tags
396
+ def tags(tag_list)
397
+ @attributes[:tags] = tag_list
398
+ end
399
+
400
+ ##
401
+ # Set security requirements
402
+ #
403
+ # @param requirements [Array<String>] List of required security schemes
404
+ def security_requirements(requirements)
405
+ @attributes[:security_requirements] = requirements
406
+ end
407
+
408
+ ##
409
+ # Set additional metadata
410
+ #
411
+ # @param meta [Hash] Metadata hash
412
+ def metadata(meta)
413
+ @attributes[:metadata] = meta
414
+ end
415
+
416
+ ##
417
+ # Set streaming support
418
+ #
419
+ # @param supported [Boolean] Whether streaming is supported
420
+ def streaming_supported(supported = true)
421
+ @attributes[:streaming_supported] = supported
422
+ end
423
+
424
+ ##
425
+ # Set async support
426
+ #
427
+ # @param supported [Boolean] Whether async execution is supported
428
+ def async_supported(supported = true)
429
+ @attributes[:async_supported] = supported
430
+ end
431
+
432
+ ##
433
+ # Add an example
434
+ #
435
+ # @param example [Hash] Example with input/output/description
436
+ def example(example)
437
+ @attributes[:examples] ||= []
438
+ @attributes[:examples] << example
439
+ end
440
+
441
+ ##
442
+ # Build the capability
443
+ #
444
+ # @return [A2A::Protocol::Capability] The built capability
445
+ def build
446
+ A2A::Protocol::Capability.new(
447
+ name: @name,
448
+ **@attributes
449
+ )
450
+ end
451
+ end
452
+
453
+ ##
454
+ # Request context for A2A method execution
455
+ #
456
+ class Context
457
+ attr_reader :request, :user, :session, :metadata
458
+
459
+ def initialize(request: nil, user: nil, session: nil, metadata: {})
460
+ @request = request
461
+ @user = user
462
+ @session = session
463
+ @metadata = metadata
464
+ @auth_schemes = {}
465
+ end
466
+
467
+ ##
468
+ # Check if the request is authenticated
469
+ #
470
+ # @return [Boolean] True if authenticated
471
+ def authenticated?
472
+ !@auth_schemes.empty?
473
+ end
474
+
475
+ ##
476
+ # Check if authenticated with a specific scheme
477
+ #
478
+ # @param scheme [String] The security scheme name
479
+ # @return [Boolean] True if authenticated with the scheme
480
+ def authenticated_with?(scheme)
481
+ @auth_schemes.key?(scheme)
482
+ end
483
+
484
+ ##
485
+ # Set authentication for a scheme
486
+ #
487
+ # @param scheme [String] The security scheme name
488
+ # @param data [Object] Authentication data
489
+ def set_authentication(scheme, data)
490
+ @auth_schemes[scheme] = data
491
+ end
492
+
493
+ ##
494
+ # Get authentication data for a scheme
495
+ #
496
+ # @param scheme [String] The security scheme name
497
+ # @return [Object, nil] The authentication data
498
+ def get_authentication(scheme)
499
+ @auth_schemes[scheme]
500
+ end
501
+
502
+ ##
503
+ # Set user information
504
+ #
505
+ # @param user [Object] User object or identifier
506
+ def set_user(user)
507
+ @user = user
508
+ end
509
+
510
+ ##
511
+ # Set session information
512
+ #
513
+ # @param session [Object] Session object or identifier
514
+ def set_session(session)
515
+ @session = session
516
+ end
517
+
518
+ ##
519
+ # Set metadata
520
+ #
521
+ # @param key [String, Symbol] Metadata key
522
+ # @param value [Object] Metadata value
523
+ def set_metadata(key, value)
524
+ @metadata[key] = value
525
+ end
526
+
527
+ ##
528
+ # Get metadata
529
+ #
530
+ # @param key [String, Symbol] Metadata key
531
+ # @return [Object, nil] Metadata value
532
+ def get_metadata(key)
533
+ @metadata[key]
534
+ end
535
+ end
536
+ end
537
+ end