Class: A2A::Server::Apps::SinatraApp

Inherits:
Sinatra::Base
  • Object
show all
Defined in:
lib/a2a/server/apps/sinatra_app.rb

Overview

Sinatra application for serving A2A protocol endpoints

This class provides a Sinatra-based application that can handle A2A JSON-RPC requests and serve agent cards. It's a more Ruby-idiomatic alternative to the Rack app.

Class Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Class Attribute Details

.agent_cardObject

Returns the value of attribute agent_card.



28
29
30
# File 'lib/a2a/server/apps/sinatra_app.rb', line 28

def agent_card
  @agent_card
end

.card_modifierObject

Returns the value of attribute card_modifier.



28
29
30
# File 'lib/a2a/server/apps/sinatra_app.rb', line 28

def card_modifier
  @card_modifier
end

.extended_agent_cardObject

Returns the value of attribute extended_agent_card.



28
29
30
# File 'lib/a2a/server/apps/sinatra_app.rb', line 28

def extended_agent_card
  @extended_agent_card
end

.extended_card_modifierObject

Returns the value of attribute extended_card_modifier.



28
29
30
# File 'lib/a2a/server/apps/sinatra_app.rb', line 28

def extended_card_modifier
  @extended_card_modifier
end

.request_handlerObject

Returns the value of attribute request_handler.



28
29
30
# File 'lib/a2a/server/apps/sinatra_app.rb', line 28

def request_handler
  @request_handler
end

Class Method Details

.configure_a2a(agent_card:, request_handler:, extended_agent_card: nil, card_modifier: nil, extended_card_modifier: nil) ⇒ Object

Configure the Sinatra app with A2A components

Parameters:

  • agent_card (A2A::Types::AgentCard)

    The agent card

  • request_handler (RequestHandler)

    The request handler

  • extended_agent_card (A2A::Types::AgentCard, nil) (defaults to: nil)

    Optional extended agent card

  • card_modifier (Proc, nil) (defaults to: nil)

    Optional card modifier

  • extended_card_modifier (Proc, nil) (defaults to: nil)

    Optional extended card modifier



38
39
40
41
42
43
44
45
# File 'lib/a2a/server/apps/sinatra_app.rb', line 38

def configure_a2a(agent_card:, request_handler:, extended_agent_card: nil, card_modifier: nil,
                  extended_card_modifier: nil)
  self.agent_card = agent_card
  self.request_handler = request_handler
  self.extended_agent_card = extended_agent_card
  self.card_modifier = card_modifier
  self.extended_card_modifier = extended_card_modifier
end

Instance Method Details

#build_server_contextA2A::Server::Context (private)

Build server context from Sinatra request

Returns:



190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
# File 'lib/a2a/server/apps/sinatra_app.rb', line 190

def build_server_context
  context = A2A::Server::Context.new

  # Extract user information if available
  if respond_to?(:current_user) && current_user
    context.set_user(current_user)
  elsif env["warden"]&.authenticated?
    context.set_user(env["warden"].user)
    context.set_authentication("warden", env["warden"])
  end

  # Set request metadata
  context.(:remote_addr, request.ip)
  context.(:user_agent, request.user_agent)
  context.(:headers, request.env.select { |k, _| k.start_with?("HTTP_") })

  context
end

#handle_streaming_response(enumerator) ⇒ String (private)

Handle streaming response using Server-Sent Events

Parameters:

  • enumerator (Enumerator)

    The enumerator yielding events

Returns:

  • (String)

    SSE response



232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
# File 'lib/a2a/server/apps/sinatra_app.rb', line 232

def handle_streaming_response(enumerator)
  content_type "text/event-stream"
  headers "Cache-Control" => "no-cache", "Connection" => "keep-alive"

  stream do |out|
    enumerator.each do |event|
      event_data = if event.respond_to?(:to_h)
                     event.to_h
                   else
                     event
                   end

      out << "data: #{JSON.generate(event_data)}\n\n"
    end
  rescue StandardError => e
    error_event = {
      error: {
        code: A2A::Protocol::JsonRpc::INTERNAL_ERROR,
        message: e.message
      }
    }
    out << "data: #{JSON.generate(error_event)}\n\n"
  ensure
    out << "data: [DONE]\n\n"
  end
end

#json_rpc_error_response(id, code, message, data = nil) ⇒ String (private)

Create a JSON-RPC error response

Parameters:

  • id (String, Integer, nil)

    Request ID

  • code (Integer)

    Error code

  • message (String)

    Error message

  • data (Object, nil) (defaults to: nil)

    Optional error data

Returns:

  • (String)

    JSON response



217
218
219
220
221
222
223
224
225
# File 'lib/a2a/server/apps/sinatra_app.rb', line 217

def json_rpc_error_response(id, code, message, data = nil)
  error_data = A2A::Protocol::JsonRpc.build_error_response(
    code: code,
    message: message,
    data: data,
    id: id
  )
  JSON.generate(error_data)
end

#route_request(request, context) ⇒ Object (private)

Route JSON-RPC request to appropriate handler method

Parameters:

Returns:

  • (Object)

    The result from the handler



161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
# File 'lib/a2a/server/apps/sinatra_app.rb', line 161

def route_request(request, context)
  case request.method
  when "message/send"
    self.class.request_handler.on_message_send(request.params, context)
  when "message/stream"
    self.class.request_handler.on_message_send_stream(request.params, context)
  when "tasks/get"
    self.class.request_handler.on_get_task(request.params, context)
  when "tasks/cancel"
    self.class.request_handler.on_cancel_task(request.params, context)
  when "tasks/resubscribe"
    self.class.request_handler.on_resubscribe_to_task(request.params, context)
  when "tasks/pushNotificationConfig/set"
    self.class.request_handler.on_set_task_push_notification_config(request.params, context)
  when "tasks/pushNotificationConfig/get"
    self.class.request_handler.on_get_task_push_notification_config(request.params, context)
  when "tasks/pushNotificationConfig/list"
    self.class.request_handler.on_list_task_push_notification_config(request.params, context)
  when "tasks/pushNotificationConfig/delete"
    self.class.request_handler.on_delete_task_push_notification_config(request.params, context)
  else
    raise A2A::Errors::MethodNotFound, "Method '#{request.method}' not found"
  end
end