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/docs/integration.md
ADDED
@@ -0,0 +1,262 @@
|
|
1
|
+
# Framework Integration Guide
|
2
|
+
|
3
|
+
This guide covers integrating the A2A Ruby SDK with different Ruby frameworks.
|
4
|
+
|
5
|
+
## Rails Integration
|
6
|
+
|
7
|
+
### Installation
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
# Gemfile
|
11
|
+
gem 'a2a-ruby'
|
12
|
+
```
|
13
|
+
|
14
|
+
### Setup
|
15
|
+
|
16
|
+
```ruby
|
17
|
+
# config/routes.rb
|
18
|
+
Rails.application.routes.draw do
|
19
|
+
mount A2A::Engine => "/a2a"
|
20
|
+
end
|
21
|
+
|
22
|
+
# config/application.rb or config/environments/production.rb
|
23
|
+
A2A.configure do |config|
|
24
|
+
config.protocol_version = "0.3.0"
|
25
|
+
config.default_transport = "JSONRPC"
|
26
|
+
config.streaming_enabled = true
|
27
|
+
end
|
28
|
+
```
|
29
|
+
|
30
|
+
### Creating Agents
|
31
|
+
|
32
|
+
```ruby
|
33
|
+
# app/controllers/agent_controller.rb
|
34
|
+
class AgentController < ApplicationController
|
35
|
+
include A2A::Server::Agent
|
36
|
+
|
37
|
+
# Define agent capabilities
|
38
|
+
a2a_skill "greeting" do |skill|
|
39
|
+
skill.description = "Greet users in different languages"
|
40
|
+
skill.examples = ["Hello", "Say hi in Spanish"]
|
41
|
+
end
|
42
|
+
|
43
|
+
# Define A2A methods
|
44
|
+
a2a_method "greet" do |params|
|
45
|
+
language = params[:language] || "en"
|
46
|
+
name = params[:name] || "there"
|
47
|
+
|
48
|
+
greeting = case language
|
49
|
+
when "es" then "¡Hola"
|
50
|
+
when "fr" then "Bonjour"
|
51
|
+
else "Hello"
|
52
|
+
end
|
53
|
+
|
54
|
+
{ message: "#{greeting}, #{name}!" }
|
55
|
+
end
|
56
|
+
|
57
|
+
# Streaming responses
|
58
|
+
a2a_method "chat", streaming: true do |params|
|
59
|
+
Enumerator.new do |yielder|
|
60
|
+
# Process and stream response
|
61
|
+
response = process_chat(params[:message])
|
62
|
+
yielder << A2A::Types::Message.new(
|
63
|
+
message_id: SecureRandom.uuid,
|
64
|
+
role: "agent",
|
65
|
+
parts: [A2A::Types::TextPart.new(text: response)]
|
66
|
+
)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
private
|
71
|
+
|
72
|
+
def process_chat(message)
|
73
|
+
# Your chat processing logic
|
74
|
+
"You said: #{message}"
|
75
|
+
end
|
76
|
+
end
|
77
|
+
```
|
78
|
+
|
79
|
+
## Sinatra Integration
|
80
|
+
|
81
|
+
### Basic Setup
|
82
|
+
|
83
|
+
```ruby
|
84
|
+
# app.rb
|
85
|
+
require 'sinatra'
|
86
|
+
require 'a2a'
|
87
|
+
|
88
|
+
# Configure A2A
|
89
|
+
A2A.configure do |config|
|
90
|
+
config.protocol_version = "0.3.0"
|
91
|
+
config.default_transport = "JSONRPC"
|
92
|
+
end
|
93
|
+
|
94
|
+
class MyAgent
|
95
|
+
include A2A::Server::Agent
|
96
|
+
|
97
|
+
a2a_method "echo" do |params|
|
98
|
+
{ message: "Echo: #{params[:text]}" }
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
# Mount A2A endpoints
|
103
|
+
post '/a2a/rpc' do
|
104
|
+
content_type :json
|
105
|
+
agent = MyAgent.new
|
106
|
+
agent.handle_request(request.body.read)
|
107
|
+
end
|
108
|
+
|
109
|
+
get '/a2a/agent-card' do
|
110
|
+
content_type :json
|
111
|
+
MyAgent.new.generate_agent_card.to_json
|
112
|
+
end
|
113
|
+
```
|
114
|
+
|
115
|
+
## Plain Ruby Integration
|
116
|
+
|
117
|
+
### Standalone Agent
|
118
|
+
|
119
|
+
```ruby
|
120
|
+
#!/usr/bin/env ruby
|
121
|
+
require 'a2a'
|
122
|
+
|
123
|
+
class StandaloneAgent
|
124
|
+
include A2A::Server::Agent
|
125
|
+
|
126
|
+
a2a_method "process" do |params|
|
127
|
+
# Your processing logic
|
128
|
+
{ result: "Processed: #{params[:input]}" }
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
# Start HTTP server
|
133
|
+
require 'webrick'
|
134
|
+
|
135
|
+
server = WEBrick::HTTPServer.new(Port: 8080)
|
136
|
+
agent = StandaloneAgent.new
|
137
|
+
|
138
|
+
server.mount_proc '/a2a/rpc' do |req, res|
|
139
|
+
if req.request_method == 'POST'
|
140
|
+
res.content_type = 'application/json'
|
141
|
+
res.body = agent.handle_request(req.body)
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
trap('INT') { server.shutdown }
|
146
|
+
server.start
|
147
|
+
```
|
148
|
+
|
149
|
+
### Client Usage
|
150
|
+
|
151
|
+
```ruby
|
152
|
+
require 'a2a'
|
153
|
+
|
154
|
+
# Create client
|
155
|
+
client = A2A::Client::HttpClient.new("http://localhost:8080/a2a")
|
156
|
+
|
157
|
+
# Send message
|
158
|
+
message = A2A::Types::Message.new(
|
159
|
+
message_id: SecureRandom.uuid,
|
160
|
+
role: "user",
|
161
|
+
parts: [A2A::Types::TextPart.new(text: "Hello!")]
|
162
|
+
)
|
163
|
+
|
164
|
+
response = client.send_message(message)
|
165
|
+
puts response.inspect
|
166
|
+
```
|
167
|
+
|
168
|
+
## Testing
|
169
|
+
|
170
|
+
### RSpec Integration
|
171
|
+
|
172
|
+
```ruby
|
173
|
+
# spec/spec_helper.rb
|
174
|
+
require 'a2a'
|
175
|
+
require 'a2a/testing'
|
176
|
+
|
177
|
+
RSpec.configure do |config|
|
178
|
+
config.include A2A::Testing::Helpers
|
179
|
+
end
|
180
|
+
|
181
|
+
# spec/agents/my_agent_spec.rb
|
182
|
+
RSpec.describe MyAgent do
|
183
|
+
include A2A::Testing::Helpers
|
184
|
+
|
185
|
+
it "responds to greet method" do
|
186
|
+
agent = MyAgent.new
|
187
|
+
response = agent.call_a2a_method("greet", name: "World")
|
188
|
+
|
189
|
+
expect(response[:message]).to eq("Hello, World!")
|
190
|
+
end
|
191
|
+
|
192
|
+
it "handles streaming responses" do
|
193
|
+
agent = MyAgent.new
|
194
|
+
responses = []
|
195
|
+
|
196
|
+
agent.call_a2a_method("chat", message: "Hi") do |response|
|
197
|
+
responses << response
|
198
|
+
end
|
199
|
+
|
200
|
+
expect(responses).not_to be_empty
|
201
|
+
end
|
202
|
+
end
|
203
|
+
```
|
204
|
+
|
205
|
+
## Common Patterns
|
206
|
+
|
207
|
+
### Error Handling
|
208
|
+
|
209
|
+
```ruby
|
210
|
+
a2a_method "risky_operation" do |params|
|
211
|
+
begin
|
212
|
+
# Your operation
|
213
|
+
{ success: true }
|
214
|
+
rescue StandardError => e
|
215
|
+
raise A2A::Errors::InternalError, "Operation failed: #{e.message}"
|
216
|
+
end
|
217
|
+
end
|
218
|
+
```
|
219
|
+
|
220
|
+
### Authentication
|
221
|
+
|
222
|
+
```ruby
|
223
|
+
class SecureAgent
|
224
|
+
include A2A::Server::Agent
|
225
|
+
|
226
|
+
before_a2a_method do |context|
|
227
|
+
unless context.authenticated?
|
228
|
+
raise A2A::Errors::AuthenticationRequired, "Authentication required"
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
a2a_method "secure_operation" do |params|
|
233
|
+
# Only authenticated requests reach here
|
234
|
+
{ result: "Success" }
|
235
|
+
end
|
236
|
+
end
|
237
|
+
```
|
238
|
+
|
239
|
+
### Background Processing
|
240
|
+
|
241
|
+
```ruby
|
242
|
+
# With Sidekiq (Rails)
|
243
|
+
a2a_method "long_task", async: true do |params|
|
244
|
+
LongTaskWorker.perform_async(params[:task_id], params[:data])
|
245
|
+
{ task_id: params[:task_id], status: "queued" }
|
246
|
+
end
|
247
|
+
|
248
|
+
class LongTaskWorker
|
249
|
+
include Sidekiq::Worker
|
250
|
+
|
251
|
+
def perform(task_id, data)
|
252
|
+
# Process task
|
253
|
+
result = process_data(data)
|
254
|
+
|
255
|
+
# Update task status
|
256
|
+
A2A::TaskManager.update_task(task_id,
|
257
|
+
status: "completed",
|
258
|
+
result: result
|
259
|
+
)
|
260
|
+
end
|
261
|
+
end
|
262
|
+
```
|