runapi-luma 0.1.0__py3-none-any.whl

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.
@@ -0,0 +1,24 @@
1
+ """Luma client for RunAPI."""
2
+
3
+ from runapi.core import (
4
+ AuthenticationError,
5
+ InsufficientCreditsError,
6
+ NotFoundError,
7
+ RateLimitError,
8
+ TaskFailedError,
9
+ TaskTimeoutError,
10
+ ValidationError,
11
+ )
12
+
13
+ from .client import LumaClient
14
+
15
+ __all__ = [
16
+ "LumaClient",
17
+ "AuthenticationError",
18
+ "RateLimitError",
19
+ "InsufficientCreditsError",
20
+ "NotFoundError",
21
+ "ValidationError",
22
+ "TaskFailedError",
23
+ "TaskTimeoutError",
24
+ ]
runapi/luma/client.py ADDED
@@ -0,0 +1,28 @@
1
+ """Luma client."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Any, Optional
6
+
7
+ from runapi.core import ClientOptions, HttpClient, resolve_api_key
8
+
9
+ from .resources.modify_video import ModifyVideo
10
+
11
+
12
+ class LumaClient:
13
+ """Luma modify-video client.
14
+
15
+ Example::
16
+
17
+ client = LumaClient(api_key="sk-...")
18
+ result = client.modify_video.run(
19
+ model="...", prompt="Make it cinematic",
20
+ source_video_url="https://example.com/source.mp4",
21
+ )
22
+ """
23
+
24
+ def __init__(self, api_key: Optional[str] = None, **options: Any) -> None:
25
+ resolved_api_key = resolve_api_key(api_key)
26
+ client_options = ClientOptions(api_key=resolved_api_key, **options)
27
+ http = client_options.http_client or HttpClient(client_options)
28
+ self.modify_video = ModifyVideo(http)
runapi/luma/py.typed ADDED
File without changes
@@ -0,0 +1,3 @@
1
+ from .modify_video import ModifyVideo
2
+
3
+ __all__ = ["ModifyVideo"]
@@ -0,0 +1,39 @@
1
+ """Luma modify-video resource."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Any, Dict
6
+
7
+ from runapi.core import Resource, ValidationError
8
+
9
+ from ..types import CompletedModifyVideoResponse, ModifyVideoResponse
10
+
11
+
12
+ class ModifyVideo(Resource):
13
+ """Modify a source video with Luma."""
14
+
15
+ ENDPOINT = "/api/v1/luma/modify_video"
16
+
17
+ RESPONSE_CLASS = ModifyVideoResponse
18
+ COMPLETED_RESPONSE_CLASS = CompletedModifyVideoResponse
19
+
20
+ def run(self, **params: Any) -> Any:
21
+ """Create a task and poll until it completes."""
22
+ task = self.create(**params)
23
+ return self._poll_until_complete(lambda: self.get(task.id))
24
+
25
+ def create(self, **params: Any) -> Any:
26
+ """Create a modify-video task and return immediately with an ``id``."""
27
+ compacted = self._compact_params(params)
28
+ self._validate_params(compacted)
29
+ return self._request("post", self.ENDPOINT, body=compacted)
30
+
31
+ def get(self, id: str) -> Any:
32
+ """Fetch the current status of a modify-video task."""
33
+ return self._request("get", f"{self.ENDPOINT}/{id}")
34
+
35
+ def _validate_params(self, params: Dict[str, Any]) -> None:
36
+ if not params.get("prompt"):
37
+ raise ValidationError("prompt is required")
38
+ if not params.get("source_video_url"):
39
+ raise ValidationError("source_video_url is required")
runapi/luma/types.py ADDED
@@ -0,0 +1,30 @@
1
+ """Luma response models."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from runapi.core import BaseModel, TaskResponse, optional, required
6
+
7
+
8
+ class Video(BaseModel):
9
+ """A generated or source video reference."""
10
+
11
+ url = optional(str)
12
+
13
+
14
+ class ModifyVideoResponse(TaskResponse):
15
+ """Response for a modify-video task."""
16
+
17
+ id = required(str)
18
+ status = optional(str, enum=lambda: TaskResponse.Status.ALL)
19
+ videos = optional([lambda: Video])
20
+ sources = optional([lambda: Video])
21
+ error = optional(str)
22
+
23
+
24
+ class CompletedModifyVideoResponse(ModifyVideoResponse):
25
+ """Returned by ``modify_video.run()`` once polling observes completion.
26
+
27
+ ``videos`` is required so callers never have to null-check it on success.
28
+ """
29
+
30
+ videos = required([lambda: Video])
@@ -0,0 +1,80 @@
1
+ Metadata-Version: 2.4
2
+ Name: runapi-luma
3
+ Version: 0.1.0
4
+ Summary: Luma modify-video client for RunAPI
5
+ Project-URL: Homepage, https://runapi.ai/models/luma
6
+ Project-URL: Documentation, https://runapi.ai/docs#sdk-luma
7
+ Author-email: RunAPI <contact@runapi.ai>
8
+ License-Expression: Apache-2.0
9
+ Keywords: ai,luma,modify-video,runapi,sdk,video
10
+ Requires-Python: >=3.9
11
+ Requires-Dist: runapi-core
12
+ Description-Content-Type: text/markdown
13
+
14
+ # Luma Python SDK for RunAPI
15
+
16
+ The Luma Python SDK is the language-specific package for Luma on RunAPI. Use it
17
+ for video modification flows when your application needs JSON request bodies,
18
+ task status lookup, and consistent RunAPI errors in Python.
19
+
20
+ For model details, use https://runapi.ai/models/luma; for API reference, use
21
+ https://runapi.ai/docs#luma; for SDK docs, use https://runapi.ai/docs#sdk-luma.
22
+
23
+ ## Install
24
+
25
+ ```bash
26
+ pip install runapi-luma
27
+ ```
28
+
29
+ ## Quick start
30
+
31
+ ```python
32
+ from runapi.luma import LumaClient
33
+
34
+ client = LumaClient() # reads RUNAPI_API_KEY, or pass api_key="sk-..."
35
+
36
+ task = client.modify_video.create(
37
+ model="ray-2-modify-video",
38
+ prompt="Make it cinematic with warm golden tones",
39
+ source_video_url="https://example.com/source.mp4",
40
+ )
41
+ status = client.modify_video.get(task.id)
42
+ ```
43
+
44
+ Use `create` to submit a task and return quickly, `get` to fetch the latest task
45
+ state, and `run` to create and poll until completion:
46
+
47
+ ```python
48
+ result = client.modify_video.run(
49
+ model="ray-2-modify-video",
50
+ prompt="Restyle as a hand-painted animation",
51
+ source_video_url="https://example.com/source.mp4",
52
+ )
53
+ print(result.videos[0].url)
54
+ ```
55
+
56
+ In web request handlers, prefer `create` plus webhook or later `get` polling so a
57
+ worker is not held open.
58
+
59
+ RunAPI-generated file URLs are temporary. Download and store generated videos in
60
+ your own durable storage within 7 days; do not treat returned URLs as long-term
61
+ assets.
62
+
63
+ ## Language notes
64
+
65
+ Pass parameters as keyword arguments and catch the `runapi.luma` error classes
66
+ when building video jobs or scripts. The available resource is `modify_video`.
67
+ Keep `RUNAPI_API_KEY` in the environment or your secret manager; never commit API
68
+ keys or callback secrets.
69
+
70
+ ## Links
71
+
72
+ - Model page: https://runapi.ai/models/luma
73
+ - SDK docs: https://runapi.ai/docs#sdk-luma
74
+ - Product docs: https://runapi.ai/docs#luma
75
+ - Pricing and rate limits: https://runapi.ai/models/luma
76
+ - Full catalog: https://runapi.ai/models
77
+
78
+ ## License
79
+
80
+ Licensed under the Apache License, Version 2.0.
@@ -0,0 +1,9 @@
1
+ runapi/luma/__init__.py,sha256=6x8qZwnaqVp7hzNM60PqbHZU3BblmSdwXA7Tz2w2N-8,454
2
+ runapi/luma/client.py,sha256=jy67J69jzYSBoCD07DgxGRnlto1SFD0CRCexuhZ8Vbk,823
3
+ runapi/luma/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
+ runapi/luma/types.py,sha256=H2m_mwutA4tK42tJ6Y3GWWosz1RBaUiD5Cmp4ww-AVI,776
5
+ runapi/luma/resources/__init__.py,sha256=UZ1c3c-jx_4xvQORC5SJ-jhXmKi4pQN9RrK0_bKSjNs,65
6
+ runapi/luma/resources/modify_video.py,sha256=YFG00ej5peIwbZOagLAEuC21V4mrUgamRuhslN8NI28,1360
7
+ runapi_luma-0.1.0.dist-info/METADATA,sha256=-3T-jpM_lhZSQXN6c6n2yle_5cwTX6QseWnZ6pYl5yA,2458
8
+ runapi_luma-0.1.0.dist-info/WHEEL,sha256=mffPy8wBnZQn2VnJUU5jE99KsxaSfiyMHV9Yt0aLVxs,87
9
+ runapi_luma-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.30.1
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any