ads_dev 1.0.0__tar.gz → 1.1.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.
- {ads_dev-1.0.0 → ads_dev-1.1.0}/PKG-INFO +3 -2
- {ads_dev-1.0.0 → ads_dev-1.1.0}/README.md +2 -1
- {ads_dev-1.0.0 → ads_dev-1.1.0}/pyproject.toml +1 -1
- {ads_dev-1.0.0 → ads_dev-1.1.0}/pyproject.toml.orig +1 -1
- {ads_dev-1.0.0 → ads_dev-1.1.0}/src/ads_dev/_async/client.py +3 -2
- {ads_dev-1.0.0 → ads_dev-1.1.0}/src/ads_dev/_core.py +32 -16
- {ads_dev-1.0.0 → ads_dev-1.1.0}/src/ads_dev/_sync/client.py +3 -2
- {ads_dev-1.0.0 → ads_dev-1.1.0}/src/ads_dev/types.py +40 -37
- {ads_dev-1.0.0 → ads_dev-1.1.0}/LICENSE +0 -0
- {ads_dev-1.0.0 → ads_dev-1.1.0}/src/ads_dev/__init__.py +0 -0
- {ads_dev-1.0.0 → ads_dev-1.1.0}/src/ads_dev/py.typed +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ads_dev
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.1.0
|
|
4
4
|
Summary: The ads.dev API for Python: image, video and audio generation on your brand, the brand kit and library, and competitor ads
|
|
5
5
|
Keywords: ads.dev,sandstorm,ads,image generation,video generation,ai,api
|
|
6
6
|
License-Expression: MIT
|
|
@@ -153,6 +153,7 @@ uv sync
|
|
|
153
153
|
uv run pytest
|
|
154
154
|
uv run python scripts/generate.py
|
|
155
155
|
uv build
|
|
156
|
+
uv run python scripts/aliases.py
|
|
156
157
|
```
|
|
157
158
|
|
|
158
|
-
`ads_dev/types.py` is generated from `../sdk/openapi.json`, the API's own document, and `ads_dev/_sync/client.py` from the async client with `unasync`; `scripts/generate.py` writes both, and the tests fail when either is stale. Build with uv 0.13 or newer.
|
|
159
|
+
`ads_dev/types.py` is generated from `../sdk/openapi.json`, the API's own document, and `ads_dev/_sync/client.py` from the async client with `unasync`; `scripts/generate.py` writes both, and the tests fail when either is stale. `scripts/aliases.py` builds `adsdotdev` and `sandstormapp`, which install `ads_dev` under those names, into `dist/` beside it, so `uv publish` uploads all three. Build with uv 0.13 or newer.
|
|
@@ -134,6 +134,7 @@ uv sync
|
|
|
134
134
|
uv run pytest
|
|
135
135
|
uv run python scripts/generate.py
|
|
136
136
|
uv build
|
|
137
|
+
uv run python scripts/aliases.py
|
|
137
138
|
```
|
|
138
139
|
|
|
139
|
-
`ads_dev/types.py` is generated from `../sdk/openapi.json`, the API's own document, and `ads_dev/_sync/client.py` from the async client with `unasync`; `scripts/generate.py` writes both, and the tests fail when either is stale. Build with uv 0.13 or newer.
|
|
140
|
+
`ads_dev/types.py` is generated from `../sdk/openapi.json`, the API's own document, and `ads_dev/_sync/client.py` from the async client with `unasync`; `scripts/generate.py` writes both, and the tests fail when either is stale. `scripts/aliases.py` builds `adsdotdev` and `sandstormapp`, which install `ads_dev` under those names, into `dist/` beside it, so `uv publish` uploads all three. Build with uv 0.13 or newer.
|
|
@@ -15,6 +15,7 @@ from .._core import (
|
|
|
15
15
|
RETRYABLE,
|
|
16
16
|
RUN_TIMEOUT_S,
|
|
17
17
|
GenerationFailed,
|
|
18
|
+
answer_of,
|
|
18
19
|
delay_of,
|
|
19
20
|
headers_of,
|
|
20
21
|
is_finished,
|
|
@@ -328,8 +329,8 @@ class AsyncSandstorm:
|
|
|
328
329
|
attempt += 1
|
|
329
330
|
continue
|
|
330
331
|
if response.is_success:
|
|
331
|
-
return shape.model_validate(response.
|
|
332
|
+
return shape.model_validate(answer_of(response, self._base_url))
|
|
332
333
|
if response.status_code not in RETRYABLE or attempt >= self._max_retries:
|
|
333
|
-
raise refusal_of(response)
|
|
334
|
+
raise refusal_of(response, self._base_url)
|
|
334
335
|
await anyio.sleep(delay_of(attempt, response))
|
|
335
336
|
attempt += 1
|
|
@@ -24,12 +24,6 @@ RETRYABLE = frozenset({408, 429, 500, 502, 503, 504})
|
|
|
24
24
|
|
|
25
25
|
FINISHED = frozenset({"succeeded", "failed", "canceled"})
|
|
26
26
|
|
|
27
|
-
MISSING_KEY = (
|
|
28
|
-
"Pass api_key or set SANDSTORM_API_KEY. To make a key: "
|
|
29
|
-
"curl -fsSL https://ads.dev/login.mjs -o sandstorm-login.mjs && node sandstorm-login.mjs"
|
|
30
|
-
)
|
|
31
|
-
|
|
32
|
-
|
|
33
27
|
class SandstormError(Exception):
|
|
34
28
|
def __init__(self, status: int, refusal: Mapping[str, Any]) -> None:
|
|
35
29
|
super().__init__(refusal.get("message", ""))
|
|
@@ -51,10 +45,14 @@ def is_finished(generation: Generation) -> bool:
|
|
|
51
45
|
|
|
52
46
|
|
|
53
47
|
def settings(api_key: str | None, base_url: str | None) -> tuple[str, str]:
|
|
48
|
+
url = (base_url or os.environ.get("SANDSTORM_API_URL") or BASE_URL).rstrip("/")
|
|
54
49
|
key = api_key or os.environ.get("SANDSTORM_API_KEY")
|
|
55
50
|
if not key:
|
|
56
|
-
raise ValueError(
|
|
57
|
-
|
|
51
|
+
raise ValueError(
|
|
52
|
+
"Pass api_key or set SANDSTORM_API_KEY. To make a key: "
|
|
53
|
+
f"curl -fsSL {url}/login.mjs -o sandstorm-login.mjs && node sandstorm-login.mjs"
|
|
54
|
+
)
|
|
55
|
+
return key, url
|
|
58
56
|
|
|
59
57
|
|
|
60
58
|
def headers_of(api_key: str, brand: str | None) -> dict[str, str]:
|
|
@@ -65,14 +63,32 @@ def query_of(params: Mapping[str, Any]) -> dict[str, str]:
|
|
|
65
63
|
return {name: ("true" if value is True else "false" if value is False else str(value)) for name, value in params.items() if value is not None}
|
|
66
64
|
|
|
67
65
|
|
|
68
|
-
def
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
66
|
+
def is_json(response: httpx.Response) -> bool:
|
|
67
|
+
return "json" in response.headers.get("content-type", "")
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def not_the_api(response: httpx.Response, base_url: str) -> SandstormError:
|
|
71
|
+
kind = response.headers.get("content-type", "no content type")
|
|
72
|
+
return SandstormError(
|
|
73
|
+
response.status_code,
|
|
74
|
+
{
|
|
75
|
+
"code": "not_the_api",
|
|
76
|
+
"message": f"{base_url} answered {response.status_code} with {kind} instead of the API's JSON. "
|
|
77
|
+
f"If {base_url} is not the Sandstorm API, pass base_url or set SANDSTORM_API_URL.",
|
|
78
|
+
},
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def answer_of(response: httpx.Response, base_url: str) -> Any:
|
|
83
|
+
if not is_json(response):
|
|
84
|
+
raise not_the_api(response, base_url)
|
|
85
|
+
return response.json()
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def refusal_of(response: httpx.Response, base_url: str) -> SandstormError:
|
|
89
|
+
if not is_json(response):
|
|
90
|
+
return not_the_api(response, base_url)
|
|
91
|
+
return SandstormError(response.status_code, response.json()["error"])
|
|
76
92
|
|
|
77
93
|
|
|
78
94
|
def delay_of(attempt: int, response: httpx.Response | None) -> float:
|
|
@@ -15,6 +15,7 @@ from .._core import (
|
|
|
15
15
|
RETRYABLE,
|
|
16
16
|
RUN_TIMEOUT_S,
|
|
17
17
|
GenerationFailed,
|
|
18
|
+
answer_of,
|
|
18
19
|
delay_of,
|
|
19
20
|
headers_of,
|
|
20
21
|
is_finished,
|
|
@@ -328,8 +329,8 @@ class Sandstorm:
|
|
|
328
329
|
attempt += 1
|
|
329
330
|
continue
|
|
330
331
|
if response.is_success:
|
|
331
|
-
return shape.model_validate(response.
|
|
332
|
+
return shape.model_validate(answer_of(response, self._base_url))
|
|
332
333
|
if response.status_code not in RETRYABLE or attempt >= self._max_retries:
|
|
333
|
-
raise refusal_of(response)
|
|
334
|
+
raise refusal_of(response, self._base_url)
|
|
334
335
|
time.sleep(delay_of(attempt, response))
|
|
335
336
|
attempt += 1
|
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
from __future__ import annotations
|
|
5
5
|
|
|
6
6
|
from typing import Any, Literal
|
|
7
|
-
from uuid import UUID
|
|
8
7
|
|
|
9
8
|
from pydantic import (
|
|
10
9
|
AnyUrl,
|
|
@@ -54,7 +53,7 @@ class CreateNanoBananaPro(BaseModel):
|
|
|
54
53
|
class CreateNanoBananaProEditInput(BaseModel):
|
|
55
54
|
prompt: constr(min_length=3, max_length=50000) = Field(
|
|
56
55
|
...,
|
|
57
|
-
description="The change to make, or how the images come together,
|
|
56
|
+
description="The change to make, or how the images come together, citing each image by its place in images as @image1, @image2.",
|
|
58
57
|
)
|
|
59
58
|
aspect_ratio: (
|
|
60
59
|
Literal[
|
|
@@ -80,7 +79,7 @@ class CreateNanoBananaProEditInput(BaseModel):
|
|
|
80
79
|
)
|
|
81
80
|
images: list[str] = Field(
|
|
82
81
|
...,
|
|
83
|
-
description="The 1 to 14 images to edit or combine, in the order the prompt
|
|
82
|
+
description="The 1 to 14 images to edit or combine, in the order the prompt cites them, each an asset id (asset_…) or an https URL.",
|
|
84
83
|
max_length=14,
|
|
85
84
|
min_length=1,
|
|
86
85
|
)
|
|
@@ -157,7 +156,7 @@ class CreateNanoBanana2(BaseModel):
|
|
|
157
156
|
class CreateNanoBanana2EditInput(BaseModel):
|
|
158
157
|
prompt: constr(min_length=3, max_length=50000) = Field(
|
|
159
158
|
...,
|
|
160
|
-
description="The change to make, or how the images come together,
|
|
159
|
+
description="The change to make, or how the images come together, citing each image by its place in images as @image1, @image2.",
|
|
161
160
|
)
|
|
162
161
|
aspect_ratio: (
|
|
163
162
|
Literal[
|
|
@@ -187,7 +186,7 @@ class CreateNanoBanana2EditInput(BaseModel):
|
|
|
187
186
|
)
|
|
188
187
|
images: list[str] = Field(
|
|
189
188
|
...,
|
|
190
|
-
description="The 1 to 14 images to edit or combine, in the order the prompt
|
|
189
|
+
description="The 1 to 14 images to edit or combine, in the order the prompt cites them, each an asset id (asset_…) or an https URL.",
|
|
191
190
|
max_length=14,
|
|
192
191
|
min_length=1,
|
|
193
192
|
)
|
|
@@ -261,7 +260,7 @@ class CreateNanoBanana2Lite(BaseModel):
|
|
|
261
260
|
class CreateNanoBanana2LiteEditInput(BaseModel):
|
|
262
261
|
prompt: constr(min_length=3, max_length=50000) = Field(
|
|
263
262
|
...,
|
|
264
|
-
description="The change to make, or how the images come together,
|
|
263
|
+
description="The change to make, or how the images come together, citing each image by its place in images as @image1, @image2.",
|
|
265
264
|
)
|
|
266
265
|
aspect_ratio: (
|
|
267
266
|
Literal[
|
|
@@ -288,7 +287,7 @@ class CreateNanoBanana2LiteEditInput(BaseModel):
|
|
|
288
287
|
)
|
|
289
288
|
images: list[str] = Field(
|
|
290
289
|
...,
|
|
291
|
-
description="The 1 to 14 images to edit or combine, in the order the prompt
|
|
290
|
+
description="The 1 to 14 images to edit or combine, in the order the prompt cites them, each an asset id (asset_…) or an https URL.",
|
|
292
291
|
max_length=14,
|
|
293
292
|
min_length=1,
|
|
294
293
|
)
|
|
@@ -363,7 +362,7 @@ class CreateGptImage25Flare(BaseModel):
|
|
|
363
362
|
class CreateGptImage25FlareEditInput(BaseModel):
|
|
364
363
|
prompt: constr(min_length=1, max_length=32000) = Field(
|
|
365
364
|
...,
|
|
366
|
-
description="The change to make, or how the images come together,
|
|
365
|
+
description="The change to make, or how the images come together, citing each image by its place in images as @image1, @image2 and writing out exactly any words the image must show.",
|
|
367
366
|
)
|
|
368
367
|
aspect_ratio: (
|
|
369
368
|
Literal[
|
|
@@ -403,7 +402,7 @@ class CreateGptImage25FlareEditInput(BaseModel):
|
|
|
403
402
|
)
|
|
404
403
|
images: list[str] = Field(
|
|
405
404
|
...,
|
|
406
|
-
description="The 1 to 16 images to edit or combine, in the order the prompt
|
|
405
|
+
description="The 1 to 16 images to edit or combine, in the order the prompt cites them, each an asset id (asset_…) or an https URL.",
|
|
407
406
|
max_length=16,
|
|
408
407
|
min_length=1,
|
|
409
408
|
)
|
|
@@ -478,7 +477,7 @@ class CreateGptImage25Sunburst(BaseModel):
|
|
|
478
477
|
class CreateGptImage25SunburstEditInput(BaseModel):
|
|
479
478
|
prompt: constr(min_length=1, max_length=32000) = Field(
|
|
480
479
|
...,
|
|
481
|
-
description="The change to make, or how the images come together,
|
|
480
|
+
description="The change to make, or how the images come together, citing each image by its place in images as @image1, @image2 and writing out exactly any words the image must show.",
|
|
482
481
|
)
|
|
483
482
|
aspect_ratio: (
|
|
484
483
|
Literal[
|
|
@@ -518,7 +517,7 @@ class CreateGptImage25SunburstEditInput(BaseModel):
|
|
|
518
517
|
)
|
|
519
518
|
images: list[str] = Field(
|
|
520
519
|
...,
|
|
521
|
-
description="The 1 to 16 images to edit or combine, in the order the prompt
|
|
520
|
+
description="The 1 to 16 images to edit or combine, in the order the prompt cites them, each an asset id (asset_…) or an https URL.",
|
|
522
521
|
max_length=16,
|
|
523
522
|
min_length=1,
|
|
524
523
|
)
|
|
@@ -581,7 +580,7 @@ class CreateSeedream5Pro(BaseModel):
|
|
|
581
580
|
class CreateSeedream5ProEditInput(BaseModel):
|
|
582
581
|
prompt: constr(min_length=3) = Field(
|
|
583
582
|
...,
|
|
584
|
-
description="The change to make as one paragraph, at most 600 words,
|
|
583
|
+
description="The change to make as one paragraph, at most 600 words, citing each image by its place in images as @image1, @image2, with the exact words the result must show written out.",
|
|
585
584
|
)
|
|
586
585
|
aspect_ratio: (
|
|
587
586
|
Literal[
|
|
@@ -608,7 +607,7 @@ class CreateSeedream5ProEditInput(BaseModel):
|
|
|
608
607
|
)
|
|
609
608
|
images: list[str] = Field(
|
|
610
609
|
...,
|
|
611
|
-
description="The images to edit or combine, in the order the prompt
|
|
610
|
+
description="The images to edit or combine, in the order the prompt cites them, at most 10, each an asset id (asset_…) or an https URL.",
|
|
612
611
|
max_length=10,
|
|
613
612
|
min_length=1,
|
|
614
613
|
)
|
|
@@ -664,7 +663,7 @@ class CreateSeedream5Lite(BaseModel):
|
|
|
664
663
|
class CreateSeedream5LiteEditInput(BaseModel):
|
|
665
664
|
prompt: constr(min_length=3) = Field(
|
|
666
665
|
...,
|
|
667
|
-
description="The change to make as one paragraph, at most 600 words,
|
|
666
|
+
description="The change to make as one paragraph, at most 600 words, citing each image by its place in images as @image1, @image2, with the exact words the result must show written out.",
|
|
668
667
|
)
|
|
669
668
|
aspect_ratio: (
|
|
670
669
|
Literal[
|
|
@@ -688,7 +687,7 @@ class CreateSeedream5LiteEditInput(BaseModel):
|
|
|
688
687
|
)
|
|
689
688
|
images: list[str] = Field(
|
|
690
689
|
...,
|
|
691
|
-
description="The images to edit or combine, in the order the prompt
|
|
690
|
+
description="The images to edit or combine, in the order the prompt cites them, at most 14, each an asset id (asset_…) or an https URL.",
|
|
692
691
|
max_length=14,
|
|
693
692
|
min_length=1,
|
|
694
693
|
)
|
|
@@ -898,7 +897,7 @@ class CreateSeedance25ImageToVideo(BaseModel):
|
|
|
898
897
|
class CreateSeedance25ReferenceToVideoInput(BaseModel):
|
|
899
898
|
prompt: constr(min_length=3, max_length=50000) = Field(
|
|
900
899
|
...,
|
|
901
|
-
description="What happens in the clip, citing each image, video or audio by its place in its list as @
|
|
900
|
+
description="What happens in the clip, citing each image, video or audio by its place in its list as @image1, @video1 or @audio1.",
|
|
902
901
|
)
|
|
903
902
|
task: Literal["auto", "reference", "editing", "extension"] | None = Field(
|
|
904
903
|
"auto",
|
|
@@ -911,12 +910,12 @@ class CreateSeedance25ReferenceToVideoInput(BaseModel):
|
|
|
911
910
|
)
|
|
912
911
|
videos: list[str] | None = Field(
|
|
913
912
|
[],
|
|
914
|
-
description="Up to 10 videos,
|
|
913
|
+
description="Up to 10 videos, each an asset id (asset_…) or an https URL; none when left out. Past 30 seconds together the longer ones are cut to their opening seconds, and beside audio their own sound is left out; editing and extension take them whole, so those must run 30 seconds or less together.",
|
|
915
914
|
max_length=10,
|
|
916
915
|
)
|
|
917
916
|
audio: list[str] | None = Field(
|
|
918
917
|
[],
|
|
919
|
-
description="Up to 10
|
|
918
|
+
description="Up to 10 audio files, each an asset id (asset_…) or an https URL; none when left out. Past 30 seconds together the longer ones are cut to their opening seconds.",
|
|
920
919
|
max_length=10,
|
|
921
920
|
)
|
|
922
921
|
aspect_ratio: (
|
|
@@ -1095,7 +1094,7 @@ class CreateKlingO3ProReferenceToVideoInputElements1(BaseModel):
|
|
|
1095
1094
|
)
|
|
1096
1095
|
video: str = Field(
|
|
1097
1096
|
...,
|
|
1098
|
-
description="A clip of the character or object
|
|
1097
|
+
description="A clip of the character or object of at least 3 seconds, as an asset id (asset_…) or an https URL, in place of images; past 10 seconds it is cut to its opening 10, and outside 720 to 2160 px a side it is resized to fit.",
|
|
1099
1098
|
)
|
|
1100
1099
|
|
|
1101
1100
|
|
|
@@ -1121,7 +1120,7 @@ class CreateKlingO3ProReferenceToVideoInput(BaseModel):
|
|
|
1121
1120
|
)
|
|
1122
1121
|
images: list[str] | None = Field(
|
|
1123
1122
|
[],
|
|
1124
|
-
description="Up to 4 images whose subject or look the clip keeps, each an asset id (asset_…) or an https URL, cited in the prompt as @
|
|
1123
|
+
description="Up to 4 images whose subject or look the clip keeps, each an asset id (asset_…) or an https URL, cited in the prompt as @image1, @image2 in this order; none when left out.",
|
|
1125
1124
|
max_length=4,
|
|
1126
1125
|
)
|
|
1127
1126
|
elements: (
|
|
@@ -1129,7 +1128,7 @@ class CreateKlingO3ProReferenceToVideoInput(BaseModel):
|
|
|
1129
1128
|
CreateKlingO3ProReferenceToVideoInputElements | CreateKlingO3ProReferenceToVideoInputElements1
|
|
1130
1129
|
]
|
|
1131
1130
|
| None
|
|
1132
|
-
) = Field([], description="Characters or objects held to one look across the clip, cited in the prompt as @
|
|
1131
|
+
) = Field([], description="Characters or objects held to one look across the clip, cited in the prompt as @element1, @element2 in this order; images and elements take 4 together at most, and none when left out.", max_length=4, validate_default=True)
|
|
1133
1132
|
aspect_ratio: Literal["16:9", "9:16", "1:1"] | None = Field(
|
|
1134
1133
|
"16:9", description="Shape of the clip as width:height; 16:9 when left out."
|
|
1135
1134
|
)
|
|
@@ -1242,7 +1241,7 @@ class CreateGeminiOmniFlashImageToVideo(BaseModel):
|
|
|
1242
1241
|
class CreateGeminiOmniFlashReferenceToVideoInput(BaseModel):
|
|
1243
1242
|
prompt: constr(min_length=3, max_length=20000) = Field(
|
|
1244
1243
|
...,
|
|
1245
|
-
description="What happens in the clip, citing each image or video
|
|
1244
|
+
description="What happens in the clip, citing each image or video by its place in its list as @image1 or @video1, with any spoken line in double quotes.",
|
|
1246
1245
|
)
|
|
1247
1246
|
images: list[str] | None = Field(
|
|
1248
1247
|
[],
|
|
@@ -1251,7 +1250,7 @@ class CreateGeminiOmniFlashReferenceToVideoInput(BaseModel):
|
|
|
1251
1250
|
)
|
|
1252
1251
|
videos: list[str] | None = Field(
|
|
1253
1252
|
[],
|
|
1254
|
-
description="Up to 3 videos
|
|
1253
|
+
description="Up to 3 videos for a likeness or a motion to copy, whose sound is ignored, each an asset id (asset_…) or an https URL and cut to its opening 3 seconds when longer; none when left out.",
|
|
1255
1254
|
max_length=3,
|
|
1256
1255
|
)
|
|
1257
1256
|
aspect_ratio: Literal["9:16", "16:9"] | None = Field(
|
|
@@ -1575,8 +1574,8 @@ class GenerationOutputItem(BaseModel):
|
|
|
1575
1574
|
name: str | None
|
|
1576
1575
|
url: str
|
|
1577
1576
|
content_type: str
|
|
1578
|
-
width:
|
|
1579
|
-
height:
|
|
1577
|
+
width: int | None = None
|
|
1578
|
+
height: int | None = None
|
|
1580
1579
|
duration: float | None = None
|
|
1581
1580
|
role: Literal["main", "last_frame", "layer"]
|
|
1582
1581
|
layer: GenerationOutputItemLayer | None = None
|
|
@@ -1619,7 +1618,11 @@ class ModelPricingRate(BaseModel):
|
|
|
1619
1618
|
usd: float
|
|
1620
1619
|
when: dict[str, Any] = Field(
|
|
1621
1620
|
...,
|
|
1622
|
-
description="The input
|
|
1621
|
+
description="The inputs, by their names in input, that this rate applies to; a media input is true when given and false when not; empty when it applies to all. A rate charged on the input itself carries `input`: the tokens of text or image, or true for an input file it charges for",
|
|
1622
|
+
)
|
|
1623
|
+
default: bool = Field(
|
|
1624
|
+
...,
|
|
1625
|
+
description="Whether a generation that leaves these inputs at their defaults pays this rate",
|
|
1623
1626
|
)
|
|
1624
1627
|
|
|
1625
1628
|
|
|
@@ -1674,8 +1677,8 @@ class LibraryAsset(BaseModel):
|
|
|
1674
1677
|
name: str | None
|
|
1675
1678
|
url: str | None
|
|
1676
1679
|
content_type: str | None
|
|
1677
|
-
width:
|
|
1678
|
-
height:
|
|
1680
|
+
width: int | None = None
|
|
1681
|
+
height: int | None = None
|
|
1679
1682
|
duration: float | None = None
|
|
1680
1683
|
caption: str | None = Field(
|
|
1681
1684
|
..., description="What the image shows, when it has been described"
|
|
@@ -1694,8 +1697,8 @@ class Asset(BaseModel):
|
|
|
1694
1697
|
name: str | None
|
|
1695
1698
|
url: str | None
|
|
1696
1699
|
content_type: str | None
|
|
1697
|
-
width:
|
|
1698
|
-
height:
|
|
1700
|
+
width: int | None = None
|
|
1701
|
+
height: int | None = None
|
|
1699
1702
|
duration: float | None = None
|
|
1700
1703
|
|
|
1701
1704
|
|
|
@@ -1751,14 +1754,14 @@ class BrandLogo(BaseModel):
|
|
|
1751
1754
|
description="icon for a small mark, light for dark backgrounds, dark for light ones",
|
|
1752
1755
|
)
|
|
1753
1756
|
format: str | None
|
|
1754
|
-
width:
|
|
1755
|
-
height:
|
|
1757
|
+
width: int | None
|
|
1758
|
+
height: int | None
|
|
1756
1759
|
url: str | None
|
|
1757
1760
|
|
|
1758
1761
|
|
|
1759
1762
|
class Brand(BaseModel):
|
|
1760
1763
|
object: Literal["brand"]
|
|
1761
|
-
id:
|
|
1764
|
+
id: str = Field(
|
|
1762
1765
|
...,
|
|
1763
1766
|
description="Send it as `Sandstorm-Brand` to work on this brand with a key made on another",
|
|
1764
1767
|
)
|
|
@@ -1797,8 +1800,8 @@ class OfferSummary(BaseModel):
|
|
|
1797
1800
|
class OfferVariantPhoto(BaseModel):
|
|
1798
1801
|
id: str = Field(..., description="An asset id, usable as a media input")
|
|
1799
1802
|
url: str | None
|
|
1800
|
-
width:
|
|
1801
|
-
height:
|
|
1803
|
+
width: int | None
|
|
1804
|
+
height: int | None
|
|
1802
1805
|
orientation: str | None
|
|
1803
1806
|
shot_type: str | None
|
|
1804
1807
|
caption: str | None
|
|
@@ -1819,8 +1822,8 @@ class OfferVariant(BaseModel):
|
|
|
1819
1822
|
class OfferPhoto(BaseModel):
|
|
1820
1823
|
id: str = Field(..., description="An asset id, usable as a media input")
|
|
1821
1824
|
url: str | None
|
|
1822
|
-
width:
|
|
1823
|
-
height:
|
|
1825
|
+
width: int | None
|
|
1826
|
+
height: int | None
|
|
1824
1827
|
orientation: str | None
|
|
1825
1828
|
shot_type: str | None
|
|
1826
1829
|
caption: str | None
|
|
File without changes
|
|
File without changes
|
|
File without changes
|