plexspaces 0.1.2__tar.gz → 0.1.4__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.
Files changed (103) hide show
  1. {plexspaces-0.1.2 → plexspaces-0.1.4}/PKG-INFO +1 -1
  2. {plexspaces-0.1.2 → plexspaces-0.1.4}/plexspaces/generated/plexspaces/application/v1/__init__.py +30 -65
  3. {plexspaces-0.1.2 → plexspaces-0.1.4}/plexspaces/generated/plexspaces/config/v1/__init__.py +1 -1
  4. {plexspaces-0.1.2 → plexspaces-0.1.4}/plexspaces/generated/plexspaces/dashboard/v1/__init__.py +464 -0
  5. {plexspaces-0.1.2 → plexspaces-0.1.4}/plexspaces/generated/plexspaces/node/v1/__init__.py +9 -0
  6. {plexspaces-0.1.2 → plexspaces-0.1.4}/plexspaces/generated/plexspaces/services/prv/__init__.py +3 -0
  7. {plexspaces-0.1.2 → plexspaces-0.1.4}/plexspaces/generated/plexspaces/storage/v1/__init__.py +4 -1
  8. {plexspaces-0.1.2 → plexspaces-0.1.4}/plexspaces.egg-info/PKG-INFO +1 -1
  9. {plexspaces-0.1.2 → plexspaces-0.1.4}/pyproject.toml +1 -1
  10. {plexspaces-0.1.2 → plexspaces-0.1.4}/README.md +0 -0
  11. {plexspaces-0.1.2 → plexspaces-0.1.4}/plexspaces/__init__.py +0 -0
  12. {plexspaces-0.1.2 → plexspaces-0.1.4}/plexspaces/actor_id.py +0 -0
  13. {plexspaces-0.1.2 → plexspaces-0.1.4}/plexspaces/decorators.py +0 -0
  14. {plexspaces-0.1.2 → plexspaces-0.1.4}/plexspaces/generated/__init__.py +0 -0
  15. {plexspaces-0.1.2 → plexspaces-0.1.4}/plexspaces/generated/buf/__init__.py +0 -0
  16. {plexspaces-0.1.2 → plexspaces-0.1.4}/plexspaces/generated/buf/validate/__init__.py +0 -0
  17. {plexspaces-0.1.2 → plexspaces-0.1.4}/plexspaces/generated/google/__init__.py +0 -0
  18. {plexspaces-0.1.2 → plexspaces-0.1.4}/plexspaces/generated/google/api/__init__.py +0 -0
  19. {plexspaces-0.1.2 → plexspaces-0.1.4}/plexspaces/generated/grpc/__init__.py +0 -0
  20. {plexspaces-0.1.2 → plexspaces-0.1.4}/plexspaces/generated/grpc/gateway/__init__.py +0 -0
  21. {plexspaces-0.1.2 → plexspaces-0.1.4}/plexspaces/generated/grpc/gateway/protoc_gen_openapiv2/__init__.py +0 -0
  22. {plexspaces-0.1.2 → plexspaces-0.1.4}/plexspaces/generated/grpc/gateway/protoc_gen_openapiv2/options/__init__.py +0 -0
  23. {plexspaces-0.1.2 → plexspaces-0.1.4}/plexspaces/generated/plexspaces/__init__.py +0 -0
  24. {plexspaces-0.1.2 → plexspaces-0.1.4}/plexspaces/generated/plexspaces/actor/__init__.py +0 -0
  25. {plexspaces-0.1.2 → plexspaces-0.1.4}/plexspaces/generated/plexspaces/actor/v1/__init__.py +0 -0
  26. {plexspaces-0.1.2 → plexspaces-0.1.4}/plexspaces/generated/plexspaces/application/__init__.py +0 -0
  27. {plexspaces-0.1.2 → plexspaces-0.1.4}/plexspaces/generated/plexspaces/behaviors/__init__.py +0 -0
  28. {plexspaces-0.1.2 → plexspaces-0.1.4}/plexspaces/generated/plexspaces/behaviors/v1/__init__.py +0 -0
  29. {plexspaces-0.1.2 → plexspaces-0.1.4}/plexspaces/generated/plexspaces/channel/__init__.py +0 -0
  30. {plexspaces-0.1.2 → plexspaces-0.1.4}/plexspaces/generated/plexspaces/channel/v1/__init__.py +0 -0
  31. {plexspaces-0.1.2 → plexspaces-0.1.4}/plexspaces/generated/plexspaces/circuitbreaker/__init__.py +0 -0
  32. {plexspaces-0.1.2 → plexspaces-0.1.4}/plexspaces/generated/plexspaces/circuitbreaker/prv/__init__.py +0 -0
  33. {plexspaces-0.1.2 → plexspaces-0.1.4}/plexspaces/generated/plexspaces/common/__init__.py +0 -0
  34. {plexspaces-0.1.2 → plexspaces-0.1.4}/plexspaces/generated/plexspaces/common/v1/__init__.py +0 -0
  35. {plexspaces-0.1.2 → plexspaces-0.1.4}/plexspaces/generated/plexspaces/config/__init__.py +0 -0
  36. {plexspaces-0.1.2 → plexspaces-0.1.4}/plexspaces/generated/plexspaces/dashboard/__init__.py +0 -0
  37. {plexspaces-0.1.2 → plexspaces-0.1.4}/plexspaces/generated/plexspaces/facets/__init__.py +0 -0
  38. {plexspaces-0.1.2 → plexspaces-0.1.4}/plexspaces/generated/plexspaces/facets/v1/__init__.py +0 -0
  39. {plexspaces-0.1.2 → plexspaces-0.1.4}/plexspaces/generated/plexspaces/firecracker/__init__.py +0 -0
  40. {plexspaces-0.1.2 → plexspaces-0.1.4}/plexspaces/generated/plexspaces/firecracker/v1/__init__.py +0 -0
  41. {plexspaces-0.1.2 → plexspaces-0.1.4}/plexspaces/generated/plexspaces/grpc/__init__.py +0 -0
  42. {plexspaces-0.1.2 → plexspaces-0.1.4}/plexspaces/generated/plexspaces/grpc/v1/__init__.py +0 -0
  43. {plexspaces-0.1.2 → plexspaces-0.1.4}/plexspaces/generated/plexspaces/journaling/__init__.py +0 -0
  44. {plexspaces-0.1.2 → plexspaces-0.1.4}/plexspaces/generated/plexspaces/journaling/v1/__init__.py +0 -0
  45. {plexspaces-0.1.2 → plexspaces-0.1.4}/plexspaces/generated/plexspaces/keyvalue/__init__.py +0 -0
  46. {plexspaces-0.1.2 → plexspaces-0.1.4}/plexspaces/generated/plexspaces/keyvalue/v1/__init__.py +0 -0
  47. {plexspaces-0.1.2 → plexspaces-0.1.4}/plexspaces/generated/plexspaces/locks/__init__.py +0 -0
  48. {plexspaces-0.1.2 → plexspaces-0.1.4}/plexspaces/generated/plexspaces/locks/prv/__init__.py +0 -0
  49. {plexspaces-0.1.2 → plexspaces-0.1.4}/plexspaces/generated/plexspaces/mailbox/__init__.py +0 -0
  50. {plexspaces-0.1.2 → plexspaces-0.1.4}/plexspaces/generated/plexspaces/mailbox/v1/__init__.py +0 -0
  51. {plexspaces-0.1.2 → plexspaces-0.1.4}/plexspaces/generated/plexspaces/metrics/__init__.py +0 -0
  52. {plexspaces-0.1.2 → plexspaces-0.1.4}/plexspaces/generated/plexspaces/metrics/v1/__init__.py +0 -0
  53. {plexspaces-0.1.2 → plexspaces-0.1.4}/plexspaces/generated/plexspaces/node/__init__.py +0 -0
  54. {plexspaces-0.1.2 → plexspaces-0.1.4}/plexspaces/generated/plexspaces/object_registry/__init__.py +0 -0
  55. {plexspaces-0.1.2 → plexspaces-0.1.4}/plexspaces/generated/plexspaces/object_registry/v1/__init__.py +0 -0
  56. {plexspaces-0.1.2 → plexspaces-0.1.4}/plexspaces/generated/plexspaces/persistence/__init__.py +0 -0
  57. {plexspaces-0.1.2 → plexspaces-0.1.4}/plexspaces/generated/plexspaces/persistence/prv/__init__.py +0 -0
  58. {plexspaces-0.1.2 → plexspaces-0.1.4}/plexspaces/generated/plexspaces/pool/__init__.py +0 -0
  59. {plexspaces-0.1.2 → plexspaces-0.1.4}/plexspaces/generated/plexspaces/pool/v1/__init__.py +0 -0
  60. {plexspaces-0.1.2 → plexspaces-0.1.4}/plexspaces/generated/plexspaces/processgroups/__init__.py +0 -0
  61. {plexspaces-0.1.2 → plexspaces-0.1.4}/plexspaces/generated/plexspaces/processgroups/v1/__init__.py +0 -0
  62. {plexspaces-0.1.2 → plexspaces-0.1.4}/plexspaces/generated/plexspaces/scheduling/__init__.py +0 -0
  63. {plexspaces-0.1.2 → plexspaces-0.1.4}/plexspaces/generated/plexspaces/scheduling/v1/__init__.py +0 -0
  64. {plexspaces-0.1.2 → plexspaces-0.1.4}/plexspaces/generated/plexspaces/security/__init__.py +0 -0
  65. {plexspaces-0.1.2 → plexspaces-0.1.4}/plexspaces/generated/plexspaces/security/v1/__init__.py +0 -0
  66. {plexspaces-0.1.2 → plexspaces-0.1.4}/plexspaces/generated/plexspaces/services/__init__.py +0 -0
  67. {plexspaces-0.1.2 → plexspaces-0.1.4}/plexspaces/generated/plexspaces/storage/__init__.py +0 -0
  68. {plexspaces-0.1.2 → plexspaces-0.1.4}/plexspaces/generated/plexspaces/supervision/__init__.py +0 -0
  69. {plexspaces-0.1.2 → plexspaces-0.1.4}/plexspaces/generated/plexspaces/supervision/v1/__init__.py +0 -0
  70. {plexspaces-0.1.2 → plexspaces-0.1.4}/plexspaces/generated/plexspaces/system/__init__.py +0 -0
  71. {plexspaces-0.1.2 → plexspaces-0.1.4}/plexspaces/generated/plexspaces/system/v1/__init__.py +0 -0
  72. {plexspaces-0.1.2 → plexspaces-0.1.4}/plexspaces/generated/plexspaces/timer/__init__.py +0 -0
  73. {plexspaces-0.1.2 → plexspaces-0.1.4}/plexspaces/generated/plexspaces/timer/v1/__init__.py +0 -0
  74. {plexspaces-0.1.2 → plexspaces-0.1.4}/plexspaces/generated/plexspaces/tuplespace/__init__.py +0 -0
  75. {plexspaces-0.1.2 → plexspaces-0.1.4}/plexspaces/generated/plexspaces/tuplespace/v1/__init__.py +0 -0
  76. {plexspaces-0.1.2 → plexspaces-0.1.4}/plexspaces/generated/plexspaces/wasm/__init__.py +0 -0
  77. {plexspaces-0.1.2 → plexspaces-0.1.4}/plexspaces/generated/plexspaces/wasm/v1/__init__.py +0 -0
  78. {plexspaces-0.1.2 → plexspaces-0.1.4}/plexspaces/generated/plexspaces/workflow/__init__.py +0 -0
  79. {plexspaces-0.1.2 → plexspaces-0.1.4}/plexspaces/generated/plexspaces/workflow/v1/__init__.py +0 -0
  80. {plexspaces-0.1.2 → plexspaces-0.1.4}/plexspaces/host.py +0 -0
  81. {plexspaces-0.1.2 → plexspaces-0.1.4}/plexspaces/leader_worker.py +0 -0
  82. {plexspaces-0.1.2 → plexspaces-0.1.4}/plexspaces/proto_wire.py +0 -0
  83. {plexspaces-0.1.2 → plexspaces-0.1.4}/plexspaces/runtime.py +0 -0
  84. {plexspaces-0.1.2 → plexspaces-0.1.4}/plexspaces/workflow.py +0 -0
  85. {plexspaces-0.1.2 → plexspaces-0.1.4}/plexspaces.egg-info/SOURCES.txt +0 -0
  86. {plexspaces-0.1.2 → plexspaces-0.1.4}/plexspaces.egg-info/dependency_links.txt +0 -0
  87. {plexspaces-0.1.2 → plexspaces-0.1.4}/plexspaces.egg-info/entry_points.txt +0 -0
  88. {plexspaces-0.1.2 → plexspaces-0.1.4}/plexspaces.egg-info/requires.txt +0 -0
  89. {plexspaces-0.1.2 → plexspaces-0.1.4}/plexspaces.egg-info/top_level.txt +0 -0
  90. {plexspaces-0.1.2 → plexspaces-0.1.4}/plexspaces_cli/__init__.py +0 -0
  91. {plexspaces-0.1.2 → plexspaces-0.1.4}/plexspaces_cli/build.py +0 -0
  92. {plexspaces-0.1.2 → plexspaces-0.1.4}/setup.cfg +0 -0
  93. {plexspaces-0.1.2 → plexspaces-0.1.4}/tests/test_abstractions_contract.py +0 -0
  94. {plexspaces-0.1.2 → plexspaces-0.1.4}/tests/test_actor_id.py +0 -0
  95. {plexspaces-0.1.2 → plexspaces-0.1.4}/tests/test_application_metrics_host.py +0 -0
  96. {plexspaces-0.1.2 → plexspaces-0.1.4}/tests/test_decorators.py +0 -0
  97. {plexspaces-0.1.2 → plexspaces-0.1.4}/tests/test_host.py +0 -0
  98. {plexspaces-0.1.2 → plexspaces-0.1.4}/tests/test_host_collective.py +0 -0
  99. {plexspaces-0.1.2 → plexspaces-0.1.4}/tests/test_host_tuple_space.py +0 -0
  100. {plexspaces-0.1.2 → plexspaces-0.1.4}/tests/test_http_fetch_wire.py +0 -0
  101. {plexspaces-0.1.2 → plexspaces-0.1.4}/tests/test_lock_wire.py +0 -0
  102. {plexspaces-0.1.2 → plexspaces-0.1.4}/tests/test_runtime.py +0 -0
  103. {plexspaces-0.1.2 → plexspaces-0.1.4}/tests/test_workflow_retry.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: plexspaces
3
- Version: 0.1.2
3
+ Version: 0.1.4
4
4
  Summary: PlexSpaces Python SDK - Build actors with minimal boilerplate
5
5
  Author: PlexSpaces Contributors
6
6
  License: AGPL-3.0-or-later
@@ -258,102 +258,68 @@ class ApplicationSpec(betterproto.Message):
258
258
 
259
259
  name: str = betterproto.string_field(1)
260
260
  """
261
- Application name (unique identifier within node)
261
+ Application name (unique identifier within node).
262
+ Serves as the namespace for all actors spawned by this application.
262
263
  Examples: "byzantine-generals", "genomics-coordinator"
263
264
  """
264
265
 
265
266
  tenant_id: str = betterproto.string_field(2)
266
267
  """
267
268
  Tenant ID for multi-tenancy isolation.
268
- Extracted from JWT token during deployment.
269
- All actors spawned by this application will be scoped to this tenant.
270
- This is the source of truth for tenant isolation - ActorFactory enforces it.
269
+ Extracted from JWT token during deployment; fallback from app-config.toml.
271
270
  """
272
271
 
273
- namespace: str = betterproto.string_field(3)
274
- """
275
- Namespace for actor isolation within a tenant.
276
- All actors spawned by this application will be registered in this namespace.
277
- If empty, defaults to application_id during deployment.
278
- Examples: "bank-test", "genomics-prod", "dev-sandbox"
279
- """
280
-
281
- version: str = betterproto.string_field(4)
272
+ version: str = betterproto.string_field(3)
282
273
  """
283
274
  Application version (semantic versioning)
284
275
  Examples: "0.1.0", "1.2.3"
285
276
  """
286
277
 
287
- description: str = betterproto.string_field(5)
278
+ description: str = betterproto.string_field(4)
288
279
  """Human-readable description"""
289
280
 
290
- type: "ApplicationType" = betterproto.enum_field(6)
281
+ type: "ApplicationType" = betterproto.enum_field(5)
291
282
  """Application type (library or active)"""
292
283
 
293
- dependencies: List[str] = betterproto.string_field(7)
294
- """
295
- Dependencies (other applications that must start first)
296
- e.g., ["plexspaces-core", "plexspaces-tuplespace"]
297
- """
284
+ dependencies: List[str] = betterproto.string_field(6)
285
+ """Dependencies (other applications that must start first)"""
298
286
 
299
287
  env: Dict[str, str] = betterproto.map_field(
300
- 8, betterproto.TYPE_STRING, betterproto.TYPE_STRING
288
+ 7, betterproto.TYPE_STRING, betterproto.TYPE_STRING
301
289
  )
302
290
  """Application-level environment variables"""
303
291
 
304
292
  supervisor: Optional["__supervision_v1__.SupervisorSpec"] = (
305
- betterproto.message_field(9, optional=True)
293
+ betterproto.message_field(8, optional=True)
306
294
  )
307
295
  """Supervision tree (only for active applications)"""
308
296
 
309
- enabled: bool = betterproto.bool_field(10)
310
- """
311
- Whether application is enabled (false = skip loading)
312
- Default: true
313
- """
297
+ enabled: bool = betterproto.bool_field(9)
298
+ """Whether application is enabled (false = skip loading). Default: true"""
314
299
 
315
- auto_start: bool = betterproto.bool_field(11)
300
+ auto_start: bool = betterproto.bool_field(10)
316
301
  """
317
- Whether to start application automatically on node boot
318
- Default: true
319
- Future: false allows manual start via ApplicationService API
302
+ Whether to start application automatically on node boot. Default: true
320
303
  """
321
304
 
322
- shutdown_timeout: timedelta = betterproto.message_field(12)
323
- """
324
- Shutdown timeout (force kill if exceeded)
325
- Default: 60 seconds
326
- """
305
+ shutdown_timeout: timedelta = betterproto.message_field(11)
306
+ """Shutdown timeout (force kill if exceeded). Default: 60 seconds"""
327
307
 
328
- shutdown_strategy: "ShutdownStrategy" = betterproto.enum_field(13)
329
- """
330
- Shutdown strategy (graceful or immediate)
331
- Default: GRACEFUL
332
- """
308
+ shutdown_strategy: "ShutdownStrategy" = betterproto.enum_field(12)
309
+ """Shutdown strategy (graceful or immediate). Default: GRACEFUL"""
333
310
 
334
- metadata: "__common_v1__.Metadata" = betterproto.message_field(14)
335
- """
336
- Application metadata (tags, labels, annotations)
337
- Examples:
338
- - environment: "production"
339
- - team: "genomics"
340
- - criticality: "high"
341
- """
311
+ metadata: "__common_v1__.Metadata" = betterproto.message_field(13)
312
+ """Application metadata (tags, labels, annotations)"""
342
313
 
343
- seed_nodes: List[str] = betterproto.string_field(15)
314
+ seed_nodes: List[str] = betterproto.string_field(14)
344
315
  """
345
316
  Seed nodes (gRPC addresses) to connect to when this application is deployed.
346
- The node will connect to these addresses if not already connected, so
347
- leader-worker and scatter/gather can use workers on other nodes.
348
- Example: ["localhost:8091", "localhost:8093"]
349
317
  """
350
318
 
351
319
  required_service_links: List["ApplicationServiceLinkRequirement"] = (
352
- betterproto.message_field(16)
320
+ betterproto.message_field(15)
353
321
  )
354
- """
355
- External service links this application expects at deploy time (validated against node catalog).
356
- """
322
+ """External service links this application expects at deploy time."""
357
323
 
358
324
 
359
325
  @dataclass(eq=False, repr=False)
@@ -556,25 +522,24 @@ class ApplicationInfo(betterproto.Message):
556
522
  """Application ID"""
557
523
 
558
524
  name: str = betterproto.string_field(2)
559
- """Application name"""
525
+ """
526
+ Application name (also serves as the namespace for actors in this application)
527
+ """
560
528
 
561
529
  tenant_id: str = betterproto.string_field(3)
562
530
  """Tenant ID for visibility and isolation."""
563
531
 
564
- namespace: str = betterproto.string_field(4)
565
- """Namespace for application-scoped actors and filters."""
566
-
567
- version: str = betterproto.string_field(5)
532
+ version: str = betterproto.string_field(4)
568
533
  """Application version"""
569
534
 
570
- status: "ApplicationStatus" = betterproto.enum_field(6)
535
+ status: "ApplicationStatus" = betterproto.enum_field(5)
571
536
  """Current status"""
572
537
 
573
- deployed_at: datetime = betterproto.message_field(7)
538
+ deployed_at: datetime = betterproto.message_field(6)
574
539
  """When the application was deployed"""
575
540
 
576
541
  metrics: Optional["ApplicationMetrics"] = betterproto.message_field(
577
- 8, optional=True
542
+ 7, optional=True
578
543
  )
579
544
  """Application metrics (optional)"""
580
545
 
@@ -96,7 +96,7 @@ class S3Config(betterproto.Message):
96
96
 
97
97
  use_path_style: bool = betterproto.bool_field(4)
98
98
  """
99
- Use path-style URLs (required for MinIO and some S3-compatible stores)
99
+ Use path-style URLs (required for embedded and some S3-compatible stores)
100
100
  """
101
101
 
102
102
 
@@ -20,7 +20,10 @@ from ...application import v1 as __application_v1__
20
20
  from ...common import v1 as __common_v1__
21
21
  from ...metrics import v1 as __metrics_v1__
22
22
  from ...node import v1 as __node_v1__
23
+ from ...object_registry import v1 as __object_registry_v1__
24
+ from ...storage import v1 as __storage_v1__
23
25
  from ...system import v1 as __system_v1__
26
+ from ...tuplespace import v1 as __tuplespace_v1__
24
27
  from ...workflow import v1 as __workflow_v1__
25
28
 
26
29
  if TYPE_CHECKING:
@@ -354,6 +357,218 @@ class GetDashboardMetricsResponse(betterproto.Message):
354
357
  prometheus_text: str = betterproto.string_field(3)
355
358
 
356
359
 
360
+ @dataclass(eq=False, repr=False)
361
+ class GetObjectsRequest(betterproto.Message):
362
+ node_id: str = betterproto.string_field(1)
363
+ """Filter by node ID (optional, empty = local node)"""
364
+
365
+ tenant_id: str = betterproto.string_field(2)
366
+ """Filter by tenant ID (optional, from auth context if not provided)"""
367
+
368
+ namespace: str = betterproto.string_field(3)
369
+ """Filter by namespace (optional)"""
370
+
371
+ object_type: str = betterproto.string_field(4)
372
+ """
373
+ Filter by object type string: "ACTOR", "TUPLESPACE", "SERVICE", "VM", "APPLICATION", "WORKFLOW", "NODE" (optional)
374
+ """
375
+
376
+ health_status: str = betterproto.string_field(5)
377
+ """
378
+ Filter by health status string: "HEALTHY", "DEGRADED", "DEAD" (optional)
379
+ """
380
+
381
+ id_pattern: str = betterproto.string_field(6)
382
+ """Filter by object ID pattern (optional)"""
383
+
384
+ page: "__common_v1__.PageRequest" = betterproto.message_field(7)
385
+ """Pagination"""
386
+
387
+
388
+ @dataclass(eq=False, repr=False)
389
+ class GetObjectsResponse(betterproto.Message):
390
+ objects: List["__object_registry_v1__.ObjectRegistration"] = (
391
+ betterproto.message_field(1)
392
+ )
393
+ page: "__common_v1__.PageResponse" = betterproto.message_field(2)
394
+
395
+
396
+ @dataclass(eq=False, repr=False)
397
+ class GetKeyValuesRequest(betterproto.Message):
398
+ node_id: str = betterproto.string_field(1)
399
+ """Filter by node ID (optional, empty = local node)"""
400
+
401
+ tenant_id: str = betterproto.string_field(2)
402
+ """Filter by tenant ID (optional, from auth context if not provided)"""
403
+
404
+ namespace: str = betterproto.string_field(3)
405
+ """Filter by namespace (optional)"""
406
+
407
+ prefix: str = betterproto.string_field(4)
408
+ """Key prefix filter (optional)"""
409
+
410
+ page: "__common_v1__.PageRequest" = betterproto.message_field(5)
411
+ """Pagination"""
412
+
413
+
414
+ @dataclass(eq=False, repr=False)
415
+ class KeyValueDashboardEntry(betterproto.Message):
416
+ """
417
+ Lightweight KV entry for dashboard display (value truncated for safety)
418
+ """
419
+
420
+ key: str = betterproto.string_field(1)
421
+ """The key"""
422
+
423
+ value_preview: str = betterproto.string_field(2)
424
+ """Value preview (first 100 UTF-8 bytes)"""
425
+
426
+ size_bytes: int = betterproto.uint64_field(3)
427
+ """Full value size in bytes"""
428
+
429
+
430
+ @dataclass(eq=False, repr=False)
431
+ class GetKeyValuesResponse(betterproto.Message):
432
+ entries: List["KeyValueDashboardEntry"] = betterproto.message_field(1)
433
+ page: "__common_v1__.PageResponse" = betterproto.message_field(2)
434
+
435
+
436
+ @dataclass(eq=False, repr=False)
437
+ class GetTupleSpacesRequest(betterproto.Message):
438
+ node_id: str = betterproto.string_field(1)
439
+ """Filter by node ID (optional, empty = local node)"""
440
+
441
+ tenant_id: str = betterproto.string_field(2)
442
+ """Filter by tenant ID (optional, from auth context if not provided)"""
443
+
444
+ namespace: str = betterproto.string_field(3)
445
+ """Filter by namespace (optional)"""
446
+
447
+ pattern: str = betterproto.string_field(4)
448
+ """Optional pattern string to match against tuples (default: wildcard)"""
449
+
450
+
451
+ @dataclass(eq=False, repr=False)
452
+ class TupleSpaceSummary(betterproto.Message):
453
+ """Summary of a tuplespace namespace"""
454
+
455
+ namespace: str = betterproto.string_field(1)
456
+ """Namespace this summary is for"""
457
+
458
+ pattern: str = betterproto.string_field(2)
459
+ """Pattern used for counting (empty = wildcard)"""
460
+
461
+ tuple_count: int = betterproto.uint64_field(3)
462
+ """Total tuple count matching the pattern"""
463
+
464
+ sample_tuples: List["__tuplespace_v1__.Tuple"] = betterproto.message_field(4)
465
+ """Sample tuples (up to 20)"""
466
+
467
+
468
+ @dataclass(eq=False, repr=False)
469
+ class GetTupleSpacesResponse(betterproto.Message):
470
+ spaces: List["TupleSpaceSummary"] = betterproto.message_field(1)
471
+
472
+
473
+ @dataclass(eq=False, repr=False)
474
+ class GetBlobsRequest(betterproto.Message):
475
+ node_id: str = betterproto.string_field(1)
476
+ """Filter by node ID (optional, empty = local node)"""
477
+
478
+ tenant_id: str = betterproto.string_field(2)
479
+ """Filter by tenant ID (optional, from auth context if not provided)"""
480
+
481
+ namespace: str = betterproto.string_field(3)
482
+ """Filter by namespace (optional)"""
483
+
484
+ kind: str = betterproto.string_field(4)
485
+ """Filter by blob kind (optional)"""
486
+
487
+ prefix: str = betterproto.string_field(5)
488
+ """Filter by blob name prefix (optional)"""
489
+
490
+ page: "__common_v1__.PageRequest" = betterproto.message_field(6)
491
+ """Pagination"""
492
+
493
+
494
+ @dataclass(eq=False, repr=False)
495
+ class GetBlobsResponse(betterproto.Message):
496
+ blobs: List["__storage_v1__.BlobMetadata"] = betterproto.message_field(1)
497
+ """Reuses existing BlobMetadata proto from storage package"""
498
+
499
+ page: "__common_v1__.PageResponse" = betterproto.message_field(2)
500
+
501
+
502
+ @dataclass(eq=False, repr=False)
503
+ class GetBlobPresignedUrlRequest(betterproto.Message):
504
+ blob_id: str = betterproto.string_field(1)
505
+ """Blob ID (required)"""
506
+
507
+ node_id: str = betterproto.string_field(2)
508
+ """Node ID where the blob lives (optional, empty = local node)"""
509
+
510
+ tenant_id: str = betterproto.string_field(3)
511
+ """
512
+ Tenant ID for authorization (optional, from auth context if not provided)
513
+ """
514
+
515
+ namespace: str = betterproto.string_field(4)
516
+ """Namespace for authorization (optional)"""
517
+
518
+
519
+ @dataclass(eq=False, repr=False)
520
+ class GetBlobPresignedUrlResponse(betterproto.Message):
521
+ url: str = betterproto.string_field(1)
522
+ """Presigned download URL (empty if not available)"""
523
+
524
+ expires_at: datetime = betterproto.message_field(2)
525
+ """URL expiration timestamp"""
526
+
527
+ error: str = betterproto.string_field(3)
528
+ """Error message if presigned URLs are not configured or blob not found"""
529
+
530
+
531
+ @dataclass(eq=False, repr=False)
532
+ class GetServiceLinksRequest(betterproto.Message):
533
+ node_id: str = betterproto.string_field(1)
534
+ """Node ID (optional, empty = local node)"""
535
+
536
+ tenant_id: str = betterproto.string_field(2)
537
+ """Tenant ID (optional, used for filtering if auth enabled)"""
538
+
539
+
540
+ @dataclass(eq=False, repr=False)
541
+ class GetServiceLinksResponse(betterproto.Message):
542
+ service_links: List["__node_v1__.ServiceLinkConfig"] = betterproto.message_field(1)
543
+ """Reuses existing ServiceLinkConfig proto from node/outbound package"""
544
+
545
+
546
+ @dataclass(eq=False, repr=False)
547
+ class GetMetricsTableRequest(betterproto.Message):
548
+ node_id: str = betterproto.string_field(1)
549
+ """Node ID (optional, empty = local node)"""
550
+
551
+ namespace: str = betterproto.string_field(2)
552
+ """Optional namespace label filter"""
553
+
554
+ name_pattern: str = betterproto.string_field(3)
555
+ """Name glob; empty or "*" matches all metric names"""
556
+
557
+ label_filter: Dict[str, str] = betterproto.map_field(
558
+ 4, betterproto.TYPE_STRING, betterproto.TYPE_STRING
559
+ )
560
+ """Additional label equality filters (AND)"""
561
+
562
+
563
+ @dataclass(eq=False, repr=False)
564
+ class GetMetricsTableResponse(betterproto.Message):
565
+ metrics: List["__metrics_v1__.Metric"] = betterproto.message_field(1)
566
+ """All matching metrics with current values"""
567
+
568
+ definitions: List["__metrics_v1__.MetricDefinition"] = betterproto.message_field(2)
569
+ """Metric definitions (metadata: description, unit, type)"""
570
+
571
+
357
572
  class DashboardServiceStub(betterproto.ServiceStub):
358
573
  async def get_summary(
359
574
  self,
@@ -491,6 +706,125 @@ class DashboardServiceStub(betterproto.ServiceStub):
491
706
  metadata=metadata,
492
707
  )
493
708
 
709
+ async def get_objects(
710
+ self,
711
+ get_objects_request: "GetObjectsRequest",
712
+ *,
713
+ timeout: Optional[float] = None,
714
+ deadline: Optional["Deadline"] = None,
715
+ metadata: Optional["MetadataLike"] = None
716
+ ) -> "GetObjectsResponse":
717
+ return await self._unary_unary(
718
+ "/plexspaces.dashboard.v1.DashboardService/GetObjects",
719
+ get_objects_request,
720
+ GetObjectsResponse,
721
+ timeout=timeout,
722
+ deadline=deadline,
723
+ metadata=metadata,
724
+ )
725
+
726
+ async def get_key_values(
727
+ self,
728
+ get_key_values_request: "GetKeyValuesRequest",
729
+ *,
730
+ timeout: Optional[float] = None,
731
+ deadline: Optional["Deadline"] = None,
732
+ metadata: Optional["MetadataLike"] = None
733
+ ) -> "GetKeyValuesResponse":
734
+ return await self._unary_unary(
735
+ "/plexspaces.dashboard.v1.DashboardService/GetKeyValues",
736
+ get_key_values_request,
737
+ GetKeyValuesResponse,
738
+ timeout=timeout,
739
+ deadline=deadline,
740
+ metadata=metadata,
741
+ )
742
+
743
+ async def get_tuple_spaces(
744
+ self,
745
+ get_tuple_spaces_request: "GetTupleSpacesRequest",
746
+ *,
747
+ timeout: Optional[float] = None,
748
+ deadline: Optional["Deadline"] = None,
749
+ metadata: Optional["MetadataLike"] = None
750
+ ) -> "GetTupleSpacesResponse":
751
+ return await self._unary_unary(
752
+ "/plexspaces.dashboard.v1.DashboardService/GetTupleSpaces",
753
+ get_tuple_spaces_request,
754
+ GetTupleSpacesResponse,
755
+ timeout=timeout,
756
+ deadline=deadline,
757
+ metadata=metadata,
758
+ )
759
+
760
+ async def get_blobs(
761
+ self,
762
+ get_blobs_request: "GetBlobsRequest",
763
+ *,
764
+ timeout: Optional[float] = None,
765
+ deadline: Optional["Deadline"] = None,
766
+ metadata: Optional["MetadataLike"] = None
767
+ ) -> "GetBlobsResponse":
768
+ return await self._unary_unary(
769
+ "/plexspaces.dashboard.v1.DashboardService/GetBlobs",
770
+ get_blobs_request,
771
+ GetBlobsResponse,
772
+ timeout=timeout,
773
+ deadline=deadline,
774
+ metadata=metadata,
775
+ )
776
+
777
+ async def get_blob_presigned_url(
778
+ self,
779
+ get_blob_presigned_url_request: "GetBlobPresignedUrlRequest",
780
+ *,
781
+ timeout: Optional[float] = None,
782
+ deadline: Optional["Deadline"] = None,
783
+ metadata: Optional["MetadataLike"] = None
784
+ ) -> "GetBlobPresignedUrlResponse":
785
+ return await self._unary_unary(
786
+ "/plexspaces.dashboard.v1.DashboardService/GetBlobPresignedUrl",
787
+ get_blob_presigned_url_request,
788
+ GetBlobPresignedUrlResponse,
789
+ timeout=timeout,
790
+ deadline=deadline,
791
+ metadata=metadata,
792
+ )
793
+
794
+ async def get_service_links(
795
+ self,
796
+ get_service_links_request: "GetServiceLinksRequest",
797
+ *,
798
+ timeout: Optional[float] = None,
799
+ deadline: Optional["Deadline"] = None,
800
+ metadata: Optional["MetadataLike"] = None
801
+ ) -> "GetServiceLinksResponse":
802
+ return await self._unary_unary(
803
+ "/plexspaces.dashboard.v1.DashboardService/GetServiceLinks",
804
+ get_service_links_request,
805
+ GetServiceLinksResponse,
806
+ timeout=timeout,
807
+ deadline=deadline,
808
+ metadata=metadata,
809
+ )
810
+
811
+ async def get_metrics_table(
812
+ self,
813
+ get_metrics_table_request: "GetMetricsTableRequest",
814
+ *,
815
+ timeout: Optional[float] = None,
816
+ deadline: Optional["Deadline"] = None,
817
+ metadata: Optional["MetadataLike"] = None
818
+ ) -> "GetMetricsTableResponse":
819
+ return await self._unary_unary(
820
+ "/plexspaces.dashboard.v1.DashboardService/GetMetricsTable",
821
+ get_metrics_table_request,
822
+ GetMetricsTableResponse,
823
+ timeout=timeout,
824
+ deadline=deadline,
825
+ metadata=metadata,
826
+ )
827
+
494
828
 
495
829
  class DashboardServiceBase(ServiceBase):
496
830
 
@@ -534,6 +868,41 @@ class DashboardServiceBase(ServiceBase):
534
868
  ) -> "GetDashboardMetricsResponse":
535
869
  raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)
536
870
 
871
+ async def get_objects(
872
+ self, get_objects_request: "GetObjectsRequest"
873
+ ) -> "GetObjectsResponse":
874
+ raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)
875
+
876
+ async def get_key_values(
877
+ self, get_key_values_request: "GetKeyValuesRequest"
878
+ ) -> "GetKeyValuesResponse":
879
+ raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)
880
+
881
+ async def get_tuple_spaces(
882
+ self, get_tuple_spaces_request: "GetTupleSpacesRequest"
883
+ ) -> "GetTupleSpacesResponse":
884
+ raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)
885
+
886
+ async def get_blobs(
887
+ self, get_blobs_request: "GetBlobsRequest"
888
+ ) -> "GetBlobsResponse":
889
+ raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)
890
+
891
+ async def get_blob_presigned_url(
892
+ self, get_blob_presigned_url_request: "GetBlobPresignedUrlRequest"
893
+ ) -> "GetBlobPresignedUrlResponse":
894
+ raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)
895
+
896
+ async def get_service_links(
897
+ self, get_service_links_request: "GetServiceLinksRequest"
898
+ ) -> "GetServiceLinksResponse":
899
+ raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)
900
+
901
+ async def get_metrics_table(
902
+ self, get_metrics_table_request: "GetMetricsTableRequest"
903
+ ) -> "GetMetricsTableResponse":
904
+ raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)
905
+
537
906
  async def __rpc_get_summary(
538
907
  self, stream: "grpclib.server.Stream[GetSummaryRequest, GetSummaryResponse]"
539
908
  ) -> None:
@@ -594,6 +963,59 @@ class DashboardServiceBase(ServiceBase):
594
963
  response = await self.get_dashboard_metrics(request)
595
964
  await stream.send_message(response)
596
965
 
966
+ async def __rpc_get_objects(
967
+ self, stream: "grpclib.server.Stream[GetObjectsRequest, GetObjectsResponse]"
968
+ ) -> None:
969
+ request = await stream.recv_message()
970
+ response = await self.get_objects(request)
971
+ await stream.send_message(response)
972
+
973
+ async def __rpc_get_key_values(
974
+ self, stream: "grpclib.server.Stream[GetKeyValuesRequest, GetKeyValuesResponse]"
975
+ ) -> None:
976
+ request = await stream.recv_message()
977
+ response = await self.get_key_values(request)
978
+ await stream.send_message(response)
979
+
980
+ async def __rpc_get_tuple_spaces(
981
+ self,
982
+ stream: "grpclib.server.Stream[GetTupleSpacesRequest, GetTupleSpacesResponse]",
983
+ ) -> None:
984
+ request = await stream.recv_message()
985
+ response = await self.get_tuple_spaces(request)
986
+ await stream.send_message(response)
987
+
988
+ async def __rpc_get_blobs(
989
+ self, stream: "grpclib.server.Stream[GetBlobsRequest, GetBlobsResponse]"
990
+ ) -> None:
991
+ request = await stream.recv_message()
992
+ response = await self.get_blobs(request)
993
+ await stream.send_message(response)
994
+
995
+ async def __rpc_get_blob_presigned_url(
996
+ self,
997
+ stream: "grpclib.server.Stream[GetBlobPresignedUrlRequest, GetBlobPresignedUrlResponse]",
998
+ ) -> None:
999
+ request = await stream.recv_message()
1000
+ response = await self.get_blob_presigned_url(request)
1001
+ await stream.send_message(response)
1002
+
1003
+ async def __rpc_get_service_links(
1004
+ self,
1005
+ stream: "grpclib.server.Stream[GetServiceLinksRequest, GetServiceLinksResponse]",
1006
+ ) -> None:
1007
+ request = await stream.recv_message()
1008
+ response = await self.get_service_links(request)
1009
+ await stream.send_message(response)
1010
+
1011
+ async def __rpc_get_metrics_table(
1012
+ self,
1013
+ stream: "grpclib.server.Stream[GetMetricsTableRequest, GetMetricsTableResponse]",
1014
+ ) -> None:
1015
+ request = await stream.recv_message()
1016
+ response = await self.get_metrics_table(request)
1017
+ await stream.send_message(response)
1018
+
597
1019
  def __mapping__(self) -> Dict[str, grpclib.const.Handler]:
598
1020
  return {
599
1021
  "/plexspaces.dashboard.v1.DashboardService/GetSummary": grpclib.const.Handler(
@@ -644,4 +1066,46 @@ class DashboardServiceBase(ServiceBase):
644
1066
  GetDashboardMetricsRequest,
645
1067
  GetDashboardMetricsResponse,
646
1068
  ),
1069
+ "/plexspaces.dashboard.v1.DashboardService/GetObjects": grpclib.const.Handler(
1070
+ self.__rpc_get_objects,
1071
+ grpclib.const.Cardinality.UNARY_UNARY,
1072
+ GetObjectsRequest,
1073
+ GetObjectsResponse,
1074
+ ),
1075
+ "/plexspaces.dashboard.v1.DashboardService/GetKeyValues": grpclib.const.Handler(
1076
+ self.__rpc_get_key_values,
1077
+ grpclib.const.Cardinality.UNARY_UNARY,
1078
+ GetKeyValuesRequest,
1079
+ GetKeyValuesResponse,
1080
+ ),
1081
+ "/plexspaces.dashboard.v1.DashboardService/GetTupleSpaces": grpclib.const.Handler(
1082
+ self.__rpc_get_tuple_spaces,
1083
+ grpclib.const.Cardinality.UNARY_UNARY,
1084
+ GetTupleSpacesRequest,
1085
+ GetTupleSpacesResponse,
1086
+ ),
1087
+ "/plexspaces.dashboard.v1.DashboardService/GetBlobs": grpclib.const.Handler(
1088
+ self.__rpc_get_blobs,
1089
+ grpclib.const.Cardinality.UNARY_UNARY,
1090
+ GetBlobsRequest,
1091
+ GetBlobsResponse,
1092
+ ),
1093
+ "/plexspaces.dashboard.v1.DashboardService/GetBlobPresignedUrl": grpclib.const.Handler(
1094
+ self.__rpc_get_blob_presigned_url,
1095
+ grpclib.const.Cardinality.UNARY_UNARY,
1096
+ GetBlobPresignedUrlRequest,
1097
+ GetBlobPresignedUrlResponse,
1098
+ ),
1099
+ "/plexspaces.dashboard.v1.DashboardService/GetServiceLinks": grpclib.const.Handler(
1100
+ self.__rpc_get_service_links,
1101
+ grpclib.const.Cardinality.UNARY_UNARY,
1102
+ GetServiceLinksRequest,
1103
+ GetServiceLinksResponse,
1104
+ ),
1105
+ "/plexspaces.dashboard.v1.DashboardService/GetMetricsTable": grpclib.const.Handler(
1106
+ self.__rpc_get_metrics_table,
1107
+ grpclib.const.Cardinality.UNARY_UNARY,
1108
+ GetMetricsTableRequest,
1109
+ GetMetricsTableResponse,
1110
+ ),
647
1111
  }
@@ -458,6 +458,15 @@ class NodeConfig(betterproto.Message):
458
458
  Example: "http://node1.example.com:8000"
459
459
  """
460
460
 
461
+ blob_http_port: int = betterproto.uint32_field(22)
462
+ """
463
+ Port for blob HTTP: the PlexSpaces blob REST API (non-embedded) or the
464
+ embedded rustfs S3-compatible subprocess (when backend = "embedded").
465
+
466
+ Set to 0 (default) to derive automatically as listen_addr port + 100.
467
+ Example: if listen_addr is "0.0.0.0:8000", blob_http_port defaults to 8100.
468
+ """
469
+
461
470
 
462
471
  @dataclass(eq=False, repr=False)
463
472
  class NodeRegistryConfig(betterproto.Message):
@@ -42,6 +42,9 @@ class ServiceName(betterproto.Enum):
42
42
  WORKFLOW_SERVICE = 19
43
43
  SYSTEM_SERVICE = 20
44
44
  NODE_SERVICE = 21
45
+ KEY_VALUE_SERVICE = 22
46
+ SERVICE_LINK_SERVICE = 23
47
+ METRICS_SERVICE = 24
45
48
 
46
49
 
47
50
  class ServiceCallErrorCode(betterproto.Enum):
@@ -127,7 +127,10 @@ class BlobConfig(betterproto.Message):
127
127
  """Bucket name"""
128
128
 
129
129
  endpoint: str = betterproto.string_field(3)
130
- """Endpoint URL (for SeaweedFS or custom S3-compatible)"""
130
+ """
131
+ Endpoint URL for embedded or custom S3-compatible store (e.g., "http://127.0.0.1:9100").
132
+ Leave empty when using embedded backend — endpoint is set automatically after process start.
133
+ """
131
134
 
132
135
  region: str = betterproto.string_field(4)
133
136
  """Region (for S3/GCP/Azure)"""
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: plexspaces
3
- Version: 0.1.2
3
+ Version: 0.1.4
4
4
  Summary: PlexSpaces Python SDK - Build actors with minimal boilerplate
5
5
  Author: PlexSpaces Contributors
6
6
  License: AGPL-3.0-or-later
@@ -7,7 +7,7 @@ build-backend = "setuptools.build_meta"
7
7
 
8
8
  [project]
9
9
  name = "plexspaces"
10
- version = "0.1.2"
10
+ version = "0.1.4"
11
11
  description = "PlexSpaces Python SDK - Build actors with minimal boilerplate"
12
12
  readme = "README.md"
13
13
  license = {text = "AGPL-3.0-or-later"}
File without changes
File without changes