livekit-server-sdk 0.9.0 → 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 +4 -4
- data/.github/CODEOWNERS +1 -0
- data/.github/banner_dark.png +0 -0
- data/.github/workflows/generate-protobufs.yml +82 -0
- data/.github/workflows/test-api.yml +43 -0
- data/.github/workflows/test.yml +10 -7
- data/CHANGELOG.md +18 -0
- data/Gemfile.lock +60 -37
- data/README.md +7 -5
- data/Rakefile +6 -1
- data/lib/livekit/agent_dispatch_service_client.rb +11 -9
- data/lib/livekit/auth_mixin.rb +23 -8
- data/lib/livekit/connector_service_client.rb +87 -0
- data/lib/livekit/dial_timeout.rb +26 -0
- data/lib/livekit/egress_service_client.rb +18 -14
- data/lib/livekit/errors.rb +60 -0
- data/lib/livekit/failover.rb +215 -0
- data/lib/livekit/grants.rb +6 -2
- data/lib/livekit/ingress_service_client.rb +8 -6
- data/lib/livekit/livekit_api.rb +67 -0
- data/lib/livekit/proto/livekit_agent_dispatch_pb.rb +3 -2
- data/lib/livekit/proto/livekit_agent_pb.rb +3 -5
- data/lib/livekit/proto/livekit_connector_pb.rb +20 -0
- data/lib/livekit/proto/livekit_connector_twilio_pb.rb +22 -0
- data/lib/livekit/proto/livekit_connector_twilio_twirp.rb +8 -0
- data/lib/livekit/proto/livekit_connector_twirp.rb +21 -0
- data/lib/livekit/proto/livekit_connector_whatsapp_pb.rb +32 -0
- data/lib/livekit/proto/livekit_connector_whatsapp_twirp.rb +8 -0
- data/lib/livekit/proto/livekit_egress_pb.rb +33 -18
- data/lib/livekit/proto/livekit_egress_twirp.rb +5 -4
- data/lib/livekit/proto/livekit_ingress_pb.rb +2 -2
- data/lib/livekit/proto/livekit_metrics_pb.rb +3 -2
- data/lib/livekit/proto/livekit_models_pb.rb +7 -2
- data/lib/livekit/proto/livekit_room_pb.rb +2 -2
- data/lib/livekit/proto/livekit_rtc_pb.rb +86 -0
- data/lib/livekit/proto/livekit_rtc_twirp.rb +8 -0
- data/lib/livekit/proto/livekit_sip_pb.rb +7 -2
- data/lib/livekit/proto/livekit_webhook_pb.rb +1 -1
- data/lib/livekit/proto/logger/options_pb.rb +3 -2
- data/lib/livekit/room_service_client.rb +17 -15
- data/lib/livekit/sip_service_client.rb +147 -21
- data/lib/livekit/version.rb +1 -1
- data/lib/livekit.rb +3 -0
- data/livekit_server_sdk.gemspec +6 -4
- metadata +43 -4
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
require "livekit/proto/livekit_egress_twirp"
|
|
4
4
|
require "livekit/auth_mixin"
|
|
5
5
|
require 'livekit/utils'
|
|
6
|
+
require 'livekit/failover'
|
|
6
7
|
|
|
7
8
|
module LiveKit
|
|
8
9
|
class EgressServiceClient < Twirp::Client
|
|
@@ -10,10 +11,11 @@ module LiveKit
|
|
|
10
11
|
include AuthMixin
|
|
11
12
|
attr_accessor :api_key, :api_secret
|
|
12
13
|
|
|
13
|
-
def initialize(base_url, api_key: nil, api_secret: nil)
|
|
14
|
-
super(
|
|
14
|
+
def initialize(base_url, api_key: nil, api_secret: nil, token: nil, failover: true, connection: nil)
|
|
15
|
+
super(connection || LiveKit::Failover.connection(base_url, failover))
|
|
15
16
|
@api_key = api_key
|
|
16
17
|
@api_secret = api_secret
|
|
18
|
+
@token = token
|
|
17
19
|
end
|
|
18
20
|
|
|
19
21
|
def start_room_composite_egress(
|
|
@@ -49,7 +51,7 @@ module LiveKit
|
|
|
49
51
|
webhooks: webhooks,
|
|
50
52
|
)
|
|
51
53
|
self.set_output(request, output)
|
|
52
|
-
|
|
54
|
+
rpc!(
|
|
53
55
|
:StartRoomCompositeEgress,
|
|
54
56
|
request,
|
|
55
57
|
headers:auth_header(video_grant: VideoGrant.new(roomRecord: true)),
|
|
@@ -79,7 +81,7 @@ module LiveKit
|
|
|
79
81
|
webhooks: webhooks,
|
|
80
82
|
)
|
|
81
83
|
self.set_output(request, output)
|
|
82
|
-
|
|
84
|
+
rpc!(
|
|
83
85
|
:StartParticipantEgress,
|
|
84
86
|
request,
|
|
85
87
|
headers:auth_header(video_grant: VideoGrant.new(roomRecord: true)),
|
|
@@ -110,7 +112,7 @@ module LiveKit
|
|
|
110
112
|
webhooks: webhooks,
|
|
111
113
|
)
|
|
112
114
|
self.set_output(request, output)
|
|
113
|
-
|
|
115
|
+
rpc!(
|
|
114
116
|
:StartTrackCompositeEgress,
|
|
115
117
|
request,
|
|
116
118
|
headers:auth_header(video_grant: VideoGrant.new(roomRecord: true)),
|
|
@@ -135,7 +137,7 @@ module LiveKit
|
|
|
135
137
|
else
|
|
136
138
|
request.websocket_url = output
|
|
137
139
|
end
|
|
138
|
-
|
|
140
|
+
rpc!(
|
|
139
141
|
:StartTrackEgress,
|
|
140
142
|
request,
|
|
141
143
|
headers:auth_header(video_grant: VideoGrant.new(roomRecord: true)),
|
|
@@ -169,7 +171,7 @@ module LiveKit
|
|
|
169
171
|
webhooks: webhooks,
|
|
170
172
|
)
|
|
171
173
|
self.set_output(request, output)
|
|
172
|
-
|
|
174
|
+
rpc!(
|
|
173
175
|
:StartWebEgress,
|
|
174
176
|
request,
|
|
175
177
|
headers:auth_header(video_grant: VideoGrant.new(roomRecord: true)),
|
|
@@ -177,7 +179,7 @@ module LiveKit
|
|
|
177
179
|
end
|
|
178
180
|
|
|
179
181
|
def update_layout(egress_id, layout)
|
|
180
|
-
|
|
182
|
+
rpc!(
|
|
181
183
|
:UpdateLayout,
|
|
182
184
|
Proto::UpdateLayoutRequest.new(
|
|
183
185
|
egress_id: egress_id,
|
|
@@ -191,7 +193,7 @@ module LiveKit
|
|
|
191
193
|
add_output_urls: [],
|
|
192
194
|
remove_output_urls: []
|
|
193
195
|
)
|
|
194
|
-
|
|
196
|
+
rpc!(
|
|
195
197
|
:UpdateStream,
|
|
196
198
|
Proto::UpdateStreamRequest.new(
|
|
197
199
|
egress_id: egress_id,
|
|
@@ -208,7 +210,7 @@ module LiveKit
|
|
|
208
210
|
egress_id: nil,
|
|
209
211
|
active: false
|
|
210
212
|
)
|
|
211
|
-
|
|
213
|
+
rpc!(
|
|
212
214
|
:ListEgress,
|
|
213
215
|
Proto::ListEgressRequest.new(
|
|
214
216
|
room_name: room_name,
|
|
@@ -220,7 +222,7 @@ module LiveKit
|
|
|
220
222
|
end
|
|
221
223
|
|
|
222
224
|
def stop_egress(egress_id)
|
|
223
|
-
|
|
225
|
+
rpc!(
|
|
224
226
|
:StopEgress,
|
|
225
227
|
Proto::StopEgressRequest.new(egress_id: egress_id),
|
|
226
228
|
headers:auth_header(video_grant: VideoGrant.new(roomRecord: true)),
|
|
@@ -252,13 +254,15 @@ module LiveKit
|
|
|
252
254
|
end
|
|
253
255
|
end
|
|
254
256
|
elsif output.is_a? LiveKit::Proto::EncodedFileOutput
|
|
255
|
-
|
|
257
|
+
# The singular field is deprecated and absent on some requests (e.g.
|
|
258
|
+
# ParticipantEgressRequest); the plural *_outputs is the current field.
|
|
259
|
+
request.file = output if request.respond_to?(:file=)
|
|
256
260
|
request.file_outputs = Google::Protobuf::RepeatedField.new(:message, Proto::EncodedFileOutput, [output])
|
|
257
261
|
elsif output.is_a? LiveKit::Proto::SegmentedFileOutput
|
|
258
|
-
request.segments = output
|
|
262
|
+
request.segments = output if request.respond_to?(:segments=)
|
|
259
263
|
request.segment_outputs = Google::Protobuf::RepeatedField.new(:message, Proto::SegmentedFileOutput, [output])
|
|
260
264
|
elsif output.is_a? LiveKit::Proto::StreamOutput
|
|
261
|
-
request.stream = output
|
|
265
|
+
request.stream = output if request.respond_to?(:stream=)
|
|
262
266
|
request.stream_outputs = Google::Protobuf::RepeatedField.new(:message, Proto::StreamOutput, [output])
|
|
263
267
|
elsif output.is_a? LiveKit::Proto::ImageOutput
|
|
264
268
|
request.image_outputs = Google::Protobuf::RepeatedField.new(:message, Proto::ImageOutput, [output])
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module LiveKit
|
|
4
|
+
# Raised when a LiveKit server API call fails. Exposes the error code, message,
|
|
5
|
+
# and any metadata the server attached.
|
|
6
|
+
class ServerError < StandardError
|
|
7
|
+
# @return [String] the error code, e.g. "not_found" or "permission_denied"
|
|
8
|
+
attr_reader :code
|
|
9
|
+
# @return [Hash{String=>String}] error metadata returned by the server
|
|
10
|
+
attr_reader :metadata
|
|
11
|
+
|
|
12
|
+
def initialize(code, message, metadata: {})
|
|
13
|
+
@code = code
|
|
14
|
+
@metadata = metadata || {}
|
|
15
|
+
super(message)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# Builds a ServerError (or SipCallError) from the underlying error. Returns nil
|
|
19
|
+
# when +err+ is nil, so it can be called directly on a response's error.
|
|
20
|
+
# @return [LiveKit::ServerError, nil]
|
|
21
|
+
def self.from(err)
|
|
22
|
+
return nil if err.nil?
|
|
23
|
+
|
|
24
|
+
meta = err.meta || {}
|
|
25
|
+
klass = meta.key?("sip_status_code") ? SipCallError : self
|
|
26
|
+
klass.new(err.code.to_s, err.msg, metadata: meta)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Raised when a SIP dialing call (create_sip_participant / transfer_sip_participant)
|
|
31
|
+
# fails with a SIP response status. The SIP code and reason are exposed
|
|
32
|
+
# directly; any other metadata remains available via {#metadata}.
|
|
33
|
+
class SipCallError < ServerError
|
|
34
|
+
# @return [Integer, nil] the SIP response code, e.g. 486 (Busy Here)
|
|
35
|
+
def sip_status_code
|
|
36
|
+
raw = metadata["sip_status_code"]
|
|
37
|
+
raw && raw.to_i
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# @return [String, nil] the SIP reason phrase, e.g. "Busy Here"
|
|
41
|
+
def sip_status
|
|
42
|
+
metadata["sip_status"]
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# A clear, SIP-specific representation, including any extra metadata.
|
|
46
|
+
def message
|
|
47
|
+
code_str = metadata["sip_status_code"]
|
|
48
|
+
return super if code_str.nil?
|
|
49
|
+
|
|
50
|
+
reason = metadata["sip_status"]
|
|
51
|
+
result = "SIP call failed: #{code_str}"
|
|
52
|
+
result += " #{reason}" if reason && !reason.empty?
|
|
53
|
+
result += " (#{code})"
|
|
54
|
+
extra = metadata.reject { |k, _| %w[sip_status_code sip_status error_details].include?(k) }
|
|
55
|
+
result += " [#{extra.map { |k, v| "#{k}=#{v}" }.join(", ")}]" unless extra.empty?
|
|
56
|
+
result
|
|
57
|
+
end
|
|
58
|
+
alias to_s message
|
|
59
|
+
end
|
|
60
|
+
end
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'faraday'
|
|
4
|
+
require 'json'
|
|
5
|
+
require 'set'
|
|
6
|
+
require 'uri'
|
|
7
|
+
require 'livekit/utils'
|
|
8
|
+
require 'livekit/version'
|
|
9
|
+
|
|
10
|
+
module LiveKit
|
|
11
|
+
# Region failover for the Twirp API clients.
|
|
12
|
+
#
|
|
13
|
+
# On a retryable failure (any transport error or HTTP 5xx) the client
|
|
14
|
+
# discovers alternative LiveKit Cloud regions via /settings/regions and
|
|
15
|
+
# replays the request against the next region, with exponential backoff. 4xx
|
|
16
|
+
# responses are returned immediately.
|
|
17
|
+
#
|
|
18
|
+
# The +failover+ argument accepted by the service clients is a boolean
|
|
19
|
+
# (default true). When enabled, failover engages for LiveKit Cloud hosts only.
|
|
20
|
+
# The total attempt count and backoff are fixed (not user-configurable) so
|
|
21
|
+
# retries can't be tuned to values that could overwhelm the server.
|
|
22
|
+
module Failover
|
|
23
|
+
MAX_ATTEMPTS = 3
|
|
24
|
+
BACKOFF_BASE = 0.2
|
|
25
|
+
# Default per-request timeout (seconds). Calls that dial a phone override it
|
|
26
|
+
# via TIMEOUT_HEADER (see SIPServiceClient).
|
|
27
|
+
DEFAULT_TIMEOUT = 10
|
|
28
|
+
# Below this per-request timeout a retry is unlikely to help and many clients
|
|
29
|
+
# would retry in lockstep across regions, so a short request gets a single
|
|
30
|
+
# attempt (thundering-herd guard).
|
|
31
|
+
MIN_FAILOVER_TIMEOUT = 5
|
|
32
|
+
# Internal header carrying a per-request timeout override (seconds). Consumed
|
|
33
|
+
# by the middleware and not sent to the server.
|
|
34
|
+
TIMEOUT_HEADER = 'X-Lk-Request-Timeout'
|
|
35
|
+
|
|
36
|
+
# Total request attempts including the initial one; 1 means no failover.
|
|
37
|
+
# Failover only engages when enabled, the host is a LiveKit Cloud domain, and
|
|
38
|
+
# the request timeout is long enough to retry. +force+ bypasses the
|
|
39
|
+
# cloud-host check and is for internal testing only.
|
|
40
|
+
def self.attempts(enabled, host, force, timeout)
|
|
41
|
+
return 1 unless enabled && (force || cloud?(host))
|
|
42
|
+
return 1 if timeout && timeout < MIN_FAILOVER_TIMEOUT
|
|
43
|
+
|
|
44
|
+
MAX_ATTEMPTS
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Builds a Faraday connection wired with the region-failover middleware and
|
|
48
|
+
# the LiveKit Twirp base URL. Passed to Twirp::Client in place of a URL.
|
|
49
|
+
def self.connection(base_url, failover)
|
|
50
|
+
url = File.join(Utils.to_http_url(base_url), '/twirp')
|
|
51
|
+
Faraday.new(url: url) do |f|
|
|
52
|
+
f.headers['User-Agent'] = "livekit-server-sdk-ruby/#{VERSION}"
|
|
53
|
+
f.options.timeout = DEFAULT_TIMEOUT
|
|
54
|
+
f.use RegionFailoverMiddleware, failover: failover
|
|
55
|
+
f.adapter Faraday.default_adapter
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Failover only engages for LiveKit Cloud project domains.
|
|
60
|
+
def self.cloud?(host)
|
|
61
|
+
!host.nil? && host.end_with?('.livekit.cloud')
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# Normalizes a region URL to an http(s) scheme (ws -> http, wss -> https).
|
|
65
|
+
def self.to_http(url)
|
|
66
|
+
url.start_with?('ws') ? "http#{url[2..]}" : url
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def self.host_key(uri)
|
|
70
|
+
"#{uri.host}:#{uri.port}".downcase
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# Returns the first region whose host has not yet been attempted.
|
|
74
|
+
def self.pick_next(regions, attempted)
|
|
75
|
+
regions.find { |uri| !attempted.include?(host_key(uri)) }
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
@cache = {}
|
|
79
|
+
@cache_mutex = Mutex.new
|
|
80
|
+
|
|
81
|
+
# Returns alternative region origins (URIs) for the given origin, fetching
|
|
82
|
+
# /settings/regions if the cache is stale. Best-effort: on a fetch failure
|
|
83
|
+
# it serves a stale cached list when available, otherwise an empty list.
|
|
84
|
+
# Forwards headers so a valid token — and any test directives — reach the
|
|
85
|
+
# discovery endpoint.
|
|
86
|
+
def self.region_uris(origin, headers)
|
|
87
|
+
key = host_key(origin)
|
|
88
|
+
@cache_mutex.synchronize do
|
|
89
|
+
entry = @cache[key]
|
|
90
|
+
return entry[:uris] if entry && (Time.now - entry[:fetched_at]) < entry[:ttl]
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
begin
|
|
94
|
+
uris, ttl = fetch(origin, headers)
|
|
95
|
+
rescue StandardError
|
|
96
|
+
return @cache_mutex.synchronize { @cache[key]&.fetch(:uris, nil) } || []
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
# A zero TTL (e.g. Cache-Control: max-age=0) means "do not cache".
|
|
100
|
+
if ttl.positive?
|
|
101
|
+
@cache_mutex.synchronize do
|
|
102
|
+
@cache[key] = { uris: uris, fetched_at: Time.now, ttl: ttl }
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
uris
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def self.fetch(origin, headers)
|
|
109
|
+
forward = headers.reject { |k, _| %w[content-type content-length].include?(k.to_s.downcase) }
|
|
110
|
+
url = "#{origin.scheme}://#{origin.host}:#{origin.port}/settings/regions"
|
|
111
|
+
resp = Faraday.get(url) do |req|
|
|
112
|
+
# Short timeout so a slow/unreachable discovery endpoint doesn't stall
|
|
113
|
+
# the failover path.
|
|
114
|
+
req.options.timeout = 2
|
|
115
|
+
forward.each { |k, v| req.headers[k] = v }
|
|
116
|
+
end
|
|
117
|
+
raise "region discovery failed: #{resp.status}" unless resp.status == 200
|
|
118
|
+
|
|
119
|
+
ttl = parse_max_age(resp.headers['cache-control'])
|
|
120
|
+
body = JSON.parse(resp.body || '{}')
|
|
121
|
+
uris = (body['regions'] || [])
|
|
122
|
+
.map { |r| r['url'] }
|
|
123
|
+
.reject { |u| u.nil? || u.empty? }
|
|
124
|
+
.map { |u| URI.parse(to_http(u)) }
|
|
125
|
+
[uris, ttl]
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def self.parse_max_age(cache_control)
|
|
129
|
+
return 0 if cache_control.nil? || cache_control.empty?
|
|
130
|
+
|
|
131
|
+
cache_control.split(',').each do |directive|
|
|
132
|
+
directive = directive.strip.downcase
|
|
133
|
+
if directive.start_with?('max-age=')
|
|
134
|
+
secs = directive.sub('max-age=', '').to_i
|
|
135
|
+
return secs.positive? ? secs : 0
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
0
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
# Faraday middleware that fails over to alternative LiveKit Cloud regions on a
|
|
143
|
+
# retryable error: any transport error or HTTP 5xx. A 4xx is returned
|
|
144
|
+
# immediately. The request body and headers are replayed intact against the
|
|
145
|
+
# next untried region, with exponential backoff.
|
|
146
|
+
class RegionFailoverMiddleware < Faraday::Middleware
|
|
147
|
+
def initialize(app, options = {})
|
|
148
|
+
super(app)
|
|
149
|
+
@failover = options.fetch(:failover, true)
|
|
150
|
+
# +force+ / +backoff_base+ are internal test-only knobs.
|
|
151
|
+
@force = options.fetch(:force, false)
|
|
152
|
+
@backoff_base = options.fetch(:backoff_base, Failover::BACKOFF_BASE)
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
def call(env)
|
|
156
|
+
original_url = env.url.dup
|
|
157
|
+
request_body = env.body
|
|
158
|
+
|
|
159
|
+
# A per-request timeout override (e.g. for SIP dialing) travels as an
|
|
160
|
+
# internal header; consume it so it isn't sent to the server. Otherwise
|
|
161
|
+
# use the connection's configured timeout.
|
|
162
|
+
timeout = env.request_headers.delete(Failover::TIMEOUT_HEADER)&.to_f
|
|
163
|
+
timeout ||= env.request.timeout
|
|
164
|
+
env.request.timeout = timeout if timeout
|
|
165
|
+
|
|
166
|
+
request_headers = env.request_headers.dup
|
|
167
|
+
max_attempts = Failover.attempts(@failover, original_url.host, @force, timeout)
|
|
168
|
+
|
|
169
|
+
attempted = [Failover.host_key(original_url)]
|
|
170
|
+
regions = nil
|
|
171
|
+
current_url = original_url
|
|
172
|
+
attempt = 0
|
|
173
|
+
|
|
174
|
+
loop do
|
|
175
|
+
is_last = attempt + 1 >= max_attempts
|
|
176
|
+
env.url = current_url
|
|
177
|
+
env.body = request_body
|
|
178
|
+
|
|
179
|
+
response = nil
|
|
180
|
+
error = nil
|
|
181
|
+
begin
|
|
182
|
+
response = @app.call(env)
|
|
183
|
+
rescue Faraday::Error => e
|
|
184
|
+
error = e
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
# Success or a non-retryable 4xx is terminal.
|
|
188
|
+
return response if response && response.status < 500
|
|
189
|
+
|
|
190
|
+
nxt = nil
|
|
191
|
+
unless is_last
|
|
192
|
+
regions ||= Failover.region_uris(original_url, request_headers)
|
|
193
|
+
nxt = Failover.pick_next(regions, attempted)
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
if nxt.nil?
|
|
197
|
+
return response if response
|
|
198
|
+
raise error
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
reason = response ? "status #{response.status}" : (error&.message || 'error')
|
|
202
|
+
warn("livekit API request to #{current_url.host} failed (#{reason}), " \
|
|
203
|
+
"retrying with fallback url #{nxt}")
|
|
204
|
+
sleep(@backoff_base * (2**attempt))
|
|
205
|
+
attempted << Failover.host_key(nxt)
|
|
206
|
+
# Swap only the region's scheme/host/port, preserving the request path.
|
|
207
|
+
current_url = original_url.dup
|
|
208
|
+
current_url.scheme = nxt.scheme
|
|
209
|
+
current_url.host = nxt.host
|
|
210
|
+
current_url.port = nxt.port
|
|
211
|
+
attempt += 1
|
|
212
|
+
end
|
|
213
|
+
end
|
|
214
|
+
end
|
|
215
|
+
end
|
data/lib/livekit/grants.rb
CHANGED
|
@@ -62,8 +62,8 @@ module LiveKit
|
|
|
62
62
|
using LiveKit::Utils::StringifyKeysRefinement
|
|
63
63
|
|
|
64
64
|
attr_accessor :roomCreate, :roomJoin, :roomList, :roomRecord, :roomAdmin,
|
|
65
|
-
:room, :canPublish, :canPublishSources, :canSubscribe,
|
|
66
|
-
:canUpdateOwnMetadata, :hidden, :recorder, :ingressAdmin
|
|
65
|
+
:room, :destinationRoom, :canPublish, :canPublishSources, :canSubscribe,
|
|
66
|
+
:canPublishData, :canUpdateOwnMetadata, :hidden, :recorder, :ingressAdmin
|
|
67
67
|
|
|
68
68
|
def initialize(
|
|
69
69
|
# true if can create or delete rooms
|
|
@@ -78,6 +78,8 @@ module LiveKit
|
|
|
78
78
|
roomAdmin: nil,
|
|
79
79
|
# name of the room for join or admin permissions
|
|
80
80
|
room: nil,
|
|
81
|
+
# destination room a participant may be forwarded or moved to
|
|
82
|
+
destinationRoom: nil,
|
|
81
83
|
# for join tokens, can participant publish, true by default
|
|
82
84
|
canPublish: nil,
|
|
83
85
|
# TrackSource types that a participant may publish
|
|
@@ -101,6 +103,7 @@ module LiveKit
|
|
|
101
103
|
@roomRecord = roomRecord
|
|
102
104
|
@roomAdmin = roomAdmin
|
|
103
105
|
@room = room
|
|
106
|
+
@destinationRoom = destinationRoom
|
|
104
107
|
@canPublish = canPublish
|
|
105
108
|
@canPublishSources = canPublishSources
|
|
106
109
|
@canSubscribe = canSubscribe
|
|
@@ -123,6 +126,7 @@ module LiveKit
|
|
|
123
126
|
roomRecord: hash["roomRecord"],
|
|
124
127
|
roomAdmin: hash["roomAdmin"],
|
|
125
128
|
room: hash["room"],
|
|
129
|
+
destinationRoom: hash["destinationRoom"],
|
|
126
130
|
canPublish: hash["canPublish"],
|
|
127
131
|
canPublishSources: hash["canPublishSources"],
|
|
128
132
|
canSubscribe: hash["canSubscribe"],
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
require "livekit/proto/livekit_ingress_twirp"
|
|
2
2
|
require "livekit/auth_mixin"
|
|
3
3
|
require 'livekit/utils'
|
|
4
|
+
require 'livekit/failover'
|
|
4
5
|
|
|
5
6
|
module LiveKit
|
|
6
7
|
class IngressServiceClient < Twirp::Client
|
|
@@ -8,10 +9,11 @@ module LiveKit
|
|
|
8
9
|
include AuthMixin
|
|
9
10
|
attr_accessor :api_key, :api_secret
|
|
10
11
|
|
|
11
|
-
def initialize(base_url, api_key: nil, api_secret: nil)
|
|
12
|
-
super(
|
|
12
|
+
def initialize(base_url, api_key: nil, api_secret: nil, token: nil, failover: true, connection: nil)
|
|
13
|
+
super(connection || LiveKit::Failover.connection(base_url, failover))
|
|
13
14
|
@api_key = api_key
|
|
14
15
|
@api_secret = api_secret
|
|
16
|
+
@token = token
|
|
15
17
|
end
|
|
16
18
|
|
|
17
19
|
def create_ingress(
|
|
@@ -48,7 +50,7 @@ module LiveKit
|
|
|
48
50
|
enable_transcoding: enable_transcoding,
|
|
49
51
|
url: url,
|
|
50
52
|
)
|
|
51
|
-
|
|
53
|
+
rpc!(
|
|
52
54
|
:CreateIngress,
|
|
53
55
|
request,
|
|
54
56
|
headers:auth_header(video_grant: VideoGrant.new(ingressAdmin: true)),
|
|
@@ -86,7 +88,7 @@ module LiveKit
|
|
|
86
88
|
bypass_transcoding: bypass_transcoding,
|
|
87
89
|
enable_transcoding: enable_transcoding,
|
|
88
90
|
)
|
|
89
|
-
|
|
91
|
+
rpc!(
|
|
90
92
|
:UpdateIngress,
|
|
91
93
|
request,
|
|
92
94
|
headers:auth_header(video_grant: VideoGrant.new(ingressAdmin: true)),
|
|
@@ -103,7 +105,7 @@ module LiveKit
|
|
|
103
105
|
room_name: room_name,
|
|
104
106
|
ingress_id: ingress_id,
|
|
105
107
|
)
|
|
106
|
-
|
|
108
|
+
rpc!(
|
|
107
109
|
:ListIngress,
|
|
108
110
|
request,
|
|
109
111
|
headers:auth_header(video_grant: VideoGrant.new(ingressAdmin: true)),
|
|
@@ -114,7 +116,7 @@ module LiveKit
|
|
|
114
116
|
request = Proto::DeleteIngressRequest.new(
|
|
115
117
|
ingress_id: ingress_id
|
|
116
118
|
)
|
|
117
|
-
|
|
119
|
+
rpc!(
|
|
118
120
|
:DeleteIngress,
|
|
119
121
|
request,
|
|
120
122
|
headers:auth_header(video_grant: VideoGrant.new(ingressAdmin: true)),
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "livekit/room_service_client"
|
|
4
|
+
require "livekit/egress_service_client"
|
|
5
|
+
require "livekit/ingress_service_client"
|
|
6
|
+
require "livekit/sip_service_client"
|
|
7
|
+
require "livekit/agent_dispatch_service_client"
|
|
8
|
+
require "livekit/connector_service_client"
|
|
9
|
+
require "livekit/failover"
|
|
10
|
+
|
|
11
|
+
module LiveKit
|
|
12
|
+
# A single entry point to every LiveKit server API, exposing each service
|
|
13
|
+
# through a reader.
|
|
14
|
+
#
|
|
15
|
+
# @example
|
|
16
|
+
# api = LiveKit::LiveKitAPI.new("https://my.livekit.host", api_key: k, api_secret: s)
|
|
17
|
+
# api.room.create_room("my-room")
|
|
18
|
+
class LiveKitAPI
|
|
19
|
+
# @return [RoomServiceClient]
|
|
20
|
+
attr_reader :room
|
|
21
|
+
# @return [EgressServiceClient]
|
|
22
|
+
attr_reader :egress
|
|
23
|
+
# @return [IngressServiceClient]
|
|
24
|
+
attr_reader :ingress
|
|
25
|
+
# @return [SIPServiceClient]
|
|
26
|
+
attr_reader :sip
|
|
27
|
+
# @return [AgentDispatchServiceClient]
|
|
28
|
+
attr_reader :agent_dispatch
|
|
29
|
+
# @return [ConnectorServiceClient]
|
|
30
|
+
attr_reader :connector
|
|
31
|
+
|
|
32
|
+
# Authenticate with either an API key and secret (recommended for backend
|
|
33
|
+
# use), or a pre-signed +token+ (for client-side use, where the API secret
|
|
34
|
+
# must not be exposed). Any omitted value falls back to its environment
|
|
35
|
+
# variable: +LIVEKIT_URL+, +LIVEKIT_TOKEN+, +LIVEKIT_API_KEY+, +LIVEKIT_API_SECRET+.
|
|
36
|
+
def initialize(url = nil, api_key: nil, api_secret: nil, token: nil, failover: true)
|
|
37
|
+
url ||= ENV["LIVEKIT_URL"]
|
|
38
|
+
|
|
39
|
+
# Only fall back to environment credentials when none were provided
|
|
40
|
+
# explicitly, so an ambient LIVEKIT_TOKEN can't silently override an
|
|
41
|
+
# explicit api_key/secret (or vice versa).
|
|
42
|
+
if token.nil? && api_key.nil? && api_secret.nil?
|
|
43
|
+
token = ENV["LIVEKIT_TOKEN"]
|
|
44
|
+
end
|
|
45
|
+
if token.nil? && api_key.nil? && api_secret.nil?
|
|
46
|
+
api_key = ENV["LIVEKIT_API_KEY"]
|
|
47
|
+
api_secret = ENV["LIVEKIT_API_SECRET"]
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
raise ArgumentError, "url is required (pass it or set LIVEKIT_URL)" if url.nil? || url.empty?
|
|
51
|
+
if token.nil? && (api_key.nil? || api_secret.nil?)
|
|
52
|
+
raise ArgumentError, "either a token, or api_key and api_secret, are required"
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# Share one Faraday connection (and its adapter/middleware) across every
|
|
56
|
+
# service instead of letting each open its own.
|
|
57
|
+
connection = LiveKit::Failover.connection(url, failover)
|
|
58
|
+
opts = { api_key: api_key, api_secret: api_secret, token: token, failover: failover, connection: connection }
|
|
59
|
+
@room = RoomServiceClient.new(url, **opts)
|
|
60
|
+
@egress = EgressServiceClient.new(url, **opts)
|
|
61
|
+
@ingress = IngressServiceClient.new(url, **opts)
|
|
62
|
+
@sip = SIPServiceClient.new(url, **opts)
|
|
63
|
+
@agent_dispatch = AgentDispatchServiceClient.new(url, **opts)
|
|
64
|
+
@connector = ConnectorServiceClient.new(url, **opts)
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
@@ -8,9 +8,9 @@ require 'livekit_agent_pb'
|
|
|
8
8
|
require 'logger/options_pb'
|
|
9
9
|
|
|
10
10
|
|
|
11
|
-
descriptor_data = "\n\x1clivekit_agent_dispatch.proto\x12\x07livekit\x1a\x13livekit_agent.proto\x1a\x14logger/options.proto\"
|
|
11
|
+
descriptor_data = "\n\x1clivekit_agent_dispatch.proto\x12\x07livekit\x1a\x13livekit_agent.proto\x1a\x14logger/options.proto\"\x9d\x02\n\x1a\x43reateAgentDispatchRequest\x12\x12\n\nagent_name\x18\x01 \x01(\t\x12\x0c\n\x04room\x18\x02 \x01(\t\x12\x15\n\x08metadata\x18\x03 \x01(\tB\x03\xc0P\x01\x12\x31\n\x0erestart_policy\x18\x04 \x01(\x0e\x32\x19.livekit.JobRestartPolicy\x12\x12\n\ndeployment\x18\x05 \x01(\t\x12L\n\nattributes\x18\x06 \x03(\x0b\x32\x33.livekit.CreateAgentDispatchRequest.AttributesEntryB\x03\xc0P\x01\x1a\x31\n\x0f\x41ttributesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\xfd\x01\n\x11RoomAgentDispatch\x12\x12\n\nagent_name\x18\x01 \x01(\t\x12\x15\n\x08metadata\x18\x02 \x01(\tB\x03\xc0P\x01\x12\x31\n\x0erestart_policy\x18\x03 \x01(\x0e\x32\x19.livekit.JobRestartPolicy\x12\x12\n\ndeployment\x18\x04 \x01(\t\x12\x43\n\nattributes\x18\x05 \x03(\x0b\x32*.livekit.RoomAgentDispatch.AttributesEntryB\x03\xc0P\x01\x1a\x31\n\x0f\x41ttributesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"N\n\x1a\x44\x65leteAgentDispatchRequest\x12\"\n\x0b\x64ispatch_id\x18\x01 \x01(\tB\r\xbaP\ndispatchID\x12\x0c\n\x04room\x18\x02 \x01(\t\"L\n\x18ListAgentDispatchRequest\x12\"\n\x0b\x64ispatch_id\x18\x01 \x01(\tB\r\xbaP\ndispatchID\x12\x0c\n\x04room\x18\x02 \x01(\t\"M\n\x19ListAgentDispatchResponse\x12\x30\n\x10\x61gent_dispatches\x18\x01 \x03(\x0b\x32\x16.livekit.AgentDispatch\"\xbb\x02\n\rAgentDispatch\x12\n\n\x02id\x18\x01 \x01(\t\x12\x12\n\nagent_name\x18\x02 \x01(\t\x12\x0c\n\x04room\x18\x03 \x01(\t\x12\x15\n\x08metadata\x18\x04 \x01(\tB\x03\xc0P\x01\x12*\n\x05state\x18\x05 \x01(\x0b\x32\x1b.livekit.AgentDispatchState\x12\x31\n\x0erestart_policy\x18\x06 \x01(\x0e\x32\x19.livekit.JobRestartPolicy\x12\x12\n\ndeployment\x18\x07 \x01(\t\x12?\n\nattributes\x18\x08 \x03(\x0b\x32&.livekit.AgentDispatch.AttributesEntryB\x03\xc0P\x01\x1a\x31\n\x0f\x41ttributesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"X\n\x12\x41gentDispatchState\x12\x1a\n\x04jobs\x18\x01 \x03(\x0b\x32\x0c.livekit.Job\x12\x12\n\ncreated_at\x18\x02 \x01(\x03\x12\x12\n\ndeleted_at\x18\x03 \x01(\x03*5\n\x10JobRestartPolicy\x12\x12\n\x0eJRP_ON_FAILURE\x10\x00\x12\r\n\tJRP_NEVER\x10\x01\x32\x8b\x02\n\x14\x41gentDispatchService\x12M\n\x0e\x43reateDispatch\x12#.livekit.CreateAgentDispatchRequest\x1a\x16.livekit.AgentDispatch\x12M\n\x0e\x44\x65leteDispatch\x12#.livekit.DeleteAgentDispatchRequest\x1a\x16.livekit.AgentDispatch\x12U\n\x0cListDispatch\x12!.livekit.ListAgentDispatchRequest\x1a\".livekit.ListAgentDispatchResponseBFZ#github.com/livekit/protocol/livekit\xaa\x02\rLiveKit.Proto\xea\x02\x0eLiveKit::Protob\x06proto3"
|
|
12
12
|
|
|
13
|
-
pool =
|
|
13
|
+
pool = Google::Protobuf::DescriptorPool.generated_pool
|
|
14
14
|
pool.add_serialized_file(descriptor_data)
|
|
15
15
|
|
|
16
16
|
module LiveKit
|
|
@@ -22,5 +22,6 @@ module LiveKit
|
|
|
22
22
|
ListAgentDispatchResponse = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.ListAgentDispatchResponse").msgclass
|
|
23
23
|
AgentDispatch = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.AgentDispatch").msgclass
|
|
24
24
|
AgentDispatchState = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.AgentDispatchState").msgclass
|
|
25
|
+
JobRestartPolicy = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.JobRestartPolicy").enummodule
|
|
25
26
|
end
|
|
26
27
|
end
|
|
@@ -5,11 +5,12 @@
|
|
|
5
5
|
require 'google/protobuf'
|
|
6
6
|
|
|
7
7
|
require 'livekit_models_pb'
|
|
8
|
+
require 'logger/options_pb'
|
|
8
9
|
|
|
9
10
|
|
|
10
|
-
descriptor_data = "\n\x13livekit_agent.proto\x12\x07livekit\x1a\x14livekit_models.proto\"\
|
|
11
|
+
descriptor_data = "\n\x13livekit_agent.proto\x12\x07livekit\x1a\x14livekit_models.proto\x1a\x14logger/options.proto\"\xb2\x03\n\x03Job\x12\n\n\x02id\x18\x01 \x01(\t\x12\"\n\x0b\x64ispatch_id\x18\t \x01(\tB\r\xbaP\ndispatchID\x12\x1e\n\x04type\x18\x02 \x01(\x0e\x32\x10.livekit.JobType\x12\x1b\n\x04room\x18\x03 \x01(\x0b\x32\r.livekit.Room\x12\x32\n\x0bparticipant\x18\x04 \x01(\x0b\x32\x18.livekit.ParticipantInfoH\x00\x88\x01\x01\x12\x15\n\tnamespace\x18\x05 \x01(\tB\x02\x18\x01\x12\x15\n\x08metadata\x18\x06 \x01(\tB\x03\xc0P\x01\x12\x12\n\nagent_name\x18\x07 \x01(\t\x12 \n\x05state\x18\x08 \x01(\x0b\x32\x11.livekit.JobState\x12\x18\n\x10\x65nable_recording\x18\n \x01(\x08\x12\x12\n\ndeployment\x18\x0b \x01(\t\x12\x35\n\nattributes\x18\x0c \x03(\x0b\x32\x1c.livekit.Job.AttributesEntryB\x03\xc0P\x01\x1a\x31\n\x0f\x41ttributesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\x0e\n\x0c_participant\"\xd3\x01\n\x08JobState\x12\"\n\x06status\x18\x01 \x01(\x0e\x32\x12.livekit.JobStatus\x12\r\n\x05\x65rror\x18\x02 \x01(\t\x12\x12\n\nstarted_at\x18\x03 \x01(\x03\x12\x10\n\x08\x65nded_at\x18\x04 \x01(\x03\x12\x12\n\nupdated_at\x18\x05 \x01(\x03\x12\x1c\n\x14participant_identity\x18\x06 \x01(\t\x12\x1e\n\tworker_id\x18\x07 \x01(\tB\x0b\xbaP\x08workerID\x12\x1c\n\x08\x61gent_id\x18\x08 \x01(\tB\n\xbaP\x07\x61gentID\"\xf8\x02\n\rWorkerMessage\x12\x32\n\x08register\x18\x01 \x01(\x0b\x32\x1e.livekit.RegisterWorkerRequestH\x00\x12\x35\n\x0c\x61vailability\x18\x02 \x01(\x0b\x32\x1d.livekit.AvailabilityResponseH\x00\x12\x34\n\rupdate_worker\x18\x03 \x01(\x0b\x32\x1b.livekit.UpdateWorkerStatusH\x00\x12.\n\nupdate_job\x18\x04 \x01(\x0b\x32\x18.livekit.UpdateJobStatusH\x00\x12#\n\x04ping\x18\x05 \x01(\x0b\x32\x13.livekit.WorkerPingH\x00\x12\x33\n\x0csimulate_job\x18\x06 \x01(\x0b\x32\x1b.livekit.SimulateJobRequestH\x00\x12\x31\n\x0bmigrate_job\x18\x07 \x01(\x0b\x32\x1a.livekit.MigrateJobRequestH\x00\x42\t\n\x07message\"\x88\x02\n\rServerMessage\x12\x33\n\x08register\x18\x01 \x01(\x0b\x32\x1f.livekit.RegisterWorkerResponseH\x00\x12\x34\n\x0c\x61vailability\x18\x02 \x01(\x0b\x32\x1c.livekit.AvailabilityRequestH\x00\x12,\n\nassignment\x18\x03 \x01(\x0b\x32\x16.livekit.JobAssignmentH\x00\x12.\n\x0btermination\x18\x05 \x01(\x0b\x32\x17.livekit.JobTerminationH\x00\x12#\n\x04pong\x18\x04 \x01(\x0b\x32\x13.livekit.WorkerPongH\x00\x42\t\n\x07message\"\x80\x01\n\x12SimulateJobRequest\x12\x1e\n\x04type\x18\x01 \x01(\x0e\x32\x10.livekit.JobType\x12\x1b\n\x04room\x18\x02 \x01(\x0b\x32\r.livekit.Room\x12-\n\x0bparticipant\x18\x03 \x01(\x0b\x32\x18.livekit.ParticipantInfo\"\x1f\n\nWorkerPing\x12\x11\n\ttimestamp\x18\x01 \x01(\x03\"7\n\nWorkerPong\x12\x16\n\x0elast_timestamp\x18\x01 \x01(\x03\x12\x11\n\ttimestamp\x18\x02 \x01(\x03\"\xea\x01\n\x15RegisterWorkerRequest\x12\x1e\n\x04type\x18\x01 \x01(\x0e\x32\x10.livekit.JobType\x12\x12\n\nagent_name\x18\x08 \x01(\t\x12\x0f\n\x07version\x18\x03 \x01(\t\x12\x15\n\rping_interval\x18\x05 \x01(\r\x12\x16\n\tnamespace\x18\x06 \x01(\tH\x00\x88\x01\x01\x12;\n\x13\x61llowed_permissions\x18\x07 \x01(\x0b\x32\x1e.livekit.ParticipantPermission\x12\x12\n\ndeployment\x18\t \x01(\tB\x0c\n\n_namespace\"b\n\x16RegisterWorkerResponse\x12\x1e\n\tworker_id\x18\x01 \x01(\tB\x0b\xbaP\x08workerID\x12(\n\x0bserver_info\x18\x03 \x01(\x0b\x32\x13.livekit.ServerInfo\"$\n\x11MigrateJobRequest\x12\x0f\n\x07job_ids\x18\x02 \x03(\t\"B\n\x13\x41vailabilityRequest\x12\x19\n\x03job\x18\x01 \x01(\x0b\x32\x0c.livekit.Job\x12\x10\n\x08resuming\x18\x02 \x01(\x08\"\xdd\x02\n\x14\x41vailabilityResponse\x12\x18\n\x06job_id\x18\x01 \x01(\tB\x08\xbaP\x05jobID\x12\x11\n\tavailable\x18\x02 \x01(\x08\x12\x17\n\x0fsupports_resume\x18\x03 \x01(\x08\x12\x11\n\tterminate\x18\x08 \x01(\x08\x12\x18\n\x10participant_name\x18\x04 \x01(\t\x12\x1c\n\x14participant_identity\x18\x05 \x01(\t\x12\x1c\n\x14participant_metadata\x18\x06 \x01(\t\x12X\n\x16participant_attributes\x18\x07 \x03(\x0b\x32\x38.livekit.AvailabilityResponse.ParticipantAttributesEntry\x1a<\n\x1aParticipantAttributesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"^\n\x0fUpdateJobStatus\x12\x18\n\x06job_id\x18\x01 \x01(\tB\x08\xbaP\x05jobID\x12\"\n\x06status\x18\x02 \x01(\x0e\x32\x12.livekit.JobStatus\x12\r\n\x05\x65rror\x18\x03 \x01(\t\"l\n\x12UpdateWorkerStatus\x12*\n\x06status\x18\x01 \x01(\x0e\x32\x15.livekit.WorkerStatusH\x00\x88\x01\x01\x12\x0c\n\x04load\x18\x03 \x01(\x02\x12\x11\n\tjob_count\x18\x04 \x01(\rB\t\n\x07_status\"S\n\rJobAssignment\x12\x19\n\x03job\x18\x01 \x01(\x0b\x32\x0c.livekit.Job\x12\x10\n\x03url\x18\x02 \x01(\tH\x00\x88\x01\x01\x12\r\n\x05token\x18\x03 \x01(\tB\x06\n\x04_url\"*\n\x0eJobTermination\x12\x18\n\x06job_id\x18\x01 \x01(\tB\x08\xbaP\x05jobID*<\n\x07JobType\x12\x0b\n\x07JT_ROOM\x10\x00\x12\x10\n\x0cJT_PUBLISHER\x10\x01\x12\x12\n\x0eJT_PARTICIPANT\x10\x02*-\n\x0cWorkerStatus\x12\x10\n\x0cWS_AVAILABLE\x10\x00\x12\x0b\n\x07WS_FULL\x10\x01*J\n\tJobStatus\x12\x0e\n\nJS_PENDING\x10\x00\x12\x0e\n\nJS_RUNNING\x10\x01\x12\x0e\n\nJS_SUCCESS\x10\x02\x12\r\n\tJS_FAILED\x10\x03\x42\x46Z#github.com/livekit/protocol/livekit\xaa\x02\rLiveKit.Proto\xea\x02\x0eLiveKit::Protob\x06proto3"
|
|
11
12
|
|
|
12
|
-
pool =
|
|
13
|
+
pool = Google::Protobuf::DescriptorPool.generated_pool
|
|
13
14
|
pool.add_serialized_file(descriptor_data)
|
|
14
15
|
|
|
15
16
|
module LiveKit
|
|
@@ -30,9 +31,6 @@ module LiveKit
|
|
|
30
31
|
UpdateWorkerStatus = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.UpdateWorkerStatus").msgclass
|
|
31
32
|
JobAssignment = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.JobAssignment").msgclass
|
|
32
33
|
JobTermination = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.JobTermination").msgclass
|
|
33
|
-
TextMessageRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.TextMessageRequest").msgclass
|
|
34
|
-
PushTextRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.PushTextRequest").msgclass
|
|
35
|
-
TextMessageResponse = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.TextMessageResponse").msgclass
|
|
36
34
|
JobType = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.JobType").enummodule
|
|
37
35
|
WorkerStatus = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.WorkerStatus").enummodule
|
|
38
36
|
JobStatus = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.JobStatus").enummodule
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
|
3
|
+
# source: livekit_connector.proto
|
|
4
|
+
|
|
5
|
+
require 'google/protobuf'
|
|
6
|
+
|
|
7
|
+
require 'livekit_connector_whatsapp_pb'
|
|
8
|
+
require 'livekit_connector_twilio_pb'
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
descriptor_data = "\n\x17livekit_connector.proto\x12\x07livekit\x1a livekit_connector_whatsapp.proto\x1a\x1elivekit_connector_twilio.proto*:\n\rConnectorType\x12\x0f\n\x0bUnspecified\x10\x00\x12\x0c\n\x08WhatsApp\x10\x01\x12\n\n\x06Twilio\x10\x02\x32\xec\x03\n\tConnector\x12W\n\x10\x44ialWhatsAppCall\x12 .livekit.DialWhatsAppCallRequest\x1a!.livekit.DialWhatsAppCallResponse\x12i\n\x16\x44isconnectWhatsAppCall\x12&.livekit.DisconnectWhatsAppCallRequest\x1a\'.livekit.DisconnectWhatsAppCallResponse\x12`\n\x13\x43onnectWhatsAppCall\x12#.livekit.ConnectWhatsAppCallRequest\x1a$.livekit.ConnectWhatsAppCallResponse\x12]\n\x12\x41\x63\x63\x65ptWhatsAppCall\x12\".livekit.AcceptWhatsAppCallRequest\x1a#.livekit.AcceptWhatsAppCallResponse\x12Z\n\x11\x43onnectTwilioCall\x12!.livekit.ConnectTwilioCallRequest\x1a\".livekit.ConnectTwilioCallResponseBFZ#github.com/livekit/protocol/livekit\xaa\x02\rLiveKit.Proto\xea\x02\x0eLiveKit::Protob\x06proto3"
|
|
12
|
+
|
|
13
|
+
pool = Google::Protobuf::DescriptorPool.generated_pool
|
|
14
|
+
pool.add_serialized_file(descriptor_data)
|
|
15
|
+
|
|
16
|
+
module LiveKit
|
|
17
|
+
module Proto
|
|
18
|
+
ConnectorType = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("livekit.ConnectorType").enummodule
|
|
19
|
+
end
|
|
20
|
+
end
|