From a2e4a6c889aeaaf4a66997cd97d3fb600bf9fa2b Mon Sep 17 00:00:00 2001 From: David Zhao Date: Sat, 9 Nov 2024 17:05:03 -0600 Subject: [PATCH] Support for explicit agent dispatches --- Gemfile.lock | 5 +- README.md | 2 +- lib/livekit.rb | 1 + lib/livekit/access_token.rb | 20 ++-- lib/livekit/agent_dispatch_service_client.rb | 95 +++++++++++++++++++ lib/livekit/auth_mixin.rb | 4 +- lib/livekit/grants.rb | 15 ++- .../proto/livekit_agent_dispatch_twirp.rb | 2 +- lib/livekit/proto/livekit_agent_twirp.rb | 2 +- lib/livekit/proto/livekit_egress_twirp.rb | 2 +- lib/livekit/proto/livekit_ingress_twirp.rb | 2 +- lib/livekit/proto/livekit_metrics_twirp.rb | 2 +- lib/livekit/proto/livekit_models_twirp.rb | 2 +- lib/livekit/proto/livekit_room_twirp.rb | 2 +- lib/livekit/proto/livekit_sip_pb.rb | 2 +- lib/livekit/proto/livekit_sip_twirp.rb | 2 +- lib/livekit/proto/livekit_webhook_twirp.rb | 2 +- lib/livekit/version.rb | 2 +- protocol | 2 +- spec/livekit/access_token_spec.rb | 54 ++++++++++- spec/livekit/token_verifier_spec.rb | 8 +- 21 files changed, 197 insertions(+), 31 deletions(-) create mode 100644 lib/livekit/agent_dispatch_service_client.rb diff --git a/Gemfile.lock b/Gemfile.lock index 0391f14..8a1aaa9 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - livekit-server-sdk (0.7.0) + livekit-server-sdk (0.7.1) google-protobuf (>= 3.21.0, < 4.0) jwt (>= 2.2.3, < 3.0) rack (>= 2.2.3) @@ -19,10 +19,9 @@ GEM faraday-net_http (3.1.1) net-http google-protobuf (3.25.4) - google-protobuf (3.25.4-x86_64-linux) jwt (2.8.2) base64 - logger (1.6.0) + logger (1.6.1) method_source (1.0.0) net-http (0.4.1) uri diff --git a/README.md b/README.md index 2f33c0a..2c7b650 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,7 @@ require 'livekit' token = LiveKit::AccessToken.new(api_key: 'yourkey', api_secret: 'yoursecret') token.identity = 'participant-identity' token.name = 'participant-name' -token.set_video_grant(LiveKit::VideoGrant.new(roomJoin: true, room: 'room-name')) +token.video_grant = LiveKit::VideoGrant.new(roomJoin: true, room: 'room-name') token.attributes = { "mykey" => "myvalue" } puts token.to_jwt ``` diff --git a/lib/livekit.rb b/lib/livekit.rb index d79a54f..69b091b 100644 --- a/lib/livekit.rb +++ b/lib/livekit.rb @@ -12,3 +12,4 @@ require "livekit/egress_service_client" require "livekit/ingress_service_client" require "livekit/sip_service_client" +require "livekit/agent_dispatch_service_client" diff --git a/lib/livekit/access_token.rb b/lib/livekit/access_token.rb index f3eb7b5..5392055 100644 --- a/lib/livekit/access_token.rb +++ b/lib/livekit/access_token.rb @@ -31,27 +31,27 @@ def initialize( @ttl = ttl end - # Deprecated, use set_video_grant instead + # Deprecated, use video_grant = instead def add_grant(video_grant) if video_grant.is_a?(Hash) video_grant = VideoGrant.from_hash(video_grant) end - self.set_video_grant(video_grant) + self.video_grant = video_grant end - def set_video_grant(video_grant) + def video_grant=(video_grant) @grants.video = video_grant end - # Deprecated, use set_sip_grant instead + # Deprecated, use sip_grant = instead def add_sip_grant(sip_grant) if sip_grant.is_a?(Hash) sip_grant = SIPGrant.from_hash(sip_grant) end - self.set_sip_grant(sip_grant) + self.sip_grant = sip_grant end - def set_sip_grant(sip_grant) + def sip_grant=(sip_grant) @grants.sip = sip_grant end @@ -75,6 +75,14 @@ def sha256=(sha_string) @grants.sha256 = sha_string end + def room_config=(room_config) + @grants.room_config = room_config + end + + def room_preset=(room_preset) + @grants.room_preset = room_preset + end + def to_jwt if @grants.video.nil? && @grants.sip.nil? raise ArgumentError, "VideoGrant or SIPGrant is required" diff --git a/lib/livekit/agent_dispatch_service_client.rb b/lib/livekit/agent_dispatch_service_client.rb new file mode 100644 index 0000000..1dd8e48 --- /dev/null +++ b/lib/livekit/agent_dispatch_service_client.rb @@ -0,0 +1,95 @@ +require "livekit/proto/livekit_agent_dispatch_twirp" +require "livekit/auth_mixin" +require 'livekit/utils' + +module LiveKit + # Client for LiveKit's Agent Dispatch Service, which manages agent assignments to rooms + # This client handles creating, deleting, and retrieving agent dispatches + class AgentDispatchServiceClient < Twirp::Client + client_for Proto::SIPService + include AuthMixin + attr_accessor :api_key, :api_secret + + def initialize(base_url, api_key: nil, api_secret: nil) + super(File.join(Utils.to_http_url(base_url), "/twirp")) + @api_key = api_key + @api_secret = api_secret + end + + # Creates a new agent dispatch for a named agent + # @param room_name [String] The room to dispatch the agent to + # @param agent_name [String] The name of the agent to dispatch + # @param metadata [String, nil] Optional metadata to include with the dispatch + # @return [LiveKit::Proto::AgentDispatch] Dispatch that was just created + def create_dispatch( + # room to dispatch agent to + room_name, + # agent to dispatch + agent_name, + # optional, metadata to send along with the job + metadata: nil + ) + request = Proto::CreateAgentDispatchRequest.new( + room: room_name, + agent_name: agent_name, + metadata: metadata, + ) + self.rpc( + :CreateDispatch, + request, + headers: auth_header(VideoGrant.new(roomAdmin: true, room: room_name)), + ) + end + + # Deletes an existing agent dispatch + # @param dispatch_id [String] The ID of the dispatch to delete + # @param room_name [String] The room name associated with the dispatch + # @return [LiveKit::Proto::AgentDispatch] AgentDispatch record that was deleted + def delete_dispatch(dispatch_id, room_name) + request = Proto::DeleteAgentDispatchRequest.new( + dispatch_id: dispatch_id, + room: room_name, + ) + self.rpc( + :DeleteDispatch, + request, + headers: auth_header(VideoGrant.new(roomAdmin: true, room: room_name)), + ) + end + + # Retrieves a specific agent dispatch by ID + # @param dispatch_id [String] The ID of the dispatch to retrieve + # @param room_name [String] The room name associated with the dispatch + # @return [LiveKit::Proto::AgentDispatch, nil] The agent dispatch if found, nil otherwise + def get_dispatch(dispatch_id, room_name) + request = Proto::ListAgentDispatchRequest.new( + dispatch_id: dispatch_id, + room: room_name, + ) + res = self.rpc( + :ListDispatch, + request, + headers: auth_header(VideoGrant.new(roomAdmin: true, room: room_name)), + ) + if res.agent_dispatches.size > 0 + return res.agent_dispatches[0] + end + nil + end + + # Lists all agent dispatches for a specific room + # @param room_name [String] The room name to list dispatches for + # @return [Array] Array of agent dispatches + def list_dispatch(room_name) + request = Proto::ListAgentDispatchRequest.new( + room: room_name, + ) + res = self.rpc( + :ListDispatch, + request, + headers: auth_header(VideoGrant.new(roomAdmin: true, room: room_name)), + ) + res.agent_dispatches + end + end +end diff --git a/lib/livekit/auth_mixin.rb b/lib/livekit/auth_mixin.rb index b733df7..71f0f9e 100644 --- a/lib/livekit/auth_mixin.rb +++ b/lib/livekit/auth_mixin.rb @@ -10,10 +10,10 @@ def auth_header( headers = {} t = ::LiveKit::AccessToken.new(api_key: @api_key, api_secret: @api_secret) if video_grant != nil - t.set_video_grant(video_grant) + t.video_grant = video_grant end if sip_grant != nil - t.set_sip_grant(sip_grant) + t.sip_grant = sip_grant end headers["Authorization"] = "Bearer #{t.to_jwt}" headers["User-Agent"] = "LiveKit Ruby SDK" diff --git a/lib/livekit/grants.rb b/lib/livekit/grants.rb index 57a40a8..0032619 100644 --- a/lib/livekit/grants.rb +++ b/lib/livekit/grants.rb @@ -2,7 +2,7 @@ module LiveKit class ClaimGrant - attr_accessor :identity, :name, :metadata, :sha256, :video, :sip, :attributes + attr_accessor :identity, :name, :metadata, :sha256, :video, :sip, :attributes, :room_preset, :room_config def self.from_hash(hash) return nil if hash.nil? @@ -15,6 +15,11 @@ def self.from_hash(hash) claim_grant.sha256 = hash["sha256"] claim_grant.video = VideoGrant.from_hash(hash["video"]) claim_grant.sip = SIPGrant.from_hash(hash["sip"]) + claim_grant.room_preset = hash["roomPreset"] + if hash["roomConfig"] + # re-hydrate from JSON to ensure it can parse camelCase fields correctly + claim_grant.room_config = Proto::RoomConfiguration.decode_json(hash["roomConfig"].to_json) + end return claim_grant end @@ -26,6 +31,8 @@ def initialize @video = nil @sip = nil @attributes = nil + @room_preset = nil + @room_config = nil end def to_hash @@ -41,6 +48,12 @@ def to_hash if @sip val[:sip] = @sip.to_hash end + if @room_preset + val[:roomPreset] = @room_preset + end + if @room_config + val[:roomConfig] = JSON.parse(@room_config.to_json) + end return val end end diff --git a/lib/livekit/proto/livekit_agent_dispatch_twirp.rb b/lib/livekit/proto/livekit_agent_dispatch_twirp.rb index d461848..67f2b6c 100644 --- a/lib/livekit/proto/livekit_agent_dispatch_twirp.rb +++ b/lib/livekit/proto/livekit_agent_dispatch_twirp.rb @@ -1,4 +1,4 @@ -# Code generated by protoc-gen-twirp_ruby 1.11.0, DO NOT EDIT. +# Code generated by protoc-gen-twirp_ruby 1.10.0, DO NOT EDIT. require 'twirp' require_relative 'livekit_agent_dispatch_pb.rb' diff --git a/lib/livekit/proto/livekit_agent_twirp.rb b/lib/livekit/proto/livekit_agent_twirp.rb index 84ca408..580b247 100644 --- a/lib/livekit/proto/livekit_agent_twirp.rb +++ b/lib/livekit/proto/livekit_agent_twirp.rb @@ -1,4 +1,4 @@ -# Code generated by protoc-gen-twirp_ruby 1.11.0, DO NOT EDIT. +# Code generated by protoc-gen-twirp_ruby 1.10.0, DO NOT EDIT. require 'twirp' require_relative 'livekit_agent_pb.rb' diff --git a/lib/livekit/proto/livekit_egress_twirp.rb b/lib/livekit/proto/livekit_egress_twirp.rb index b5eca4e..c5d8b61 100644 --- a/lib/livekit/proto/livekit_egress_twirp.rb +++ b/lib/livekit/proto/livekit_egress_twirp.rb @@ -1,4 +1,4 @@ -# Code generated by protoc-gen-twirp_ruby 1.11.0, DO NOT EDIT. +# Code generated by protoc-gen-twirp_ruby 1.10.0, DO NOT EDIT. require 'twirp' require_relative 'livekit_egress_pb.rb' diff --git a/lib/livekit/proto/livekit_ingress_twirp.rb b/lib/livekit/proto/livekit_ingress_twirp.rb index bade624..da65afc 100644 --- a/lib/livekit/proto/livekit_ingress_twirp.rb +++ b/lib/livekit/proto/livekit_ingress_twirp.rb @@ -1,4 +1,4 @@ -# Code generated by protoc-gen-twirp_ruby 1.11.0, DO NOT EDIT. +# Code generated by protoc-gen-twirp_ruby 1.10.0, DO NOT EDIT. require 'twirp' require_relative 'livekit_ingress_pb.rb' diff --git a/lib/livekit/proto/livekit_metrics_twirp.rb b/lib/livekit/proto/livekit_metrics_twirp.rb index c009e66..605f7bc 100644 --- a/lib/livekit/proto/livekit_metrics_twirp.rb +++ b/lib/livekit/proto/livekit_metrics_twirp.rb @@ -1,4 +1,4 @@ -# Code generated by protoc-gen-twirp_ruby 1.11.0, DO NOT EDIT. +# Code generated by protoc-gen-twirp_ruby 1.10.0, DO NOT EDIT. require 'twirp' require_relative 'livekit_metrics_pb.rb' diff --git a/lib/livekit/proto/livekit_models_twirp.rb b/lib/livekit/proto/livekit_models_twirp.rb index f97b809..0691b5f 100644 --- a/lib/livekit/proto/livekit_models_twirp.rb +++ b/lib/livekit/proto/livekit_models_twirp.rb @@ -1,4 +1,4 @@ -# Code generated by protoc-gen-twirp_ruby 1.11.0, DO NOT EDIT. +# Code generated by protoc-gen-twirp_ruby 1.10.0, DO NOT EDIT. require 'twirp' require_relative 'livekit_models_pb.rb' diff --git a/lib/livekit/proto/livekit_room_twirp.rb b/lib/livekit/proto/livekit_room_twirp.rb index 575e82c..e19b1f2 100644 --- a/lib/livekit/proto/livekit_room_twirp.rb +++ b/lib/livekit/proto/livekit_room_twirp.rb @@ -1,4 +1,4 @@ -# Code generated by protoc-gen-twirp_ruby 1.11.0, DO NOT EDIT. +# Code generated by protoc-gen-twirp_ruby 1.10.0, DO NOT EDIT. require 'twirp' require_relative 'livekit_room_pb.rb' diff --git a/lib/livekit/proto/livekit_sip_pb.rb b/lib/livekit/proto/livekit_sip_pb.rb index 79b7356..8ab062c 100644 --- a/lib/livekit/proto/livekit_sip_pb.rb +++ b/lib/livekit/proto/livekit_sip_pb.rb @@ -9,7 +9,7 @@ require 'livekit_models_pb' -descriptor_data = "\n\x11livekit_sip.proto\x12\x07livekit\x1a\x1egoogle/protobuf/duration.proto\x1a\x1bgoogle/protobuf/empty.proto\x1a\x14livekit_models.proto\"\xaf\x02\n\x15\x43reateSIPTrunkRequest\x12\x19\n\x11inbound_addresses\x18\x01 \x03(\t\x12\x18\n\x10outbound_address\x18\x02 \x01(\t\x12\x17\n\x0foutbound_number\x18\x03 \x01(\t\x12!\n\x15inbound_numbers_regex\x18\x04 \x03(\tB\x02\x18\x01\x12\x17\n\x0finbound_numbers\x18\t \x03(\t\x12\x18\n\x10inbound_username\x18\x05 \x01(\t\x12\x18\n\x10inbound_password\x18\x06 \x01(\t\x12\x19\n\x11outbound_username\x18\x07 \x01(\t\x12\x19\n\x11outbound_password\x18\x08 \x01(\t\x12\x0c\n\x04name\x18\n \x01(\t\x12\x10\n\x08metadata\x18\x0b \x01(\t:\x02\x18\x01\"\xdb\x03\n\x0cSIPTrunkInfo\x12\x14\n\x0csip_trunk_id\x18\x01 \x01(\t\x12-\n\x04kind\x18\x0e \x01(\x0e\x32\x1f.livekit.SIPTrunkInfo.TrunkKind\x12\x19\n\x11inbound_addresses\x18\x02 \x03(\t\x12\x18\n\x10outbound_address\x18\x03 \x01(\t\x12\x17\n\x0foutbound_number\x18\x04 \x01(\t\x12(\n\ttransport\x18\r \x01(\x0e\x32\x15.livekit.SIPTransport\x12!\n\x15inbound_numbers_regex\x18\x05 \x03(\tB\x02\x18\x01\x12\x17\n\x0finbound_numbers\x18\n \x03(\t\x12\x18\n\x10inbound_username\x18\x06 \x01(\t\x12\x18\n\x10inbound_password\x18\x07 \x01(\t\x12\x19\n\x11outbound_username\x18\x08 \x01(\t\x12\x19\n\x11outbound_password\x18\t \x01(\t\x12\x0c\n\x04name\x18\x0b \x01(\t\x12\x10\n\x08metadata\x18\x0c \x01(\t\"D\n\tTrunkKind\x12\x10\n\x0cTRUNK_LEGACY\x10\x00\x12\x11\n\rTRUNK_INBOUND\x10\x01\x12\x12\n\x0eTRUNK_OUTBOUND\x10\x02:\x02\x18\x01\"K\n\x1c\x43reateSIPInboundTrunkRequest\x12+\n\x05trunk\x18\x01 \x01(\x0b\x32\x1c.livekit.SIPInboundTrunkInfo\"\xbd\x04\n\x13SIPInboundTrunkInfo\x12\x14\n\x0csip_trunk_id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x10\n\x08metadata\x18\x03 \x01(\t\x12\x0f\n\x07numbers\x18\x04 \x03(\t\x12\x19\n\x11\x61llowed_addresses\x18\x05 \x03(\t\x12\x17\n\x0f\x61llowed_numbers\x18\x06 \x03(\t\x12\x15\n\rauth_username\x18\x07 \x01(\t\x12\x15\n\rauth_password\x18\x08 \x01(\t\x12:\n\x07headers\x18\t \x03(\x0b\x32).livekit.SIPInboundTrunkInfo.HeadersEntry\x12T\n\x15headers_to_attributes\x18\n \x03(\x0b\x32\x35.livekit.SIPInboundTrunkInfo.HeadersToAttributesEntry\x12\x32\n\x0fringing_timeout\x18\x0b \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x34\n\x11max_call_duration\x18\x0c \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x15\n\rkrisp_enabled\x18\r \x01(\x08\x1a.\n\x0cHeadersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a:\n\x18HeadersToAttributesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"M\n\x1d\x43reateSIPOutboundTrunkRequest\x12,\n\x05trunk\x18\x01 \x01(\x0b\x32\x1d.livekit.SIPOutboundTrunkInfo\"\xc6\x03\n\x14SIPOutboundTrunkInfo\x12\x14\n\x0csip_trunk_id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x10\n\x08metadata\x18\x03 \x01(\t\x12\x0f\n\x07\x61\x64\x64ress\x18\x04 \x01(\t\x12(\n\ttransport\x18\x05 \x01(\x0e\x32\x15.livekit.SIPTransport\x12\x0f\n\x07numbers\x18\x06 \x03(\t\x12\x15\n\rauth_username\x18\x07 \x01(\t\x12\x15\n\rauth_password\x18\x08 \x01(\t\x12;\n\x07headers\x18\t \x03(\x0b\x32*.livekit.SIPOutboundTrunkInfo.HeadersEntry\x12U\n\x15headers_to_attributes\x18\n \x03(\x0b\x32\x36.livekit.SIPOutboundTrunkInfo.HeadersToAttributesEntry\x1a.\n\x0cHeadersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a:\n\x18HeadersToAttributesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"1\n\x19GetSIPInboundTrunkRequest\x12\x14\n\x0csip_trunk_id\x18\x01 \x01(\t\"I\n\x1aGetSIPInboundTrunkResponse\x12+\n\x05trunk\x18\x01 \x01(\x0b\x32\x1c.livekit.SIPInboundTrunkInfo\"2\n\x1aGetSIPOutboundTrunkRequest\x12\x14\n\x0csip_trunk_id\x18\x01 \x01(\t\"K\n\x1bGetSIPOutboundTrunkResponse\x12,\n\x05trunk\x18\x01 \x01(\x0b\x32\x1d.livekit.SIPOutboundTrunkInfo\"\x19\n\x13ListSIPTrunkRequest:\x02\x18\x01\"@\n\x14ListSIPTrunkResponse\x12$\n\x05items\x18\x01 \x03(\x0b\x32\x15.livekit.SIPTrunkInfo:\x02\x18\x01\"\x1c\n\x1aListSIPInboundTrunkRequest\"J\n\x1bListSIPInboundTrunkResponse\x12+\n\x05items\x18\x01 \x03(\x0b\x32\x1c.livekit.SIPInboundTrunkInfo\"\x1d\n\x1bListSIPOutboundTrunkRequest\"L\n\x1cListSIPOutboundTrunkResponse\x12,\n\x05items\x18\x01 \x03(\x0b\x32\x1d.livekit.SIPOutboundTrunkInfo\"-\n\x15\x44\x65leteSIPTrunkRequest\x12\x14\n\x0csip_trunk_id\x18\x01 \x01(\t\"7\n\x15SIPDispatchRuleDirect\x12\x11\n\troom_name\x18\x01 \x01(\t\x12\x0b\n\x03pin\x18\x02 \x01(\t\"=\n\x19SIPDispatchRuleIndividual\x12\x13\n\x0broom_prefix\x18\x01 \x01(\t\x12\x0b\n\x03pin\x18\x02 \x01(\t\"L\n\x15SIPDispatchRuleCallee\x12\x13\n\x0broom_prefix\x18\x01 \x01(\t\x12\x0b\n\x03pin\x18\x02 \x01(\t\x12\x11\n\trandomize\x18\x03 \x01(\x08\"\xe1\x01\n\x0fSIPDispatchRule\x12>\n\x14\x64ispatch_rule_direct\x18\x01 \x01(\x0b\x32\x1e.livekit.SIPDispatchRuleDirectH\x00\x12\x46\n\x18\x64ispatch_rule_individual\x18\x02 \x01(\x0b\x32\".livekit.SIPDispatchRuleIndividualH\x00\x12>\n\x14\x64ispatch_rule_callee\x18\x03 \x01(\x0b\x32\x1e.livekit.SIPDispatchRuleCalleeH\x00\x42\x06\n\x04rule\"\xab\x02\n\x1c\x43reateSIPDispatchRuleRequest\x12&\n\x04rule\x18\x01 \x01(\x0b\x32\x18.livekit.SIPDispatchRule\x12\x11\n\ttrunk_ids\x18\x02 \x03(\t\x12\x19\n\x11hide_phone_number\x18\x03 \x01(\x08\x12\x17\n\x0finbound_numbers\x18\x06 \x03(\t\x12\x0c\n\x04name\x18\x04 \x01(\t\x12\x10\n\x08metadata\x18\x05 \x01(\t\x12I\n\nattributes\x18\x07 \x03(\x0b\x32\x35.livekit.CreateSIPDispatchRuleRequest.AttributesEntry\x1a\x31\n\x0f\x41ttributesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\xb7\x02\n\x13SIPDispatchRuleInfo\x12\x1c\n\x14sip_dispatch_rule_id\x18\x01 \x01(\t\x12&\n\x04rule\x18\x02 \x01(\x0b\x32\x18.livekit.SIPDispatchRule\x12\x11\n\ttrunk_ids\x18\x03 \x03(\t\x12\x19\n\x11hide_phone_number\x18\x04 \x01(\x08\x12\x17\n\x0finbound_numbers\x18\x07 \x03(\t\x12\x0c\n\x04name\x18\x05 \x01(\t\x12\x10\n\x08metadata\x18\x06 \x01(\t\x12@\n\nattributes\x18\x08 \x03(\x0b\x32,.livekit.SIPDispatchRuleInfo.AttributesEntry\x1a\x31\n\x0f\x41ttributesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\x1c\n\x1aListSIPDispatchRuleRequest\"J\n\x1bListSIPDispatchRuleResponse\x12+\n\x05items\x18\x01 \x03(\x0b\x32\x1c.livekit.SIPDispatchRuleInfo\"<\n\x1c\x44\x65leteSIPDispatchRuleRequest\x12\x1c\n\x14sip_dispatch_rule_id\x18\x01 \x01(\t\"\x95\x04\n\x1b\x43reateSIPParticipantRequest\x12\x14\n\x0csip_trunk_id\x18\x01 \x01(\t\x12\x13\n\x0bsip_call_to\x18\x02 \x01(\t\x12\x11\n\troom_name\x18\x03 \x01(\t\x12\x1c\n\x14participant_identity\x18\x04 \x01(\t\x12\x18\n\x10participant_name\x18\x07 \x01(\t\x12\x1c\n\x14participant_metadata\x18\x08 \x01(\t\x12_\n\x16participant_attributes\x18\t \x03(\x0b\x32?.livekit.CreateSIPParticipantRequest.ParticipantAttributesEntry\x12\x0c\n\x04\x64tmf\x18\x05 \x01(\t\x12\x19\n\rplay_ringtone\x18\x06 \x01(\x08\x42\x02\x18\x01\x12\x15\n\rplay_dialtone\x18\r \x01(\x08\x12\x19\n\x11hide_phone_number\x18\n \x01(\x08\x12\x32\n\x0fringing_timeout\x18\x0b \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x34\n\x11max_call_duration\x18\x0c \x01(\x0b\x32\x19.google.protobuf.Duration\x1a<\n\x1aParticipantAttributesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"r\n\x12SIPParticipantInfo\x12\x16\n\x0eparticipant_id\x18\x01 \x01(\t\x12\x1c\n\x14participant_identity\x18\x02 \x01(\t\x12\x11\n\troom_name\x18\x03 \x01(\t\x12\x13\n\x0bsip_call_id\x18\x04 \x01(\t\"|\n\x1dTransferSIPParticipantRequest\x12\x1c\n\x14participant_identity\x18\x01 \x01(\t\x12\x11\n\troom_name\x18\x02 \x01(\t\x12\x13\n\x0btransfer_to\x18\x03 \x01(\t\x12\x15\n\rplay_dialtone\x18\x04 \x01(\x08\"\xbf\x02\n\x0bSIPCallInfo\x12\x0f\n\x07\x63\x61ll_id\x18\x01 \x01(\t\x12\x10\n\x08trunk_id\x18\x02 \x01(\t\x12\x11\n\troom_name\x18\x03 \x01(\t\x12\x0f\n\x07room_id\x18\x04 \x01(\t\x12\x1c\n\x14participant_identity\x18\x05 \x01(\t\x12!\n\x08\x66rom_uri\x18\x06 \x01(\x0b\x32\x0f.livekit.SIPUri\x12\x1f\n\x06to_uri\x18\x07 \x01(\x0b\x32\x0f.livekit.SIPUri\x12+\n\x0b\x63\x61ll_status\x18\x08 \x01(\x0e\x32\x16.livekit.SIPCallStatus\x12\x12\n\nstarted_at\x18\t \x01(\x03\x12\x10\n\x08\x65nded_at\x18\n \x01(\x03\x12\x34\n\x11\x64isconnect_reason\x18\x0b \x01(\x0e\x32\x19.livekit.DisconnectReason\"h\n\x06SIPUri\x12\x0c\n\x04user\x18\x01 \x01(\t\x12\x0c\n\x04host\x18\x02 \x01(\t\x12\n\n\x02ip\x18\x03 \x01(\t\x12\x0c\n\x04port\x18\x04 \x01(\t\x12(\n\ttransport\x18\x05 \x01(\x0e\x32\x15.livekit.SIPTransport*k\n\x0cSIPTransport\x12\x16\n\x12SIP_TRANSPORT_AUTO\x10\x00\x12\x15\n\x11SIP_TRANSPORT_UDP\x10\x01\x12\x15\n\x11SIP_TRANSPORT_TCP\x10\x02\x12\x15\n\x11SIP_TRANSPORT_TLS\x10\x03*h\n\rSIPCallStatus\x12\x15\n\x11SCS_CALL_INCOMING\x10\x00\x12\x1a\n\x16SCS_PARTICIPANT_JOINED\x10\x01\x12\x0e\n\nSCS_ACTIVE\x10\x02\x12\x14\n\x10SCS_DISCONNECTED\x10\x03\x32\xba\t\n\x03SIP\x12P\n\x0cListSIPTrunk\x12\x1c.livekit.ListSIPTrunkRequest\x1a\x1d.livekit.ListSIPTrunkResponse\"\x03\x88\x02\x01\x12\\\n\x15\x43reateSIPInboundTrunk\x12%.livekit.CreateSIPInboundTrunkRequest\x1a\x1c.livekit.SIPInboundTrunkInfo\x12_\n\x16\x43reateSIPOutboundTrunk\x12&.livekit.CreateSIPOutboundTrunkRequest\x1a\x1d.livekit.SIPOutboundTrunkInfo\x12]\n\x12GetSIPInboundTrunk\x12\".livekit.GetSIPInboundTrunkRequest\x1a#.livekit.GetSIPInboundTrunkResponse\x12`\n\x13GetSIPOutboundTrunk\x12#.livekit.GetSIPOutboundTrunkRequest\x1a$.livekit.GetSIPOutboundTrunkResponse\x12`\n\x13ListSIPInboundTrunk\x12#.livekit.ListSIPInboundTrunkRequest\x1a$.livekit.ListSIPInboundTrunkResponse\x12\x63\n\x14ListSIPOutboundTrunk\x12$.livekit.ListSIPOutboundTrunkRequest\x1a%.livekit.ListSIPOutboundTrunkResponse\x12G\n\x0e\x44\x65leteSIPTrunk\x12\x1e.livekit.DeleteSIPTrunkRequest\x1a\x15.livekit.SIPTrunkInfo\x12\\\n\x15\x43reateSIPDispatchRule\x12%.livekit.CreateSIPDispatchRuleRequest\x1a\x1c.livekit.SIPDispatchRuleInfo\x12`\n\x13ListSIPDispatchRule\x12#.livekit.ListSIPDispatchRuleRequest\x1a$.livekit.ListSIPDispatchRuleResponse\x12\\\n\x15\x44\x65leteSIPDispatchRule\x12%.livekit.DeleteSIPDispatchRuleRequest\x1a\x1c.livekit.SIPDispatchRuleInfo\x12Y\n\x14\x43reateSIPParticipant\x12$.livekit.CreateSIPParticipantRequest\x1a\x1b.livekit.SIPParticipantInfo\x12X\n\x16TransferSIPParticipant\x12&.livekit.TransferSIPParticipantRequest\x1a\x16.google.protobuf.EmptyBFZ#github.com/livekit/protocol/livekit\xaa\x02\rLiveKit.Proto\xea\x02\x0eLiveKit::Protob\x06proto3" +descriptor_data = "\n\x11livekit_sip.proto\x12\x07livekit\x1a\x1egoogle/protobuf/duration.proto\x1a\x1bgoogle/protobuf/empty.proto\x1a\x14livekit_models.proto\"\xaf\x02\n\x15\x43reateSIPTrunkRequest\x12\x19\n\x11inbound_addresses\x18\x01 \x03(\t\x12\x18\n\x10outbound_address\x18\x02 \x01(\t\x12\x17\n\x0foutbound_number\x18\x03 \x01(\t\x12!\n\x15inbound_numbers_regex\x18\x04 \x03(\tB\x02\x18\x01\x12\x17\n\x0finbound_numbers\x18\t \x03(\t\x12\x18\n\x10inbound_username\x18\x05 \x01(\t\x12\x18\n\x10inbound_password\x18\x06 \x01(\t\x12\x19\n\x11outbound_username\x18\x07 \x01(\t\x12\x19\n\x11outbound_password\x18\x08 \x01(\t\x12\x0c\n\x04name\x18\n \x01(\t\x12\x10\n\x08metadata\x18\x0b \x01(\t:\x02\x18\x01\"\xdb\x03\n\x0cSIPTrunkInfo\x12\x14\n\x0csip_trunk_id\x18\x01 \x01(\t\x12-\n\x04kind\x18\x0e \x01(\x0e\x32\x1f.livekit.SIPTrunkInfo.TrunkKind\x12\x19\n\x11inbound_addresses\x18\x02 \x03(\t\x12\x18\n\x10outbound_address\x18\x03 \x01(\t\x12\x17\n\x0foutbound_number\x18\x04 \x01(\t\x12(\n\ttransport\x18\r \x01(\x0e\x32\x15.livekit.SIPTransport\x12!\n\x15inbound_numbers_regex\x18\x05 \x03(\tB\x02\x18\x01\x12\x17\n\x0finbound_numbers\x18\n \x03(\t\x12\x18\n\x10inbound_username\x18\x06 \x01(\t\x12\x18\n\x10inbound_password\x18\x07 \x01(\t\x12\x19\n\x11outbound_username\x18\x08 \x01(\t\x12\x19\n\x11outbound_password\x18\t \x01(\t\x12\x0c\n\x04name\x18\x0b \x01(\t\x12\x10\n\x08metadata\x18\x0c \x01(\t\"D\n\tTrunkKind\x12\x10\n\x0cTRUNK_LEGACY\x10\x00\x12\x11\n\rTRUNK_INBOUND\x10\x01\x12\x12\n\x0eTRUNK_OUTBOUND\x10\x02:\x02\x18\x01\"K\n\x1c\x43reateSIPInboundTrunkRequest\x12+\n\x05trunk\x18\x01 \x01(\x0b\x32\x1c.livekit.SIPInboundTrunkInfo\"\xbd\x04\n\x13SIPInboundTrunkInfo\x12\x14\n\x0csip_trunk_id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x10\n\x08metadata\x18\x03 \x01(\t\x12\x0f\n\x07numbers\x18\x04 \x03(\t\x12\x19\n\x11\x61llowed_addresses\x18\x05 \x03(\t\x12\x17\n\x0f\x61llowed_numbers\x18\x06 \x03(\t\x12\x15\n\rauth_username\x18\x07 \x01(\t\x12\x15\n\rauth_password\x18\x08 \x01(\t\x12:\n\x07headers\x18\t \x03(\x0b\x32).livekit.SIPInboundTrunkInfo.HeadersEntry\x12T\n\x15headers_to_attributes\x18\n \x03(\x0b\x32\x35.livekit.SIPInboundTrunkInfo.HeadersToAttributesEntry\x12\x32\n\x0fringing_timeout\x18\x0b \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x34\n\x11max_call_duration\x18\x0c \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x15\n\rkrisp_enabled\x18\r \x01(\x08\x1a.\n\x0cHeadersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a:\n\x18HeadersToAttributesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"M\n\x1d\x43reateSIPOutboundTrunkRequest\x12,\n\x05trunk\x18\x01 \x01(\x0b\x32\x1d.livekit.SIPOutboundTrunkInfo\"\xc6\x03\n\x14SIPOutboundTrunkInfo\x12\x14\n\x0csip_trunk_id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x10\n\x08metadata\x18\x03 \x01(\t\x12\x0f\n\x07\x61\x64\x64ress\x18\x04 \x01(\t\x12(\n\ttransport\x18\x05 \x01(\x0e\x32\x15.livekit.SIPTransport\x12\x0f\n\x07numbers\x18\x06 \x03(\t\x12\x15\n\rauth_username\x18\x07 \x01(\t\x12\x15\n\rauth_password\x18\x08 \x01(\t\x12;\n\x07headers\x18\t \x03(\x0b\x32*.livekit.SIPOutboundTrunkInfo.HeadersEntry\x12U\n\x15headers_to_attributes\x18\n \x03(\x0b\x32\x36.livekit.SIPOutboundTrunkInfo.HeadersToAttributesEntry\x1a.\n\x0cHeadersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a:\n\x18HeadersToAttributesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"1\n\x19GetSIPInboundTrunkRequest\x12\x14\n\x0csip_trunk_id\x18\x01 \x01(\t\"I\n\x1aGetSIPInboundTrunkResponse\x12+\n\x05trunk\x18\x01 \x01(\x0b\x32\x1c.livekit.SIPInboundTrunkInfo\"2\n\x1aGetSIPOutboundTrunkRequest\x12\x14\n\x0csip_trunk_id\x18\x01 \x01(\t\"K\n\x1bGetSIPOutboundTrunkResponse\x12,\n\x05trunk\x18\x01 \x01(\x0b\x32\x1d.livekit.SIPOutboundTrunkInfo\"\x19\n\x13ListSIPTrunkRequest:\x02\x18\x01\"@\n\x14ListSIPTrunkResponse\x12$\n\x05items\x18\x01 \x03(\x0b\x32\x15.livekit.SIPTrunkInfo:\x02\x18\x01\"\x1c\n\x1aListSIPInboundTrunkRequest\"J\n\x1bListSIPInboundTrunkResponse\x12+\n\x05items\x18\x01 \x03(\x0b\x32\x1c.livekit.SIPInboundTrunkInfo\"\x1d\n\x1bListSIPOutboundTrunkRequest\"L\n\x1cListSIPOutboundTrunkResponse\x12,\n\x05items\x18\x01 \x03(\x0b\x32\x1d.livekit.SIPOutboundTrunkInfo\"-\n\x15\x44\x65leteSIPTrunkRequest\x12\x14\n\x0csip_trunk_id\x18\x01 \x01(\t\"7\n\x15SIPDispatchRuleDirect\x12\x11\n\troom_name\x18\x01 \x01(\t\x12\x0b\n\x03pin\x18\x02 \x01(\t\"=\n\x19SIPDispatchRuleIndividual\x12\x13\n\x0broom_prefix\x18\x01 \x01(\t\x12\x0b\n\x03pin\x18\x02 \x01(\t\"L\n\x15SIPDispatchRuleCallee\x12\x13\n\x0broom_prefix\x18\x01 \x01(\t\x12\x0b\n\x03pin\x18\x02 \x01(\t\x12\x11\n\trandomize\x18\x03 \x01(\x08\"\xe1\x01\n\x0fSIPDispatchRule\x12>\n\x14\x64ispatch_rule_direct\x18\x01 \x01(\x0b\x32\x1e.livekit.SIPDispatchRuleDirectH\x00\x12\x46\n\x18\x64ispatch_rule_individual\x18\x02 \x01(\x0b\x32\".livekit.SIPDispatchRuleIndividualH\x00\x12>\n\x14\x64ispatch_rule_callee\x18\x03 \x01(\x0b\x32\x1e.livekit.SIPDispatchRuleCalleeH\x00\x42\x06\n\x04rule\"\xab\x02\n\x1c\x43reateSIPDispatchRuleRequest\x12&\n\x04rule\x18\x01 \x01(\x0b\x32\x18.livekit.SIPDispatchRule\x12\x11\n\ttrunk_ids\x18\x02 \x03(\t\x12\x19\n\x11hide_phone_number\x18\x03 \x01(\x08\x12\x17\n\x0finbound_numbers\x18\x06 \x03(\t\x12\x0c\n\x04name\x18\x04 \x01(\t\x12\x10\n\x08metadata\x18\x05 \x01(\t\x12I\n\nattributes\x18\x07 \x03(\x0b\x32\x35.livekit.CreateSIPDispatchRuleRequest.AttributesEntry\x1a\x31\n\x0f\x41ttributesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\xb7\x02\n\x13SIPDispatchRuleInfo\x12\x1c\n\x14sip_dispatch_rule_id\x18\x01 \x01(\t\x12&\n\x04rule\x18\x02 \x01(\x0b\x32\x18.livekit.SIPDispatchRule\x12\x11\n\ttrunk_ids\x18\x03 \x03(\t\x12\x19\n\x11hide_phone_number\x18\x04 \x01(\x08\x12\x17\n\x0finbound_numbers\x18\x07 \x03(\t\x12\x0c\n\x04name\x18\x05 \x01(\t\x12\x10\n\x08metadata\x18\x06 \x01(\t\x12@\n\nattributes\x18\x08 \x03(\x0b\x32,.livekit.SIPDispatchRuleInfo.AttributesEntry\x1a\x31\n\x0f\x41ttributesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\x1c\n\x1aListSIPDispatchRuleRequest\"J\n\x1bListSIPDispatchRuleResponse\x12+\n\x05items\x18\x01 \x03(\x0b\x32\x1c.livekit.SIPDispatchRuleInfo\"<\n\x1c\x44\x65leteSIPDispatchRuleRequest\x12\x1c\n\x14sip_dispatch_rule_id\x18\x01 \x01(\t\"\xab\x04\n\x1b\x43reateSIPParticipantRequest\x12\x14\n\x0csip_trunk_id\x18\x01 \x01(\t\x12\x13\n\x0bsip_call_to\x18\x02 \x01(\t\x12\x11\n\troom_name\x18\x03 \x01(\t\x12\x1c\n\x14participant_identity\x18\x04 \x01(\t\x12\x18\n\x10participant_name\x18\x07 \x01(\t\x12\x1c\n\x14participant_metadata\x18\x08 \x01(\t\x12_\n\x16participant_attributes\x18\t \x03(\x0b\x32?.livekit.CreateSIPParticipantRequest.ParticipantAttributesEntry\x12\x0c\n\x04\x64tmf\x18\x05 \x01(\t\x12\x19\n\rplay_ringtone\x18\x06 \x01(\x08\x42\x02\x18\x01\x12\x15\n\rplay_dialtone\x18\r \x01(\x08\x12\x19\n\x11hide_phone_number\x18\n \x01(\x08\x12\x32\n\x0fringing_timeout\x18\x0b \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x34\n\x11max_call_duration\x18\x0c \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x14\n\x0c\x65nable_krisp\x18\x0e \x01(\x08\x1a<\n\x1aParticipantAttributesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"r\n\x12SIPParticipantInfo\x12\x16\n\x0eparticipant_id\x18\x01 \x01(\t\x12\x1c\n\x14participant_identity\x18\x02 \x01(\t\x12\x11\n\troom_name\x18\x03 \x01(\t\x12\x13\n\x0bsip_call_id\x18\x04 \x01(\t\"|\n\x1dTransferSIPParticipantRequest\x12\x1c\n\x14participant_identity\x18\x01 \x01(\t\x12\x11\n\troom_name\x18\x02 \x01(\t\x12\x13\n\x0btransfer_to\x18\x03 \x01(\t\x12\x15\n\rplay_dialtone\x18\x04 \x01(\x08\"\xe2\x02\n\x0bSIPCallInfo\x12\x0f\n\x07\x63\x61ll_id\x18\x01 \x01(\t\x12\x10\n\x08trunk_id\x18\x02 \x01(\t\x12\x11\n\troom_name\x18\x03 \x01(\t\x12\x0f\n\x07room_id\x18\x04 \x01(\t\x12\x1c\n\x14participant_identity\x18\x05 \x01(\t\x12!\n\x08\x66rom_uri\x18\x06 \x01(\x0b\x32\x0f.livekit.SIPUri\x12\x1f\n\x06to_uri\x18\x07 \x01(\x0b\x32\x0f.livekit.SIPUri\x12+\n\x0b\x63\x61ll_status\x18\x08 \x01(\x0e\x32\x16.livekit.SIPCallStatus\x12\x12\n\ncreated_at\x18\t \x01(\x03\x12\x12\n\nstarted_at\x18\n \x01(\x03\x12\x10\n\x08\x65nded_at\x18\x0b \x01(\x03\x12\x34\n\x11\x64isconnect_reason\x18\x0c \x01(\x0e\x32\x19.livekit.DisconnectReason\x12\r\n\x05\x65rror\x18\r \x01(\t\"h\n\x06SIPUri\x12\x0c\n\x04user\x18\x01 \x01(\t\x12\x0c\n\x04host\x18\x02 \x01(\t\x12\n\n\x02ip\x18\x03 \x01(\t\x12\x0c\n\x04port\x18\x04 \x01(\t\x12(\n\ttransport\x18\x05 \x01(\x0e\x32\x15.livekit.SIPTransport*k\n\x0cSIPTransport\x12\x16\n\x12SIP_TRANSPORT_AUTO\x10\x00\x12\x15\n\x11SIP_TRANSPORT_UDP\x10\x01\x12\x15\n\x11SIP_TRANSPORT_TCP\x10\x02\x12\x15\n\x11SIP_TRANSPORT_TLS\x10\x03*w\n\rSIPCallStatus\x12\x15\n\x11SCS_CALL_INCOMING\x10\x00\x12\x1a\n\x16SCS_PARTICIPANT_JOINED\x10\x01\x12\x0e\n\nSCS_ACTIVE\x10\x02\x12\x14\n\x10SCS_DISCONNECTED\x10\x03\x12\r\n\tSCS_ERROR\x10\x04\x32\xba\t\n\x03SIP\x12P\n\x0cListSIPTrunk\x12\x1c.livekit.ListSIPTrunkRequest\x1a\x1d.livekit.ListSIPTrunkResponse\"\x03\x88\x02\x01\x12\\\n\x15\x43reateSIPInboundTrunk\x12%.livekit.CreateSIPInboundTrunkRequest\x1a\x1c.livekit.SIPInboundTrunkInfo\x12_\n\x16\x43reateSIPOutboundTrunk\x12&.livekit.CreateSIPOutboundTrunkRequest\x1a\x1d.livekit.SIPOutboundTrunkInfo\x12]\n\x12GetSIPInboundTrunk\x12\".livekit.GetSIPInboundTrunkRequest\x1a#.livekit.GetSIPInboundTrunkResponse\x12`\n\x13GetSIPOutboundTrunk\x12#.livekit.GetSIPOutboundTrunkRequest\x1a$.livekit.GetSIPOutboundTrunkResponse\x12`\n\x13ListSIPInboundTrunk\x12#.livekit.ListSIPInboundTrunkRequest\x1a$.livekit.ListSIPInboundTrunkResponse\x12\x63\n\x14ListSIPOutboundTrunk\x12$.livekit.ListSIPOutboundTrunkRequest\x1a%.livekit.ListSIPOutboundTrunkResponse\x12G\n\x0e\x44\x65leteSIPTrunk\x12\x1e.livekit.DeleteSIPTrunkRequest\x1a\x15.livekit.SIPTrunkInfo\x12\\\n\x15\x43reateSIPDispatchRule\x12%.livekit.CreateSIPDispatchRuleRequest\x1a\x1c.livekit.SIPDispatchRuleInfo\x12`\n\x13ListSIPDispatchRule\x12#.livekit.ListSIPDispatchRuleRequest\x1a$.livekit.ListSIPDispatchRuleResponse\x12\\\n\x15\x44\x65leteSIPDispatchRule\x12%.livekit.DeleteSIPDispatchRuleRequest\x1a\x1c.livekit.SIPDispatchRuleInfo\x12Y\n\x14\x43reateSIPParticipant\x12$.livekit.CreateSIPParticipantRequest\x1a\x1b.livekit.SIPParticipantInfo\x12X\n\x16TransferSIPParticipant\x12&.livekit.TransferSIPParticipantRequest\x1a\x16.google.protobuf.EmptyBFZ#github.com/livekit/protocol/livekit\xaa\x02\rLiveKit.Proto\xea\x02\x0eLiveKit::Protob\x06proto3" pool = Google::Protobuf::DescriptorPool.generated_pool pool.add_serialized_file(descriptor_data) diff --git a/lib/livekit/proto/livekit_sip_twirp.rb b/lib/livekit/proto/livekit_sip_twirp.rb index 7f6923c..e51f2e9 100644 --- a/lib/livekit/proto/livekit_sip_twirp.rb +++ b/lib/livekit/proto/livekit_sip_twirp.rb @@ -1,4 +1,4 @@ -# Code generated by protoc-gen-twirp_ruby 1.11.0, DO NOT EDIT. +# Code generated by protoc-gen-twirp_ruby 1.10.0, DO NOT EDIT. require 'twirp' require_relative 'livekit_sip_pb.rb' diff --git a/lib/livekit/proto/livekit_webhook_twirp.rb b/lib/livekit/proto/livekit_webhook_twirp.rb index 2fdd762..94d9a01 100644 --- a/lib/livekit/proto/livekit_webhook_twirp.rb +++ b/lib/livekit/proto/livekit_webhook_twirp.rb @@ -1,4 +1,4 @@ -# Code generated by protoc-gen-twirp_ruby 1.11.0, DO NOT EDIT. +# Code generated by protoc-gen-twirp_ruby 1.10.0, DO NOT EDIT. require 'twirp' require_relative 'livekit_webhook_pb.rb' diff --git a/lib/livekit/version.rb b/lib/livekit/version.rb index c8d96f6..32fd43a 100644 --- a/lib/livekit/version.rb +++ b/lib/livekit/version.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true module LiveKit - VERSION = "0.7.1" + VERSION = "0.8.0" end diff --git a/protocol b/protocol index caa595e..3aee320 160000 --- a/protocol +++ b/protocol @@ -1 +1 @@ -Subproject commit caa595ed32926f47977a9e0a863a28341ff889d4 +Subproject commit 3aee320bc87c9ce02d0f51a9155b5817647b287d diff --git a/spec/livekit/access_token_spec.rb b/spec/livekit/access_token_spec.rb index 19dced8..2e50d95 100644 --- a/spec/livekit/access_token_spec.rb +++ b/spec/livekit/access_token_spec.rb @@ -6,7 +6,7 @@ RSpec.describe LiveKit::AccessToken do it "generates a valid JWT with defaults" do token = described_class.new(api_key: TEST_KEY, api_secret: TEST_SECRET) - token.set_video_grant LiveKit::VideoGrant.new + token.video_grant = LiveKit::VideoGrant.new jwt = token.to_jwt decoded = JWT.decode(jwt, TEST_SECRET, true, algorithm: "HS256") expect(decoded.first["iss"]).to eq(TEST_KEY) @@ -24,7 +24,7 @@ token = described_class.new(api_key: TEST_KEY, api_secret: TEST_SECRET, identity: "test_identity", ttl: 60) token.name = "myname" - token.set_video_grant(LiveKit::VideoGrant.new(roomJoin: true, room: "myroom", canPublish: false)) + token.video_grant = LiveKit::VideoGrant.new(roomJoin: true, room: "myroom", canPublish: false) jwt = token.to_jwt decoded = JWT.decode(jwt, TEST_SECRET, true, algorithm: "HS256") @@ -34,4 +34,54 @@ expect(video_grant["room"]).to eq("myroom") expect(video_grant["canPublish"]).to eq(false) end + + it "handles agent dispatch" do + token = described_class.new(api_key: TEST_KEY, api_secret: TEST_SECRET) + token.video_grant = LiveKit::VideoGrant.new(roomJoin: true, room: "myroom", canPublish: false) + token.room_config = LiveKit::Proto::RoomConfiguration.new( + max_participants: 10, + agents: [LiveKit::Proto::RoomAgentDispatch.new( + agent_name: "test-agent", + metadata: "test-metadata", + )] + ) + jwt = token.to_jwt + + grant = LiveKit::TokenVerifier.new(api_key: TEST_KEY, api_secret: TEST_SECRET).verify(jwt) + expect(grant.video.room).to eq("myroom") + expect(grant.room_config.agents[0].agent_name).to eq("test-agent") + expect(grant.room_config.agents[0].metadata).to eq("test-metadata") + end +end + +RSpec.describe LiveKit::ClaimGrant do + it "can be converted to a hash and back" do + claim_grant = described_class.new + claim_grant.identity = "test_identity" + claim_grant.name = "myname" + claim_grant.video = LiveKit::VideoGrant.new(roomJoin: true, room: "myroom", canPublish: false) + claim_grant.room_config = LiveKit::Proto::RoomConfiguration.new( + max_participants: 10, + agents: [LiveKit::Proto::RoomAgentDispatch.new( + agent_name: "test-agent", + metadata: "test-metadata", + )] + ) + hash = claim_grant.to_hash + expect(hash[:name]).to eq("myname") + agents = hash[:roomConfig]["agents"] + expect(agents.size).to eq(1) + expect(agents[0]["agentName"]).to eq("test-agent") + expect(agents[0]["metadata"]).to eq("test-metadata") + + serialized = hash.to_json + restored = JSON.parse(serialized) + + grant_parsed = LiveKit::ClaimGrant.from_hash(restored) + expect(grant_parsed.name).to eq("myname") + expect(grant_parsed.video.room).to eq("myroom") + expect(grant_parsed.room_config.max_participants).to eq(10) + expect(grant_parsed.room_config.agents[0].agent_name).to eq("test-agent") + expect(grant_parsed.room_config.agents[0].metadata).to eq("test-metadata") + end end diff --git a/spec/livekit/token_verifier_spec.rb b/spec/livekit/token_verifier_spec.rb index d6a1e0f..00a99fd 100644 --- a/spec/livekit/token_verifier_spec.rb +++ b/spec/livekit/token_verifier_spec.rb @@ -5,7 +5,7 @@ token = LiveKit::AccessToken.new(api_key: TEST_KEY, api_secret: TEST_SECRET, identity: "user") token.name = "name" - token.set_video_grant LiveKit::VideoGrant.new(roomJoin: true, room: "testroom") + token.video_grant = LiveKit::VideoGrant.new(roomJoin: true, room: "testroom") token.attributes = { "mykey" => "myvalue" } jwt = token.to_jwt v = described_class.new(api_key: TEST_KEY, api_secret: TEST_SECRET) @@ -20,7 +20,7 @@ it "fails on expired tokens" do token = LiveKit::AccessToken.new(api_key: TEST_KEY, api_secret: TEST_SECRET, identity: "test_identity", ttl: -10) - token.set_video_grant(LiveKit::VideoGrant.new(roomJoin: true)) + token.video_grant = LiveKit::VideoGrant.new(roomJoin: true) jwt = token.to_jwt v = described_class.new(api_key: TEST_KEY, api_secret: TEST_SECRET) @@ -30,7 +30,7 @@ it "fails on invalid secret" do token = LiveKit::AccessToken.new(api_key: TEST_KEY, api_secret: TEST_SECRET, identity: "test_identity") - token.set_video_grant(LiveKit::VideoGrant.new(roomJoin: true)) + token.video_grant = LiveKit::VideoGrant.new(roomJoin: true) jwt = token.to_jwt v = described_class.new(api_key: TEST_KEY, api_secret: "wrong-secret") @@ -40,7 +40,7 @@ it "fails on invalid api-key" do token = LiveKit::AccessToken.new(api_key: TEST_KEY, api_secret: TEST_SECRET, identity: "test_identity") - token.set_video_grant(LiveKit::VideoGrant.new(roomJoin: true)) + token.video_grant = LiveKit::VideoGrant.new(roomJoin: true) jwt = token.to_jwt v = described_class.new(api_key: "wrong key", api_secret: TEST_SECRET)