lovekit 4.0.0__tar.gz → 4.2.0__tar.gz

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.
@@ -1,11 +1,11 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: lovekit
3
- Version: 4.0.0
3
+ Version: 4.2.0
4
4
  Author-email: jhnnsrs <jhnnsrs@gmail.com>
5
5
  Requires-Python: >=3.11
6
6
  Requires-Dist: aiohttp<4,>=3.9.5
7
- Requires-Dist: arkitekt-spec>=3.4
8
- Requires-Dist: fakts>=5.4
7
+ Requires-Dist: arkitekt-spec>=3.19.1
8
+ Requires-Dist: fakts>=6.1
9
9
  Requires-Dist: livekit>=1.0
10
10
  Requires-Dist: numpy>=1.26
11
11
  Requires-Dist: rath>=4.1.1
@@ -66,6 +66,13 @@
66
66
  "external_modules": [],
67
67
  "additional_bases": {},
68
68
  "additional_config": {},
69
+ "directive_class_vars": [
70
+ {
71
+ "directive": "identified",
72
+ "argument": "by",
73
+ "attribute": "__identifier__"
74
+ }
75
+ ],
69
76
  "force_plugin_order": true,
70
77
  "omitted_document_rules": [],
71
78
  "parsers": [],
@@ -1,3 +1,7 @@
1
+ directive @auth(required_scopes: [String!], required_roles: [String!], required_org_roles: [String!], any_scope_of: [String!], any_role_of: [String!], any_org_role_of: [String!], allow_scoped: Boolean) on FIELD_DEFINITION
2
+
3
+ directive @identified(by: String!) on OBJECT
4
+
1
5
  directive @oneOf on INPUT_OBJECT
2
6
 
3
7
  schema @link(url: "https://specs.apollo.dev/federation/v2.11", import: ["@key"]) {
@@ -15,7 +19,7 @@ input AddToCallInput {
15
19
  """
16
20
  An app instance that owns live streams: one per client, user and organization
17
21
  """
18
- type Agent {
22
+ type Agent @identified(by: "@lovekit/agent") {
19
23
  id: ID!
20
24
  client: Client!
21
25
  user: User!
@@ -144,6 +148,55 @@ type Client @key(fields: "id", resolvable: true) {
144
148
  clientId: String!
145
149
  }
146
150
 
151
+ """
152
+ What a guest granted it sees of the organization: the objects put in it, and what is part of them.
153
+ """
154
+ type Collaboration {
155
+ id: ID!
156
+ name: String!
157
+ description: String
158
+ createdAt: DateTime!
159
+
160
+ """What is in the collaboration; what is part of these is in it too"""
161
+ items: [CollaborationItem!]!
162
+ }
163
+
164
+ """
165
+ One object in a collaboration: put there, or brought along with one that needs it to be seen.
166
+ """
167
+ type CollaborationItem {
168
+ id: ID!
169
+
170
+ """The object's id, in its structure"""
171
+ objectId: String!
172
+ addedAt: DateTime!
173
+
174
+ """The structure the object is known by across the hub: @mikro/scene"""
175
+ identifier: String
176
+
177
+ """
178
+ Whether it is in the collaboration only as what another object in it needs to be seen
179
+ """
180
+ brought: Boolean!
181
+ }
182
+
183
+ """An object to put in, or take out of, a collaboration"""
184
+ input CollaborationObjectInput {
185
+ collaboration: ID!
186
+
187
+ """The structure the object is known by: @mikro/scene"""
188
+ identifier: String!
189
+
190
+ """The object's id"""
191
+ object: ID!
192
+ }
193
+
194
+ """A new collaboration"""
195
+ input CreateCollaborationInput {
196
+ name: String!
197
+ description: String = null
198
+ }
199
+
147
200
  """Date with time (isoformat)"""
148
201
  scalar DateTime
149
202
 
@@ -182,6 +235,24 @@ input JoinCallInput {
182
235
  }
183
236
 
184
237
  type Mutation {
238
+ """
239
+ Create an empty collaboration, to put agents and streams in and grant a guest
240
+ """
241
+ createCollaboration(input: CreateCollaborationInput!): Collaboration! @auth(any_role_of: ["admin", "editor"])
242
+
243
+ """
244
+ Put an agent or a stream in a collaboration: an agent brings every stream it offers
245
+ """
246
+ addToCollaboration(input: CollaborationObjectInput!): Collaboration! @auth(any_role_of: ["admin", "editor"])
247
+
248
+ """Take an agent or a stream out of a collaboration"""
249
+ removeFromCollaboration(input: CollaborationObjectInput!): Collaboration! @auth(any_role_of: ["admin", "editor"])
250
+
251
+ """
252
+ Delete a collaboration: whoever was granted it sees nothing of it any more
253
+ """
254
+ deleteCollaboration(id: ID!): ID! @auth(any_role_of: ["admin", "editor"])
255
+
185
256
  """
186
257
  Offer exactly these streams as the caller's agent: undeclared ones are removed, unchanged ones untouched
187
258
  """
@@ -193,12 +264,14 @@ type Mutation {
193
264
  publishToken: String!
194
265
 
195
266
  """
196
- A token to watch a stream: its agent's room, where it is the track named by its key
267
+ A token to watch a stream: its agent's room, where it is the track named by its key. A guest needs the agent in one of their collaborations
197
268
  """
198
- watchStream(input: WatchStreamInput!): String!
269
+ watchStream(input: WatchStreamInput!): String! @auth(allow_scoped: true)
199
270
 
200
- """A token to watch every stream of an agent"""
201
- watchAgent(input: WatchAgentInput!): String!
271
+ """
272
+ A token to watch every stream of an agent. A guest needs the agent in one of their collaborations
273
+ """
274
+ watchAgent(input: WatchAgentInput!): String! @auth(allow_scoped: true)
202
275
 
203
276
  """The live call about these structures, or a new one"""
204
277
  ensureCall(input: EnsureCallInput!): Call!
@@ -252,6 +325,14 @@ type Query {
252
325
  """The organization's calls; filter `live` for the ones in progress"""
253
326
  calls(filters: CallFilter, order: CallOrder, pagination: OffsetPaginationInput): [Call!]!
254
327
 
328
+ """
329
+ List the organization's collaborations: what a guest granted one sees of it (a guest: the collaborations granted to them)
330
+ """
331
+ collaborations: [Collaboration!]!
332
+
333
+ """Get a single collaboration by ID"""
334
+ collaboration(id: ID!): Collaboration!
335
+
255
336
  """Get a stream by ID"""
256
337
  stream(id: ID!): Stream!
257
338
 
@@ -272,7 +353,7 @@ type Release @key(fields: "id", resolvable: true) {
272
353
  }
273
354
 
274
355
  """One live source an agent offers: a camera, a detector, a microphone"""
275
- type Stream {
356
+ type Stream @identified(by: "@lovekit/stream") {
276
357
  id: ID!
277
358
 
278
359
  """
@@ -2,7 +2,7 @@ import builtins
2
2
  from enum import Enum
3
3
  from pydantic import AliasChoices, BaseModel, ConfigDict, Field
4
4
  from rath.scalars import ID, IDCoercible
5
- from typing import Annotated, Iterable, Literal
5
+ from typing import Annotated, ClassVar, Iterable, Literal
6
6
 
7
7
 
8
8
  class GraphQLDefault:
@@ -138,6 +138,7 @@ class WatchStreamInput(BaseModel):
138
138
  class StreamAgent(BaseModel):
139
139
  """An app instance that owns live streams: one per client, user and organization"""
140
140
 
141
+ __identifier__: ClassVar[Literal["@lovekit/agent"]] = "@lovekit/agent"
141
142
  typename: Literal["Agent"] = Field(
142
143
  alias="__typename", default="Agent", exclude=True
143
144
  )
@@ -150,6 +151,7 @@ class StreamAgent(BaseModel):
150
151
  class Stream(BaseModel):
151
152
  """One live source an agent offers: a camera, a detector, a microphone"""
152
153
 
154
+ __identifier__: ClassVar[Literal["@lovekit/stream"]] = "@lovekit/stream"
153
155
  typename: Literal["Stream"] = Field(
154
156
  alias="__typename", default="Stream", exclude=True
155
157
  )
@@ -191,6 +193,7 @@ class AgentUser(BaseModel):
191
193
  class Agent(BaseModel):
192
194
  """An app instance that owns live streams: one per client, user and organization"""
193
195
 
196
+ __identifier__: ClassVar[Literal["@lovekit/agent"]] = "@lovekit/agent"
194
197
  typename: Literal["Agent"] = Field(
195
198
  alias="__typename", default="Agent", exclude=True
196
199
  )
@@ -251,7 +254,7 @@ class WatchStreamMutation(BaseModel):
251
254
  """No documentation found for this operation."""
252
255
 
253
256
  watch_stream: str = Field(alias="watchStream")
254
- "A token to watch a stream: its agent's room, where it is the track named by its key"
257
+ "A token to watch a stream: its agent's room, where it is the track named by its key. A guest needs the agent in one of their collaborations"
255
258
 
256
259
  class Arguments(BaseModel):
257
260
  """Arguments for WatchStream"""
@@ -268,7 +271,7 @@ class WatchAgentMutation(BaseModel):
268
271
  """No documentation found for this operation."""
269
272
 
270
273
  watch_agent: str = Field(alias="watchAgent")
271
- "A token to watch every stream of an agent"
274
+ "A token to watch every stream of an agent. A guest needs the agent in one of their collaborations"
272
275
 
273
276
  class Arguments(BaseModel):
274
277
  """Arguments for WatchAgent"""
@@ -301,6 +304,7 @@ class GetAgentQuery(BaseModel):
301
304
  class SearchAgentsQueryOptions(BaseModel):
302
305
  """An app instance that owns live streams: one per client, user and organization"""
303
306
 
307
+ __identifier__: ClassVar[Literal["@lovekit/agent"]] = "@lovekit/agent"
304
308
  typename: Literal["Agent"] = Field(
305
309
  alias="__typename", default="Agent", exclude=True
306
310
  )
@@ -348,6 +352,7 @@ class GetStreamQuery(BaseModel):
348
352
  class IsStreamLiveQueryStream(BaseModel):
349
353
  """One live source an agent offers: a camera, a detector, a microphone"""
350
354
 
355
+ __identifier__: ClassVar[Literal["@lovekit/stream"]] = "@lovekit/stream"
351
356
  typename: Literal["Stream"] = Field(
352
357
  alias="__typename", default="Stream", exclude=True
353
358
  )
@@ -376,6 +381,7 @@ class IsStreamLiveQuery(BaseModel):
376
381
  class SearchStreamsQueryOptions(BaseModel):
377
382
  """One live source an agent offers: a camera, a detector, a microphone"""
378
383
 
384
+ __identifier__: ClassVar[Literal["@lovekit/stream"]] = "@lovekit/stream"
379
385
  typename: Literal["Stream"] = Field(
380
386
  alias="__typename", default="Stream", exclude=True
381
387
  )
@@ -493,7 +499,7 @@ class LovekitApi:
493
499
  async def awatch_stream(self, stream: IDCoercible) -> str:
494
500
  """WatchStream
495
501
 
496
- A token to watch a stream: its agent's room, where it is the track named by its key
502
+ A token to watch a stream: its agent's room, where it is the track named by its key. A guest needs the agent in one of their collaborations
497
503
 
498
504
  Args:
499
505
  stream: The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `"4"`) or integer (such as `4`) input value will be accepted as an ID. (required)
@@ -510,7 +516,7 @@ class LovekitApi:
510
516
  def watch_stream(self, stream: IDCoercible) -> str:
511
517
  """WatchStream
512
518
 
513
- A token to watch a stream: its agent's room, where it is the track named by its key
519
+ A token to watch a stream: its agent's room, where it is the track named by its key. A guest needs the agent in one of their collaborations
514
520
 
515
521
  Args:
516
522
  stream: The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `"4"`) or integer (such as `4`) input value will be accepted as an ID. (required)
@@ -527,7 +533,7 @@ class LovekitApi:
527
533
  async def awatch_agent(self, agent: IDCoercible) -> str:
528
534
  """WatchAgent
529
535
 
530
- A token to watch every stream of an agent
536
+ A token to watch every stream of an agent. A guest needs the agent in one of their collaborations
531
537
 
532
538
  Args:
533
539
  agent: The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `"4"`) or integer (such as `4`) input value will be accepted as an ID. (required)
@@ -544,7 +550,7 @@ class LovekitApi:
544
550
  def watch_agent(self, agent: IDCoercible) -> str:
545
551
  """WatchAgent
546
552
 
547
- A token to watch every stream of an agent
553
+ A token to watch every stream of an agent. A guest needs the agent in one of their collaborations
548
554
 
549
555
  Args:
550
556
  agent: The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `"4"`) or integer (such as `4`) input value will be accepted as an ID. (required)
@@ -57,8 +57,8 @@ def lovekit(
57
57
  link=LovekitLinkComposition(
58
58
  auth=FaktsAuthLink(token_loader=tokens),
59
59
  split=SplitLink(
60
- left=AIOHttpLink(endpoint_url=lovekit.to_http_path("graphql"), proxy=lovekit.proxy),
61
- right=GraphQLWSLink(ws_endpoint_url=lovekit.to_ws_path("graphql"), proxy=lovekit.proxy),
60
+ left=AIOHttpLink(endpoint_url=lovekit.to_http_path("graphql"), proxy=lovekit.proxy, ssl_context=lovekit.ssl_context()),
61
+ right=GraphQLWSLink(ws_endpoint_url=lovekit.to_ws_path("graphql"), proxy=lovekit.proxy, ssl_context=lovekit.ssl_context()),
62
62
  split=lambda o: o.node.operation != OperationType.SUBSCRIPTION,
63
63
  ),
64
64
  )
@@ -36,6 +36,12 @@ async def aroom_options(alias: Alias) -> tuple[str, Any]:
36
36
  from livekit import rtc
37
37
 
38
38
  if not alias.is_mesh():
39
+ # LiveKit's SDK (rustls) reads its roots only from SSL_CERT_FILE: a pinned
40
+ # SFU's hub certificate is added to them there.
41
+ if alias.is_pinned():
42
+ from arkitekt_spec.declare import tls
43
+
44
+ tls.trust_natively(alias.certificates)
39
45
  return alias.to_ws_path(), rtc.RoomOptions()
40
46
  local = await alias.aforward()
41
47
  turn = await alias.aturn()
@@ -12,11 +12,11 @@ dependencies = [
12
12
  "numpy>=1.26",
13
13
  "rath>=4.1.1",
14
14
  # The service and structures are declared with arkitekt-spec.
15
- "arkitekt-spec>=3.4",
15
+ "arkitekt-spec>=3.19.1",
16
16
  # The GraphQL-WS link the client subscribes through; it came through rekuest before.
17
17
  "websockets>=15.0.1",
18
18
  # The service wiring (Alias, Require, FaktsAuthLink); it came through rekuest before.
19
- "fakts>=5.4",
19
+ "fakts>=6.1",
20
20
  ]
21
21
 
22
22
  [project.optional-dependencies]
@@ -30,6 +30,7 @@ dev-dependencies = [
30
30
  "python-semantic-release>=9.21.0",
31
31
  "pytest-aiohttp>=1.0.4,<2",
32
32
  "ruff>0.11",
33
+ "turms>=2.3.0",
33
34
  "dokker>=2.8",
34
35
  "websockets>=15.0.1",
35
36
  "basedpyright>=1.21",
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes