a2a-rb 0.1.1
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/CHANGELOG.md +38 -0
- data/LICENSE.txt +21 -0
- data/README.md +311 -0
- data/lib/a2a/agent_capabilities.rb +32 -0
- data/lib/a2a/agent_card/builder.rb +135 -0
- data/lib/a2a/agent_card/signature.rb +35 -0
- data/lib/a2a/agent_card/verifier.rb +19 -0
- data/lib/a2a/agent_card.rb +118 -0
- data/lib/a2a/agent_extension.rb +32 -0
- data/lib/a2a/agent_interface.rb +54 -0
- data/lib/a2a/agent_provider.rb +20 -0
- data/lib/a2a/agent_skill.rb +46 -0
- data/lib/a2a/artifact.rb +40 -0
- data/lib/a2a/client.rb +109 -0
- data/lib/a2a/discovery.rb +49 -0
- data/lib/a2a/json_rpc_envelope.rb +32 -0
- data/lib/a2a/message.rb +54 -0
- data/lib/a2a/oauth_flow/authorization_code.rb +37 -0
- data/lib/a2a/oauth_flow/client_credentials.rb +31 -0
- data/lib/a2a/oauth_flow/device_code.rb +34 -0
- data/lib/a2a/oauth_flow.rb +37 -0
- data/lib/a2a/operation/cancel_task.rb +39 -0
- data/lib/a2a/operation/create_task_push_notification_config.rb +38 -0
- data/lib/a2a/operation/delete_task_push_notification_config.rb +38 -0
- data/lib/a2a/operation/executable.rb +27 -0
- data/lib/a2a/operation/get_extended_agent_card.rb +32 -0
- data/lib/a2a/operation/get_task.rb +39 -0
- data/lib/a2a/operation/get_task_push_notification_config.rb +38 -0
- data/lib/a2a/operation/list_task_push_notification_configs.rb +64 -0
- data/lib/a2a/operation/list_tasks.rb +78 -0
- data/lib/a2a/operation/send_message/configuration.rb +39 -0
- data/lib/a2a/operation/send_message.rb +58 -0
- data/lib/a2a/operation/send_message_request.rb +37 -0
- data/lib/a2a/operation/send_streaming_message.rb +53 -0
- data/lib/a2a/operation/subscribe_to_task.rb +40 -0
- data/lib/a2a/operation.rb +19 -0
- data/lib/a2a/part/data.rb +34 -0
- data/lib/a2a/part/file.rb +45 -0
- data/lib/a2a/part/text.rb +34 -0
- data/lib/a2a/part.rb +21 -0
- data/lib/a2a/protocol/http_json/transport.rb +82 -0
- data/lib/a2a/protocol/http_json.rb +53 -0
- data/lib/a2a/protocol/json_rpc/transport.rb +54 -0
- data/lib/a2a/protocol/json_rpc.rb +55 -0
- data/lib/a2a/push_notification/authentication_info.rb +29 -0
- data/lib/a2a/push_notification/config.rb +40 -0
- data/lib/a2a/push_notification/dispatcher.rb +52 -0
- data/lib/a2a/push_notification/receiver.rb +54 -0
- data/lib/a2a/push_notification.rb +11 -0
- data/lib/a2a/role.rb +13 -0
- data/lib/a2a/security_requirement.rb +19 -0
- data/lib/a2a/security_scheme/api_key.rb +33 -0
- data/lib/a2a/security_scheme/http_auth.rb +33 -0
- data/lib/a2a/security_scheme/mutual_tls.rb +25 -0
- data/lib/a2a/security_scheme/oauth2.rb +52 -0
- data/lib/a2a/security_scheme/open_id_connect.rb +30 -0
- data/lib/a2a/security_scheme.rb +26 -0
- data/lib/a2a/streaming/artifact_update_event.rb +40 -0
- data/lib/a2a/streaming/response.rb +65 -0
- data/lib/a2a/streaming/sse_parser.rb +43 -0
- data/lib/a2a/streaming/sse_writer.rb +25 -0
- data/lib/a2a/streaming/status_update_event.rb +43 -0
- data/lib/a2a/streaming/subscription.rb +56 -0
- data/lib/a2a/streaming.rb +12 -0
- data/lib/a2a/task/state.rb +31 -0
- data/lib/a2a/task/status.rb +35 -0
- data/lib/a2a/task.rb +66 -0
- data/lib/a2a/version.rb +6 -0
- data/lib/a2a/versioning.rb +28 -0
- data/lib/a2a.rb +90 -0
- metadata +116 -0
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "oauth_flow/authorization_code"
|
|
4
|
+
require_relative "oauth_flow/client_credentials"
|
|
5
|
+
require_relative "oauth_flow/device_code"
|
|
6
|
+
|
|
7
|
+
module A2A
|
|
8
|
+
module OAuthFlow
|
|
9
|
+
FLOW_KEYS = %w[authorizationCode clientCredentials deviceCode].freeze
|
|
10
|
+
DEPRECATED_FLOW_KEYS = %w[implicit password].freeze
|
|
11
|
+
|
|
12
|
+
def self.from_h(hash)
|
|
13
|
+
reject_deprecated!(hash)
|
|
14
|
+
matched = FLOW_KEYS.count { |k| hash.key?(k) }
|
|
15
|
+
raise ArgumentError, "OAuthFlows must contain exactly one flow type, got #{matched}" unless matched == 1
|
|
16
|
+
|
|
17
|
+
build_flows(hash)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def self.build_flows(hash)
|
|
21
|
+
{}.tap do |flows|
|
|
22
|
+
flows[:authorization_code] = AuthorizationCode.from_h(hash["authorizationCode"]) if hash["authorizationCode"]
|
|
23
|
+
flows[:client_credentials] = ClientCredentials.from_h(hash["clientCredentials"]) if hash["clientCredentials"]
|
|
24
|
+
flows[:device_code] = DeviceCode.from_h(hash["deviceCode"]) if hash["deviceCode"]
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def self.reject_deprecated!(hash)
|
|
29
|
+
deprecated = DEPRECATED_FLOW_KEYS.select { |k| hash.key?(k) }
|
|
30
|
+
return unless deprecated.any?
|
|
31
|
+
|
|
32
|
+
raise ArgumentError,
|
|
33
|
+
"OAuthFlows contains deprecated flow(s): #{deprecated.join(', ')} — use authorizationCode or deviceCode"
|
|
34
|
+
end
|
|
35
|
+
private_class_method :build_flows, :reject_deprecated!
|
|
36
|
+
end
|
|
37
|
+
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module A2A
|
|
4
|
+
module Operation
|
|
5
|
+
class CancelTask
|
|
6
|
+
include Executable
|
|
7
|
+
|
|
8
|
+
METHOD = "CancelTask"
|
|
9
|
+
|
|
10
|
+
attr_reader :id, :metadata, :tenant
|
|
11
|
+
|
|
12
|
+
def initialize(id:, metadata: nil, tenant: nil)
|
|
13
|
+
@id = id
|
|
14
|
+
@metadata = metadata
|
|
15
|
+
@tenant = tenant
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def execute_json_rpc(protocol)
|
|
19
|
+
raw = protocol.post(METHOD, params)
|
|
20
|
+
raise A2A.from_json_rpc_error(raw["error"]) if raw["error"]
|
|
21
|
+
|
|
22
|
+
Task.from_h(Hash(raw["result"]))
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def execute_http_json(protocol)
|
|
26
|
+
body = metadata ? { "metadata" => metadata } : {}
|
|
27
|
+
Task.from_h(protocol.post("/tasks/#{id}:cancel", body: body))
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def params
|
|
31
|
+
{
|
|
32
|
+
"id" => id,
|
|
33
|
+
"metadata" => metadata,
|
|
34
|
+
"tenant" => tenant
|
|
35
|
+
}.compact
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module A2A
|
|
4
|
+
module Operation
|
|
5
|
+
class CreateTaskPushNotificationConfig
|
|
6
|
+
include Executable
|
|
7
|
+
|
|
8
|
+
METHOD = "CreateTaskPushNotificationConfig"
|
|
9
|
+
|
|
10
|
+
attr_reader :config, :tenant
|
|
11
|
+
|
|
12
|
+
def initialize(config, tenant: nil)
|
|
13
|
+
@config = config.is_a?(PushNotification::Config) ? config : PushNotification::Config.from_h(config)
|
|
14
|
+
@tenant = tenant
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def execute_json_rpc(protocol)
|
|
18
|
+
raw = protocol.post(METHOD, params)
|
|
19
|
+
raise A2A.from_json_rpc_error(raw["error"]) if raw["error"]
|
|
20
|
+
|
|
21
|
+
PushNotification::Config.from_h(Hash(raw["result"]))
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def execute_http_json(protocol)
|
|
25
|
+
PushNotification::Config.from_h(
|
|
26
|
+
protocol.post("/tasks/#{config.task_id}/pushNotificationConfigs", body: config.to_h)
|
|
27
|
+
)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def params
|
|
31
|
+
{
|
|
32
|
+
"pushNotificationConfig" => config.to_h,
|
|
33
|
+
"tenant" => tenant
|
|
34
|
+
}.compact
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module A2A
|
|
4
|
+
module Operation
|
|
5
|
+
class DeleteTaskPushNotificationConfig
|
|
6
|
+
include Executable
|
|
7
|
+
|
|
8
|
+
METHOD = "DeleteTaskPushNotificationConfig"
|
|
9
|
+
|
|
10
|
+
attr_reader :task_id, :id, :tenant
|
|
11
|
+
|
|
12
|
+
def initialize(task_id:, id:, tenant: nil)
|
|
13
|
+
@task_id = task_id
|
|
14
|
+
@id = id
|
|
15
|
+
@tenant = tenant
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def execute_json_rpc(protocol)
|
|
19
|
+
raw = protocol.post(METHOD, params)
|
|
20
|
+
raise A2A.from_json_rpc_error(raw["error"]) if raw["error"]
|
|
21
|
+
|
|
22
|
+
nil
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def execute_http_json(protocol)
|
|
26
|
+
protocol.delete("/tasks/#{task_id}/pushNotificationConfigs/#{id}")
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def params
|
|
30
|
+
{
|
|
31
|
+
"taskId" => task_id,
|
|
32
|
+
"id" => id,
|
|
33
|
+
"tenant" => tenant
|
|
34
|
+
}.compact
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module A2A
|
|
4
|
+
module Operation
|
|
5
|
+
module Executable
|
|
6
|
+
def execute(protocol, &)
|
|
7
|
+
if protocol.is_a?(Protocol::HttpJson)
|
|
8
|
+
execute_http_json(protocol, &)
|
|
9
|
+
else
|
|
10
|
+
execute_json_rpc(protocol, &)
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def execute_json_rpc(*)
|
|
15
|
+
raise NotImplementedError, "#{self.class}#execute_json_rpc is not implemented"
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def execute_http_json(*)
|
|
19
|
+
raise NotImplementedError, "#{self.class}#execute_http_json is not implemented"
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def params
|
|
23
|
+
raise NotImplementedError, "#{self.class}#params is not implemented"
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module A2A
|
|
4
|
+
module Operation
|
|
5
|
+
class GetExtendedAgentCard
|
|
6
|
+
include Executable
|
|
7
|
+
|
|
8
|
+
METHOD = "GetExtendedAgentCard"
|
|
9
|
+
|
|
10
|
+
attr_reader :tenant
|
|
11
|
+
|
|
12
|
+
def initialize(tenant: nil)
|
|
13
|
+
@tenant = tenant
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def execute_json_rpc(protocol)
|
|
17
|
+
raw = protocol.post(METHOD, params)
|
|
18
|
+
raise A2A.from_json_rpc_error(raw["error"]) if raw["error"]
|
|
19
|
+
|
|
20
|
+
AgentCard.from_h(Hash(raw["result"]))
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def execute_http_json(protocol)
|
|
24
|
+
AgentCard.from_h(protocol.get("/extendedAgentCard", query: {}))
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def params
|
|
28
|
+
{ "tenant" => tenant }.compact
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module A2A
|
|
4
|
+
module Operation
|
|
5
|
+
class GetTask
|
|
6
|
+
include Executable
|
|
7
|
+
|
|
8
|
+
METHOD = "GetTask"
|
|
9
|
+
|
|
10
|
+
attr_reader :id, :history_length, :tenant
|
|
11
|
+
|
|
12
|
+
def initialize(id:, history_length: nil, tenant: nil)
|
|
13
|
+
@id = id
|
|
14
|
+
@history_length = history_length
|
|
15
|
+
@tenant = tenant
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def execute_json_rpc(protocol)
|
|
19
|
+
raw = protocol.post(METHOD, params)
|
|
20
|
+
raise A2A.from_json_rpc_error(raw["error"]) if raw["error"]
|
|
21
|
+
|
|
22
|
+
Task.from_h(Hash(raw["result"]))
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def execute_http_json(protocol)
|
|
26
|
+
query = { "historyLength" => history_length }.compact
|
|
27
|
+
Task.from_h(protocol.get("/tasks/#{id}", query: query))
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def params
|
|
31
|
+
{
|
|
32
|
+
"id" => id,
|
|
33
|
+
"historyLength" => history_length,
|
|
34
|
+
"tenant" => tenant
|
|
35
|
+
}.compact
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module A2A
|
|
4
|
+
module Operation
|
|
5
|
+
class GetTaskPushNotificationConfig
|
|
6
|
+
include Executable
|
|
7
|
+
|
|
8
|
+
METHOD = "GetTaskPushNotificationConfig"
|
|
9
|
+
|
|
10
|
+
attr_reader :task_id, :id, :tenant
|
|
11
|
+
|
|
12
|
+
def initialize(task_id:, id:, tenant: nil)
|
|
13
|
+
@task_id = task_id
|
|
14
|
+
@id = id
|
|
15
|
+
@tenant = tenant
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def execute_json_rpc(protocol)
|
|
19
|
+
raw = protocol.post(METHOD, params)
|
|
20
|
+
raise A2A.from_json_rpc_error(raw["error"]) if raw["error"]
|
|
21
|
+
|
|
22
|
+
PushNotification::Config.from_h(Hash(raw["result"]))
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def execute_http_json(protocol)
|
|
26
|
+
PushNotification::Config.from_h(protocol.get("/tasks/#{task_id}/pushNotificationConfigs/#{id}", query: {}))
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def params
|
|
30
|
+
{
|
|
31
|
+
"taskId" => task_id,
|
|
32
|
+
"id" => id,
|
|
33
|
+
"tenant" => tenant
|
|
34
|
+
}.compact
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module A2A
|
|
4
|
+
module Operation
|
|
5
|
+
class ListTaskPushNotificationConfigs
|
|
6
|
+
include Executable
|
|
7
|
+
|
|
8
|
+
METHOD = "ListTaskPushNotificationConfigs"
|
|
9
|
+
|
|
10
|
+
attr_reader :task_id, :page_size, :page_token, :tenant
|
|
11
|
+
|
|
12
|
+
def initialize(task_id:, page_size: nil, page_token: nil, tenant: nil)
|
|
13
|
+
@task_id = task_id
|
|
14
|
+
@page_size = page_size
|
|
15
|
+
@page_token = page_token
|
|
16
|
+
@tenant = tenant
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def execute_json_rpc(protocol)
|
|
20
|
+
raw = protocol.post(METHOD, params)
|
|
21
|
+
raise A2A.from_json_rpc_error(raw["error"]) if raw["error"]
|
|
22
|
+
|
|
23
|
+
Response.from_h(Hash(raw["result"]))
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def execute_http_json(protocol)
|
|
27
|
+
query = { "pageSize" => page_size, "pageToken" => page_token }.compact
|
|
28
|
+
Response.from_h(protocol.get("/tasks/#{task_id}/pushNotificationConfigs", query: query))
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def params
|
|
32
|
+
{
|
|
33
|
+
"taskId" => task_id,
|
|
34
|
+
"pageSize" => page_size,
|
|
35
|
+
"pageToken" => page_token,
|
|
36
|
+
"tenant" => tenant
|
|
37
|
+
}.compact
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
class Response
|
|
41
|
+
attr_reader :configs, :next_page_token
|
|
42
|
+
|
|
43
|
+
def initialize(configs:, next_page_token: nil)
|
|
44
|
+
@configs = configs
|
|
45
|
+
@next_page_token = next_page_token
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def self.from_h(hash)
|
|
49
|
+
new(
|
|
50
|
+
configs: Array(hash["configs"]).map { PushNotification::Config.from_h(_1) },
|
|
51
|
+
next_page_token: hash["nextPageToken"]
|
|
52
|
+
)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def to_h
|
|
56
|
+
{
|
|
57
|
+
"configs" => configs.map(&:to_h),
|
|
58
|
+
"nextPageToken" => next_page_token
|
|
59
|
+
}.compact
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module A2A
|
|
4
|
+
module Operation
|
|
5
|
+
class ListTasks
|
|
6
|
+
include Executable
|
|
7
|
+
|
|
8
|
+
METHOD = "ListTasks"
|
|
9
|
+
|
|
10
|
+
attr_reader :context_id, :status, :page_size, :page_token, :history_length,
|
|
11
|
+
:status_timestamp_after, :include_artifacts, :tenant
|
|
12
|
+
|
|
13
|
+
def initialize(**kwargs)
|
|
14
|
+
@context_id = kwargs[:context_id]
|
|
15
|
+
@status = kwargs[:status]
|
|
16
|
+
@page_size = kwargs[:page_size]
|
|
17
|
+
@page_token = kwargs[:page_token]
|
|
18
|
+
@history_length = kwargs[:history_length]
|
|
19
|
+
@status_timestamp_after = kwargs[:status_timestamp_after]
|
|
20
|
+
@include_artifacts = kwargs[:include_artifacts]
|
|
21
|
+
@tenant = kwargs[:tenant]
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def execute_json_rpc(protocol)
|
|
25
|
+
raw = protocol.post(METHOD, params)
|
|
26
|
+
raise A2A.from_json_rpc_error(raw["error"]) if raw["error"]
|
|
27
|
+
|
|
28
|
+
Response.from_h(Hash(raw["result"]))
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def execute_http_json(protocol)
|
|
32
|
+
Response.from_h(protocol.get("/tasks", query: params))
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def params
|
|
36
|
+
{
|
|
37
|
+
"contextId" => context_id,
|
|
38
|
+
"status" => status,
|
|
39
|
+
"pageSize" => page_size,
|
|
40
|
+
"pageToken" => page_token,
|
|
41
|
+
"historyLength" => history_length,
|
|
42
|
+
"statusTimestampAfter" => status_timestamp_after,
|
|
43
|
+
"includeArtifacts" => include_artifacts,
|
|
44
|
+
"tenant" => tenant
|
|
45
|
+
}.compact
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
class Response
|
|
49
|
+
attr_reader :tasks, :next_page_token, :page_size, :total_size
|
|
50
|
+
|
|
51
|
+
def initialize(tasks:, next_page_token:, page_size:, total_size:)
|
|
52
|
+
@tasks = tasks
|
|
53
|
+
@next_page_token = next_page_token
|
|
54
|
+
@page_size = page_size
|
|
55
|
+
@total_size = total_size
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def self.from_h(hash)
|
|
59
|
+
new(
|
|
60
|
+
tasks: Array(hash["tasks"]).map { Task.from_h(_1) },
|
|
61
|
+
next_page_token: hash.fetch("nextPageToken"),
|
|
62
|
+
page_size: hash.fetch("pageSize"),
|
|
63
|
+
total_size: hash.fetch("totalSize")
|
|
64
|
+
)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def to_h
|
|
68
|
+
{
|
|
69
|
+
"tasks" => tasks.map(&:to_h),
|
|
70
|
+
"nextPageToken" => next_page_token,
|
|
71
|
+
"pageSize" => page_size,
|
|
72
|
+
"totalSize" => total_size
|
|
73
|
+
}
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module A2A
|
|
4
|
+
module Operation
|
|
5
|
+
class SendMessage
|
|
6
|
+
class Configuration
|
|
7
|
+
attr_reader :accepted_output_modes, :task_push_notification_config, :history_length,
|
|
8
|
+
:return_immediately
|
|
9
|
+
|
|
10
|
+
def initialize(**kwargs)
|
|
11
|
+
@accepted_output_modes = kwargs[:accepted_output_modes]
|
|
12
|
+
@task_push_notification_config = kwargs[:task_push_notification_config]
|
|
13
|
+
@history_length = kwargs[:history_length]
|
|
14
|
+
@return_immediately = kwargs[:return_immediately]
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def self.from_h(hash)
|
|
18
|
+
new(
|
|
19
|
+
accepted_output_modes: hash["acceptedOutputModes"],
|
|
20
|
+
task_push_notification_config: hash["taskPushNotificationConfig"],
|
|
21
|
+
history_length: hash["historyLength"],
|
|
22
|
+
return_immediately: hash["returnImmediately"]
|
|
23
|
+
)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def to_h
|
|
27
|
+
push_config = task_push_notification_config
|
|
28
|
+
push_config = push_config.to_h if push_config.is_a?(PushNotification::Config)
|
|
29
|
+
{
|
|
30
|
+
"acceptedOutputModes" => accepted_output_modes,
|
|
31
|
+
"taskPushNotificationConfig" => push_config,
|
|
32
|
+
"historyLength" => history_length,
|
|
33
|
+
"returnImmediately" => return_immediately
|
|
34
|
+
}.compact
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "send_message/configuration"
|
|
4
|
+
|
|
5
|
+
module A2A
|
|
6
|
+
module Operation
|
|
7
|
+
class SendMessage
|
|
8
|
+
include Executable
|
|
9
|
+
|
|
10
|
+
METHOD = "SendMessage"
|
|
11
|
+
|
|
12
|
+
attr_reader :message, :configuration, :metadata, :tenant
|
|
13
|
+
|
|
14
|
+
def initialize(message, configuration: {}, metadata: nil, tenant: nil)
|
|
15
|
+
@message = message.is_a?(Message) ? message : Message.from_h(message)
|
|
16
|
+
@configuration = if configuration.is_a?(Configuration)
|
|
17
|
+
configuration
|
|
18
|
+
else
|
|
19
|
+
Configuration.new(**configuration.transform_keys(&:to_sym))
|
|
20
|
+
end
|
|
21
|
+
@metadata = metadata
|
|
22
|
+
@tenant = tenant
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def execute_json_rpc(protocol)
|
|
26
|
+
raw = protocol.post(METHOD, params)
|
|
27
|
+
raise A2A.from_json_rpc_error(raw["error"]) if raw["error"]
|
|
28
|
+
|
|
29
|
+
parse_result(Hash(raw["result"]))
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def execute_http_json(protocol)
|
|
33
|
+
parse_result(protocol.post("/message:send", body: params))
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def params
|
|
37
|
+
p = { "message" => message.to_h }
|
|
38
|
+
config_h = configuration.to_h
|
|
39
|
+
p["configuration"] = config_h unless config_h.empty?
|
|
40
|
+
p["metadata"] = metadata if metadata
|
|
41
|
+
p["tenant"] = tenant if tenant
|
|
42
|
+
p
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
private
|
|
46
|
+
|
|
47
|
+
def parse_result(result)
|
|
48
|
+
if result.key?("task")
|
|
49
|
+
Task.from_h(result["task"])
|
|
50
|
+
elsif result.key?("message")
|
|
51
|
+
Message.from_h(result["message"])
|
|
52
|
+
else
|
|
53
|
+
raise InvalidAgentResponseError, "response is neither Task nor Message"
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "send_message/configuration"
|
|
4
|
+
|
|
5
|
+
module A2A
|
|
6
|
+
module Operation
|
|
7
|
+
# Server-side counterpart to SendMessage. Deserialises the params hash from
|
|
8
|
+
# an incoming SendMessage / SendStreamingMessage JSON-RPC call or HTTP+JSON
|
|
9
|
+
# request body into typed objects.
|
|
10
|
+
class SendMessageRequest
|
|
11
|
+
attr_reader :message, :configuration, :metadata, :tenant
|
|
12
|
+
|
|
13
|
+
def initialize(message:, configuration: nil, metadata: nil, tenant: nil)
|
|
14
|
+
@message = message
|
|
15
|
+
@configuration = configuration
|
|
16
|
+
@metadata = metadata
|
|
17
|
+
@tenant = tenant
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def self.from_h(hash)
|
|
21
|
+
config_raw = hash["configuration"]
|
|
22
|
+
config = if config_raw
|
|
23
|
+
SendMessage::Configuration.from_h(config_raw)
|
|
24
|
+
else
|
|
25
|
+
SendMessage::Configuration.new
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
new(
|
|
29
|
+
message: Message.from_h(hash.fetch("message")),
|
|
30
|
+
configuration: config,
|
|
31
|
+
metadata: hash["metadata"],
|
|
32
|
+
tenant: hash["tenant"]
|
|
33
|
+
)
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module A2A
|
|
4
|
+
module Operation
|
|
5
|
+
class SendStreamingMessage
|
|
6
|
+
include Executable
|
|
7
|
+
|
|
8
|
+
METHOD = "SendStreamingMessage"
|
|
9
|
+
|
|
10
|
+
Configuration = SendMessage::Configuration
|
|
11
|
+
|
|
12
|
+
attr_reader :message, :configuration, :metadata, :tenant
|
|
13
|
+
|
|
14
|
+
def initialize(message, configuration: {}, metadata: nil, tenant: nil)
|
|
15
|
+
@message = message.is_a?(Message) ? message : Message.from_h(message)
|
|
16
|
+
@configuration = if configuration.is_a?(Configuration)
|
|
17
|
+
configuration
|
|
18
|
+
else
|
|
19
|
+
Configuration.new(**configuration.transform_keys(&:to_sym))
|
|
20
|
+
end
|
|
21
|
+
@metadata = metadata
|
|
22
|
+
@tenant = tenant
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def execute_json_rpc(protocol, &block)
|
|
26
|
+
protocol.stream(METHOD, params) do |response|
|
|
27
|
+
sub = Streaming::Subscription.new(response)
|
|
28
|
+
return sub unless block
|
|
29
|
+
|
|
30
|
+
sub.each(&block)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def execute_http_json(protocol, &block)
|
|
35
|
+
protocol.stream("/message:stream", method: :post, body: params) do |response|
|
|
36
|
+
sub = Streaming::Subscription.new(response)
|
|
37
|
+
return sub unless block
|
|
38
|
+
|
|
39
|
+
sub.each(&block)
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def params
|
|
44
|
+
p = { "message" => message.to_h }
|
|
45
|
+
config_h = configuration.to_h
|
|
46
|
+
p["configuration"] = config_h unless config_h.empty?
|
|
47
|
+
p["metadata"] = metadata if metadata
|
|
48
|
+
p["tenant"] = tenant if tenant
|
|
49
|
+
p
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module A2A
|
|
4
|
+
module Operation
|
|
5
|
+
class SubscribeToTask
|
|
6
|
+
include Executable
|
|
7
|
+
|
|
8
|
+
METHOD = "SubscribeToTask"
|
|
9
|
+
|
|
10
|
+
attr_reader :id, :tenant
|
|
11
|
+
|
|
12
|
+
def initialize(id:, tenant: nil)
|
|
13
|
+
@id = id
|
|
14
|
+
@tenant = tenant
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def execute_json_rpc(protocol, &block)
|
|
18
|
+
protocol.stream(METHOD, params) do |response|
|
|
19
|
+
sub = Streaming::Subscription.new(response)
|
|
20
|
+
return sub unless block
|
|
21
|
+
|
|
22
|
+
sub.each(&block)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def execute_http_json(protocol, &block)
|
|
27
|
+
protocol.stream("/tasks/#{id}:subscribe", method: :get) do |response|
|
|
28
|
+
sub = Streaming::Subscription.new(response)
|
|
29
|
+
return sub unless block
|
|
30
|
+
|
|
31
|
+
sub.each(&block)
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def params
|
|
36
|
+
{ "id" => id, "tenant" => tenant }.compact
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "operation/executable"
|
|
4
|
+
require_relative "operation/send_message"
|
|
5
|
+
require_relative "operation/send_streaming_message"
|
|
6
|
+
require_relative "operation/get_task"
|
|
7
|
+
require_relative "operation/list_tasks"
|
|
8
|
+
require_relative "operation/cancel_task"
|
|
9
|
+
require_relative "operation/subscribe_to_task"
|
|
10
|
+
require_relative "operation/create_task_push_notification_config"
|
|
11
|
+
require_relative "operation/get_task_push_notification_config"
|
|
12
|
+
require_relative "operation/list_task_push_notification_configs"
|
|
13
|
+
require_relative "operation/delete_task_push_notification_config"
|
|
14
|
+
require_relative "operation/get_extended_agent_card"
|
|
15
|
+
|
|
16
|
+
module A2A
|
|
17
|
+
module Operation
|
|
18
|
+
end
|
|
19
|
+
end
|