agent2agent 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/data/a2a.json +1961 -0
- data/data/a2a.proto +796 -0
- data/data/download-a2a-resources +4 -0
- data/data/spec.txt +3611 -0
- data/lib/a2a/agent.rb +243 -0
- data/lib/a2a/bindings/json_rpc.rb +110 -0
- data/lib/a2a/bindings/rest.rb +106 -0
- data/lib/a2a/client.rb +85 -0
- data/lib/a2a/proto.rb +444 -0
- data/lib/a2a/schema/definition.rb +114 -0
- data/lib/a2a/schema/validation_error.rb +129 -0
- data/lib/a2a/schema.rb +429 -0
- data/lib/a2a/server/cancel_task.rb +14 -0
- data/lib/a2a/server/create_task_push_notification_config.rb +14 -0
- data/lib/a2a/server/delete_task_push_notification_config.rb +14 -0
- data/lib/a2a/server/dispatcher.rb +127 -0
- data/lib/a2a/server/env.rb +28 -0
- data/lib/a2a/server/get_extended_agent_card.rb +15 -0
- data/lib/a2a/server/get_task.rb +14 -0
- data/lib/a2a/server/get_task_push_notification_config.rb +14 -0
- data/lib/a2a/server/list_task_push_notification_configs.rb +14 -0
- data/lib/a2a/server/list_tasks.rb +14 -0
- data/lib/a2a/server/send_message.rb +14 -0
- data/lib/a2a/server/send_streaming_message.rb +14 -0
- data/lib/a2a/server/subscribe_to_task.rb +14 -0
- data/lib/a2a/server/triage.rb +96 -0
- data/lib/a2a/server.rb +98 -0
- data/lib/a2a/sse/json_rpc_stream.rb +66 -0
- data/lib/a2a/sse/rest_stream.rb +50 -0
- data/lib/a2a/sse/stream.rb +129 -0
- data/lib/a2a/sse.rb +5 -0
- data/lib/a2a/store/processor.rb +136 -0
- data/lib/a2a/store/pub_sub.rb +149 -0
- data/lib/a2a/store/sqlite.rb +533 -0
- data/lib/a2a/store/webhooks.rb +94 -0
- data/lib/a2a/store.rb +6 -0
- data/lib/a2a/task_store.rb +315 -0
- data/lib/a2a/version.rb +5 -0
- data/lib/a2a.rb +26 -0
- metadata +216 -0
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "async"
|
|
4
|
+
require "async/http/internet"
|
|
5
|
+
require "json"
|
|
6
|
+
require "console"
|
|
7
|
+
|
|
8
|
+
module A2A
|
|
9
|
+
module Store
|
|
10
|
+
# Async webhook delivery for A2A push notifications.
|
|
11
|
+
#
|
|
12
|
+
# Following the gospel (async-http):
|
|
13
|
+
# - Uses Async::HTTP::Internet for non-blocking HTTP requests
|
|
14
|
+
# - Each delivery runs in its own Async task (fiber, not thread)
|
|
15
|
+
# - Failures are logged but do not propagate
|
|
16
|
+
#
|
|
17
|
+
# The A2A spec says:
|
|
18
|
+
# - Push notification payloads use StreamResponse format
|
|
19
|
+
# - Content-Type: application/a2a+json
|
|
20
|
+
# - Authentication via scheme + credentials from the config
|
|
21
|
+
# - Token header: X-A2A-Notification-Token
|
|
22
|
+
# - Delivery is at-least-once with possible retries
|
|
23
|
+
#
|
|
24
|
+
class Webhooks
|
|
25
|
+
def initialize
|
|
26
|
+
@internet = nil
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Deliver a payload to all push notification configs for a task.
|
|
30
|
+
#
|
|
31
|
+
# @param configs [Array<Hash>] push notification configs
|
|
32
|
+
# @param payload [Hash] the StreamResponse payload
|
|
33
|
+
#
|
|
34
|
+
def deliver(configs, payload)
|
|
35
|
+
return if configs.nil? || configs.empty?
|
|
36
|
+
|
|
37
|
+
configs.each do |config|
|
|
38
|
+
Async do
|
|
39
|
+
deliver_single(config, payload)
|
|
40
|
+
rescue => e
|
|
41
|
+
Console.error(self) { "Webhook delivery failed for #{config["url"]}: #{e.message}" }
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
private
|
|
47
|
+
|
|
48
|
+
def internet
|
|
49
|
+
@internet ||= Async::HTTP::Internet.new
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def deliver_single(config, payload)
|
|
53
|
+
url = config["url"]
|
|
54
|
+
return unless url && !url.empty?
|
|
55
|
+
|
|
56
|
+
headers = {
|
|
57
|
+
"content-type" => "application/a2a+json",
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
# Authentication
|
|
61
|
+
if (auth = config["authentication"])
|
|
62
|
+
scheme = auth["scheme"] || "Bearer"
|
|
63
|
+
creds = auth["credentials"] || ""
|
|
64
|
+
headers["authorization"] = "#{scheme} #{creds}"
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# Token header
|
|
68
|
+
if (token = config["token"])
|
|
69
|
+
headers["x-a2a-notification-token"] = token
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
body = JSON.generate(payload)
|
|
73
|
+
|
|
74
|
+
internet.post(url, headers, [body])
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
test do
|
|
81
|
+
describe "A2A::Store::Webhooks" do
|
|
82
|
+
it "can be instantiated" do
|
|
83
|
+
wh = A2A::Store::Webhooks.new
|
|
84
|
+
wh.should.not.be.nil
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
it "silently skips empty config lists" do
|
|
88
|
+
wh = A2A::Store::Webhooks.new
|
|
89
|
+
# Should not raise — returns nil for empty/nil configs
|
|
90
|
+
wh.deliver([], { "statusUpdate" => {} }).should.be.nil
|
|
91
|
+
wh.deliver(nil, { "statusUpdate" => {} }).should.be.nil
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|
data/lib/a2a/store.rb
ADDED
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "bundler/setup"
|
|
4
|
+
require "a2a"
|
|
5
|
+
require "securerandom"
|
|
6
|
+
require "net/http"
|
|
7
|
+
require "uri"
|
|
8
|
+
require "json"
|
|
9
|
+
|
|
10
|
+
module A2A
|
|
11
|
+
Task = Struct.new(
|
|
12
|
+
:id, :context_id, :state, :result, :artifacts, :history,
|
|
13
|
+
:push_configs, :subscribers, :created_at, :updated_at,
|
|
14
|
+
keyword_init: true
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
# In-memory task registry with pub/sub for streaming and webhook delivery.
|
|
18
|
+
# Swap for a DB-backed implementation in production --
|
|
19
|
+
# if the server crashes, in-memory tasks vanish and the client never gets notified.
|
|
20
|
+
class TaskStore
|
|
21
|
+
TERMINAL_STATES = %w[
|
|
22
|
+
TASK_STATE_COMPLETED TASK_STATE_FAILED
|
|
23
|
+
TASK_STATE_CANCELED TASK_STATE_REJECTED
|
|
24
|
+
].freeze
|
|
25
|
+
|
|
26
|
+
def initialize
|
|
27
|
+
@tasks = {}
|
|
28
|
+
@mutex = Mutex.new
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# ── Task CRUD ──────────────────────────────────────────────────────
|
|
32
|
+
|
|
33
|
+
def create(id, context_id, push_config = nil)
|
|
34
|
+
@mutex.synchronize do
|
|
35
|
+
now = Time.now.utc
|
|
36
|
+
configs = {}
|
|
37
|
+
if push_config
|
|
38
|
+
cfg_id = push_config["id"] || SecureRandom.uuid
|
|
39
|
+
push_config["id"] = cfg_id
|
|
40
|
+
configs[cfg_id] = push_config
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
@tasks[id] = Task.new(
|
|
44
|
+
id: id,
|
|
45
|
+
context_id: context_id,
|
|
46
|
+
state: "TASK_STATE_SUBMITTED",
|
|
47
|
+
result: nil,
|
|
48
|
+
artifacts: [],
|
|
49
|
+
history: [],
|
|
50
|
+
push_configs: configs,
|
|
51
|
+
subscribers: [],
|
|
52
|
+
created_at: now,
|
|
53
|
+
updated_at: now,
|
|
54
|
+
)
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def get(id)
|
|
59
|
+
@mutex.synchronize { @tasks[id] }
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def update_state(id, state, message: nil)
|
|
63
|
+
task = nil
|
|
64
|
+
@mutex.synchronize do
|
|
65
|
+
task = @tasks[id]
|
|
66
|
+
return nil unless task
|
|
67
|
+
task.state = state
|
|
68
|
+
task.updated_at = Time.now.utc
|
|
69
|
+
end
|
|
70
|
+
if task
|
|
71
|
+
event = build_status_event(task, message)
|
|
72
|
+
notify_subscribers(task, event)
|
|
73
|
+
deliver_webhooks(task, { "statusUpdate" => event })
|
|
74
|
+
end
|
|
75
|
+
task
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def complete(id, result)
|
|
79
|
+
task = nil
|
|
80
|
+
@mutex.synchronize do
|
|
81
|
+
task = @tasks[id]
|
|
82
|
+
return nil unless task
|
|
83
|
+
task.state = "TASK_STATE_COMPLETED"
|
|
84
|
+
task.result = result
|
|
85
|
+
task.updated_at = Time.now.utc
|
|
86
|
+
end
|
|
87
|
+
if task
|
|
88
|
+
event = build_status_event(task)
|
|
89
|
+
notify_subscribers(task, event)
|
|
90
|
+
deliver_webhooks(task, { "statusUpdate" => event })
|
|
91
|
+
close_subscribers(task)
|
|
92
|
+
end
|
|
93
|
+
task
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def fail(id, msg)
|
|
97
|
+
task = nil
|
|
98
|
+
@mutex.synchronize do
|
|
99
|
+
task = @tasks[id]
|
|
100
|
+
return nil unless task
|
|
101
|
+
task.state = "TASK_STATE_FAILED"
|
|
102
|
+
task.result = msg
|
|
103
|
+
task.updated_at = Time.now.utc
|
|
104
|
+
end
|
|
105
|
+
if task
|
|
106
|
+
event = build_status_event(task)
|
|
107
|
+
notify_subscribers(task, event)
|
|
108
|
+
deliver_webhooks(task, { "statusUpdate" => event })
|
|
109
|
+
close_subscribers(task)
|
|
110
|
+
end
|
|
111
|
+
task
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def cancel(id)
|
|
115
|
+
update_state(id, "TASK_STATE_CANCELED")
|
|
116
|
+
task = get(id)
|
|
117
|
+
close_subscribers(task) if task
|
|
118
|
+
task
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def terminal?(id)
|
|
122
|
+
task = get(id)
|
|
123
|
+
task && TERMINAL_STATES.include?(task.state)
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
# ── Artifacts ──────────────────────────────────────────────────────
|
|
127
|
+
|
|
128
|
+
def add_artifact(id, artifact)
|
|
129
|
+
task = nil
|
|
130
|
+
@mutex.synchronize do
|
|
131
|
+
task = @tasks[id]
|
|
132
|
+
return nil unless task
|
|
133
|
+
task.artifacts << artifact
|
|
134
|
+
task.updated_at = Time.now.utc
|
|
135
|
+
end
|
|
136
|
+
if task
|
|
137
|
+
event = {
|
|
138
|
+
"taskId" => task.id,
|
|
139
|
+
"contextId" => task.context_id,
|
|
140
|
+
"artifact" => artifact,
|
|
141
|
+
"append" => false,
|
|
142
|
+
"lastChunk" => true,
|
|
143
|
+
}
|
|
144
|
+
notify_subscribers(task, event, type: :artifact)
|
|
145
|
+
deliver_webhooks(task, { "artifactUpdate" => event })
|
|
146
|
+
end
|
|
147
|
+
task
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
# ── History ────────────────────────────────────────────────────────
|
|
151
|
+
|
|
152
|
+
def add_message(id, msg)
|
|
153
|
+
@mutex.synchronize do
|
|
154
|
+
task = @tasks[id]
|
|
155
|
+
return nil unless task
|
|
156
|
+
task.history << msg
|
|
157
|
+
task.updated_at = Time.now.utc
|
|
158
|
+
task
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
# ── Listing ────────────────────────────────────────────────────────
|
|
163
|
+
|
|
164
|
+
def list(context_id: nil, state: nil)
|
|
165
|
+
@mutex.synchronize do
|
|
166
|
+
@tasks.values
|
|
167
|
+
.select { |t| context_id.nil? || t.context_id == context_id }
|
|
168
|
+
.select { |t| state.nil? || t.state == state }
|
|
169
|
+
.sort_by { |t| t.updated_at }
|
|
170
|
+
.reverse
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
# ── Push Notification Config CRUD ──────────────────────────────────
|
|
175
|
+
|
|
176
|
+
def create_push_config(task_id, config)
|
|
177
|
+
@mutex.synchronize do
|
|
178
|
+
task = @tasks[task_id]
|
|
179
|
+
return nil unless task
|
|
180
|
+
cfg_id = config["id"] || SecureRandom.uuid
|
|
181
|
+
config["id"] = cfg_id
|
|
182
|
+
config["taskId"] = task_id
|
|
183
|
+
task.push_configs[cfg_id] = config
|
|
184
|
+
task.updated_at = Time.now.utc
|
|
185
|
+
config
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
def get_push_config(task_id, config_id)
|
|
190
|
+
@mutex.synchronize do
|
|
191
|
+
task = @tasks[task_id]
|
|
192
|
+
return nil unless task
|
|
193
|
+
task.push_configs[config_id]
|
|
194
|
+
end
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
def list_push_configs(task_id)
|
|
198
|
+
@mutex.synchronize do
|
|
199
|
+
task = @tasks[task_id]
|
|
200
|
+
return [] unless task
|
|
201
|
+
task.push_configs.values
|
|
202
|
+
end
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
def delete_push_config(task_id, config_id)
|
|
206
|
+
@mutex.synchronize do
|
|
207
|
+
task = @tasks[task_id]
|
|
208
|
+
return nil unless task
|
|
209
|
+
task.push_configs.delete(config_id)
|
|
210
|
+
task.updated_at = Time.now.utc
|
|
211
|
+
end
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
# ── Streaming / Pub-Sub ────────────────────────────────────────────
|
|
215
|
+
|
|
216
|
+
# Subscribe to task updates. Returns a Queue that will receive events.
|
|
217
|
+
# Each event is a Hash: { type: :status|:artifact, data: Hash }
|
|
218
|
+
# A nil sentinel signals stream end.
|
|
219
|
+
def subscribe(task_id)
|
|
220
|
+
queue = Thread::Queue.new
|
|
221
|
+
@mutex.synchronize do
|
|
222
|
+
task = @tasks[task_id]
|
|
223
|
+
return nil unless task
|
|
224
|
+
task.subscribers << queue
|
|
225
|
+
end
|
|
226
|
+
queue
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
def unsubscribe(task_id, queue)
|
|
230
|
+
@mutex.synchronize do
|
|
231
|
+
task = @tasks[task_id]
|
|
232
|
+
return unless task
|
|
233
|
+
task.subscribers.delete(queue)
|
|
234
|
+
end
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
private
|
|
238
|
+
|
|
239
|
+
def build_status_event(task, message = nil)
|
|
240
|
+
event = {
|
|
241
|
+
"taskId" => task.id,
|
|
242
|
+
"contextId" => task.context_id,
|
|
243
|
+
"status" => {
|
|
244
|
+
"state" => task.state,
|
|
245
|
+
"timestamp" => task.updated_at.strftime("%Y-%m-%dT%H:%M:%S.%3NZ"),
|
|
246
|
+
},
|
|
247
|
+
}
|
|
248
|
+
event["status"]["message"] = message if message
|
|
249
|
+
event
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
def notify_subscribers(task, event, type: :status)
|
|
253
|
+
subs = @mutex.synchronize { task.subscribers.dup }
|
|
254
|
+
subs.each do |queue|
|
|
255
|
+
queue << { type: type, data: event }
|
|
256
|
+
rescue ClosedQueueError
|
|
257
|
+
# subscriber disconnected
|
|
258
|
+
end
|
|
259
|
+
end
|
|
260
|
+
|
|
261
|
+
def close_subscribers(task)
|
|
262
|
+
subs = @mutex.synchronize { task.subscribers.dup }
|
|
263
|
+
subs.each do |queue|
|
|
264
|
+
queue << nil # sentinel
|
|
265
|
+
queue.close
|
|
266
|
+
rescue ClosedQueueError
|
|
267
|
+
# already closed
|
|
268
|
+
end
|
|
269
|
+
@mutex.synchronize { task.subscribers.clear }
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
def deliver_webhooks(task, payload)
|
|
273
|
+
configs = @mutex.synchronize { task.push_configs.values.dup }
|
|
274
|
+
return if configs.empty?
|
|
275
|
+
|
|
276
|
+
configs.each do |config|
|
|
277
|
+
Thread.new do
|
|
278
|
+
deliver_single_webhook(config, payload)
|
|
279
|
+
rescue => e
|
|
280
|
+
# Log but don't fail
|
|
281
|
+
$stderr.puts "[A2A::TaskStore] Webhook delivery failed for #{config["url"]}: #{e.message}"
|
|
282
|
+
end
|
|
283
|
+
end
|
|
284
|
+
end
|
|
285
|
+
|
|
286
|
+
def deliver_single_webhook(config, payload)
|
|
287
|
+
url = config["url"]
|
|
288
|
+
return unless url && !url.empty?
|
|
289
|
+
|
|
290
|
+
uri = URI.parse(url)
|
|
291
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
|
292
|
+
http.use_ssl = (uri.scheme == "https")
|
|
293
|
+
http.open_timeout = 10
|
|
294
|
+
http.read_timeout = 30
|
|
295
|
+
|
|
296
|
+
request = Net::HTTP::Post.new(uri.request_uri)
|
|
297
|
+
request["Content-Type"] = "application/a2a+json"
|
|
298
|
+
|
|
299
|
+
# Authentication
|
|
300
|
+
if (auth = config["authentication"])
|
|
301
|
+
scheme = auth["scheme"] || "Bearer"
|
|
302
|
+
creds = auth["credentials"] || ""
|
|
303
|
+
request["Authorization"] = "#{scheme} #{creds}"
|
|
304
|
+
end
|
|
305
|
+
|
|
306
|
+
# Token header
|
|
307
|
+
if (token = config["token"])
|
|
308
|
+
request["X-A2A-Notification-Token"] = token
|
|
309
|
+
end
|
|
310
|
+
|
|
311
|
+
request.body = JSON.generate(payload)
|
|
312
|
+
http.request(request)
|
|
313
|
+
end
|
|
314
|
+
end
|
|
315
|
+
end
|
data/lib/a2a/version.rb
ADDED
data/lib/a2a.rb
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "bundler/setup"
|
|
4
|
+
require "scampi"
|
|
5
|
+
require "json"
|
|
6
|
+
require "json_schemer"
|
|
7
|
+
require "async"
|
|
8
|
+
require "async/http/internet"
|
|
9
|
+
require "uri"
|
|
10
|
+
require "rack"
|
|
11
|
+
|
|
12
|
+
module A2A
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
require "a2a/proto"
|
|
16
|
+
require "a2a/schema"
|
|
17
|
+
require "a2a/schema/definition"
|
|
18
|
+
require "a2a/schema/validation_error"
|
|
19
|
+
require "a2a/task_store"
|
|
20
|
+
require "a2a/store"
|
|
21
|
+
require "a2a/sse"
|
|
22
|
+
require "a2a/agent"
|
|
23
|
+
|
|
24
|
+
require "a2a/server"
|
|
25
|
+
|
|
26
|
+
require "a2a/client"
|
metadata
ADDED
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: agent2agent
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- A2A Contributors
|
|
8
|
+
bindir: bin
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-01 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: async
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - ">="
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '0'
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - ">="
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '0'
|
|
26
|
+
- !ruby/object:Gem::Dependency
|
|
27
|
+
name: async-http
|
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
|
29
|
+
requirements:
|
|
30
|
+
- - "~>"
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: '0.95'
|
|
33
|
+
type: :runtime
|
|
34
|
+
prerelease: false
|
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - "~>"
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: '0.95'
|
|
40
|
+
- !ruby/object:Gem::Dependency
|
|
41
|
+
name: protocol-http
|
|
42
|
+
requirement: !ruby/object:Gem::Requirement
|
|
43
|
+
requirements:
|
|
44
|
+
- - "~>"
|
|
45
|
+
- !ruby/object:Gem::Version
|
|
46
|
+
version: '0.62'
|
|
47
|
+
type: :runtime
|
|
48
|
+
prerelease: false
|
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
50
|
+
requirements:
|
|
51
|
+
- - "~>"
|
|
52
|
+
- !ruby/object:Gem::Version
|
|
53
|
+
version: '0.62'
|
|
54
|
+
- !ruby/object:Gem::Dependency
|
|
55
|
+
name: scampi
|
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
|
57
|
+
requirements:
|
|
58
|
+
- - ">="
|
|
59
|
+
- !ruby/object:Gem::Version
|
|
60
|
+
version: '0'
|
|
61
|
+
type: :runtime
|
|
62
|
+
prerelease: false
|
|
63
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
64
|
+
requirements:
|
|
65
|
+
- - ">="
|
|
66
|
+
- !ruby/object:Gem::Version
|
|
67
|
+
version: '0'
|
|
68
|
+
- !ruby/object:Gem::Dependency
|
|
69
|
+
name: rack
|
|
70
|
+
requirement: !ruby/object:Gem::Requirement
|
|
71
|
+
requirements:
|
|
72
|
+
- - "~>"
|
|
73
|
+
- !ruby/object:Gem::Version
|
|
74
|
+
version: '3.0'
|
|
75
|
+
type: :runtime
|
|
76
|
+
prerelease: false
|
|
77
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
78
|
+
requirements:
|
|
79
|
+
- - "~>"
|
|
80
|
+
- !ruby/object:Gem::Version
|
|
81
|
+
version: '3.0'
|
|
82
|
+
- !ruby/object:Gem::Dependency
|
|
83
|
+
name: json_schemer
|
|
84
|
+
requirement: !ruby/object:Gem::Requirement
|
|
85
|
+
requirements:
|
|
86
|
+
- - "~>"
|
|
87
|
+
- !ruby/object:Gem::Version
|
|
88
|
+
version: '2.5'
|
|
89
|
+
type: :runtime
|
|
90
|
+
prerelease: false
|
|
91
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
92
|
+
requirements:
|
|
93
|
+
- - "~>"
|
|
94
|
+
- !ruby/object:Gem::Version
|
|
95
|
+
version: '2.5'
|
|
96
|
+
- !ruby/object:Gem::Dependency
|
|
97
|
+
name: google-protobuf
|
|
98
|
+
requirement: !ruby/object:Gem::Requirement
|
|
99
|
+
requirements:
|
|
100
|
+
- - "~>"
|
|
101
|
+
- !ruby/object:Gem::Version
|
|
102
|
+
version: '4.34'
|
|
103
|
+
type: :runtime
|
|
104
|
+
prerelease: false
|
|
105
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
106
|
+
requirements:
|
|
107
|
+
- - "~>"
|
|
108
|
+
- !ruby/object:Gem::Version
|
|
109
|
+
version: '4.34'
|
|
110
|
+
- !ruby/object:Gem::Dependency
|
|
111
|
+
name: sqlite3
|
|
112
|
+
requirement: !ruby/object:Gem::Requirement
|
|
113
|
+
requirements:
|
|
114
|
+
- - ">="
|
|
115
|
+
- !ruby/object:Gem::Version
|
|
116
|
+
version: '0'
|
|
117
|
+
type: :runtime
|
|
118
|
+
prerelease: false
|
|
119
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
120
|
+
requirements:
|
|
121
|
+
- - ">="
|
|
122
|
+
- !ruby/object:Gem::Version
|
|
123
|
+
version: '0'
|
|
124
|
+
- !ruby/object:Gem::Dependency
|
|
125
|
+
name: rake
|
|
126
|
+
requirement: !ruby/object:Gem::Requirement
|
|
127
|
+
requirements:
|
|
128
|
+
- - "~>"
|
|
129
|
+
- !ruby/object:Gem::Version
|
|
130
|
+
version: '13.0'
|
|
131
|
+
type: :development
|
|
132
|
+
prerelease: false
|
|
133
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
134
|
+
requirements:
|
|
135
|
+
- - "~>"
|
|
136
|
+
- !ruby/object:Gem::Version
|
|
137
|
+
version: '13.0'
|
|
138
|
+
- !ruby/object:Gem::Dependency
|
|
139
|
+
name: falcon
|
|
140
|
+
requirement: !ruby/object:Gem::Requirement
|
|
141
|
+
requirements:
|
|
142
|
+
- - "~>"
|
|
143
|
+
- !ruby/object:Gem::Version
|
|
144
|
+
version: '0.55'
|
|
145
|
+
type: :development
|
|
146
|
+
prerelease: false
|
|
147
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
148
|
+
requirements:
|
|
149
|
+
- - "~>"
|
|
150
|
+
- !ruby/object:Gem::Version
|
|
151
|
+
version: '0.55'
|
|
152
|
+
description: Abstraction to help work with A2A protocol
|
|
153
|
+
executables: []
|
|
154
|
+
extensions: []
|
|
155
|
+
extra_rdoc_files: []
|
|
156
|
+
files:
|
|
157
|
+
- data/a2a.json
|
|
158
|
+
- data/a2a.proto
|
|
159
|
+
- data/download-a2a-resources
|
|
160
|
+
- data/spec.txt
|
|
161
|
+
- lib/a2a.rb
|
|
162
|
+
- lib/a2a/agent.rb
|
|
163
|
+
- lib/a2a/bindings/json_rpc.rb
|
|
164
|
+
- lib/a2a/bindings/rest.rb
|
|
165
|
+
- lib/a2a/client.rb
|
|
166
|
+
- lib/a2a/proto.rb
|
|
167
|
+
- lib/a2a/schema.rb
|
|
168
|
+
- lib/a2a/schema/definition.rb
|
|
169
|
+
- lib/a2a/schema/validation_error.rb
|
|
170
|
+
- lib/a2a/server.rb
|
|
171
|
+
- lib/a2a/server/cancel_task.rb
|
|
172
|
+
- lib/a2a/server/create_task_push_notification_config.rb
|
|
173
|
+
- lib/a2a/server/delete_task_push_notification_config.rb
|
|
174
|
+
- lib/a2a/server/dispatcher.rb
|
|
175
|
+
- lib/a2a/server/env.rb
|
|
176
|
+
- lib/a2a/server/get_extended_agent_card.rb
|
|
177
|
+
- lib/a2a/server/get_task.rb
|
|
178
|
+
- lib/a2a/server/get_task_push_notification_config.rb
|
|
179
|
+
- lib/a2a/server/list_task_push_notification_configs.rb
|
|
180
|
+
- lib/a2a/server/list_tasks.rb
|
|
181
|
+
- lib/a2a/server/send_message.rb
|
|
182
|
+
- lib/a2a/server/send_streaming_message.rb
|
|
183
|
+
- lib/a2a/server/subscribe_to_task.rb
|
|
184
|
+
- lib/a2a/server/triage.rb
|
|
185
|
+
- lib/a2a/sse.rb
|
|
186
|
+
- lib/a2a/sse/json_rpc_stream.rb
|
|
187
|
+
- lib/a2a/sse/rest_stream.rb
|
|
188
|
+
- lib/a2a/sse/stream.rb
|
|
189
|
+
- lib/a2a/store.rb
|
|
190
|
+
- lib/a2a/store/processor.rb
|
|
191
|
+
- lib/a2a/store/pub_sub.rb
|
|
192
|
+
- lib/a2a/store/sqlite.rb
|
|
193
|
+
- lib/a2a/store/webhooks.rb
|
|
194
|
+
- lib/a2a/task_store.rb
|
|
195
|
+
- lib/a2a/version.rb
|
|
196
|
+
licenses:
|
|
197
|
+
- MIT
|
|
198
|
+
metadata: {}
|
|
199
|
+
rdoc_options: []
|
|
200
|
+
require_paths:
|
|
201
|
+
- lib
|
|
202
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
203
|
+
requirements:
|
|
204
|
+
- - ">="
|
|
205
|
+
- !ruby/object:Gem::Version
|
|
206
|
+
version: '3.2'
|
|
207
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
208
|
+
requirements:
|
|
209
|
+
- - ">="
|
|
210
|
+
- !ruby/object:Gem::Version
|
|
211
|
+
version: '0'
|
|
212
|
+
requirements: []
|
|
213
|
+
rubygems_version: 3.7.2
|
|
214
|
+
specification_version: 4
|
|
215
|
+
summary: Agent2Agent protocol
|
|
216
|
+
test_files: []
|