runapi-core 0.8.2__tar.gz → 0.9.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.
- {runapi_core-0.8.2 → runapi_core-0.9.0}/PKG-INFO +3 -3
- {runapi_core-0.8.2 → runapi_core-0.9.0}/README.md +1 -1
- {runapi_core-0.8.2 → runapi_core-0.9.0}/pyproject.toml +1 -1
- {runapi_core-0.8.2 → runapi_core-0.9.0}/src/runapi/core/__init__.py +2 -8
- {runapi_core-0.8.2 → runapi_core-0.9.0}/src/runapi/core/contract_gen.py +218 -10
- {runapi_core-0.8.2 → runapi_core-0.9.0}/src/runapi/core/models.py +8 -20
- runapi_core-0.9.0/src/runapi/core/version.py +1 -0
- {runapi_core-0.8.2 → runapi_core-0.9.0}/tests/test_models.py +29 -12
- {runapi_core-0.8.2 → runapi_core-0.9.0}/tests/test_resource.py +17 -33
- runapi_core-0.8.2/src/runapi/core/version.py +0 -1
- {runapi_core-0.8.2 → runapi_core-0.9.0}/src/runapi/core/account.py +0 -0
- {runapi_core-0.8.2 → runapi_core-0.9.0}/src/runapi/core/auth.py +0 -0
- {runapi_core-0.8.2 → runapi_core-0.9.0}/src/runapi/core/config.py +0 -0
- {runapi_core-0.8.2 → runapi_core-0.9.0}/src/runapi/core/constants.py +0 -0
- {runapi_core-0.8.2 → runapi_core-0.9.0}/src/runapi/core/errors.py +0 -0
- {runapi_core-0.8.2 → runapi_core-0.9.0}/src/runapi/core/files.py +0 -0
- {runapi_core-0.8.2 → runapi_core-0.9.0}/src/runapi/core/http_client.py +0 -0
- {runapi_core-0.8.2 → runapi_core-0.9.0}/src/runapi/core/multipart.py +0 -0
- {runapi_core-0.8.2 → runapi_core-0.9.0}/src/runapi/core/options.py +0 -0
- {runapi_core-0.8.2 → runapi_core-0.9.0}/src/runapi/core/polling.py +0 -0
- {runapi_core-0.8.2 → runapi_core-0.9.0}/src/runapi/core/pricing.py +0 -0
- {runapi_core-0.8.2 → runapi_core-0.9.0}/src/runapi/core/provider_client.py +0 -0
- {runapi_core-0.8.2 → runapi_core-0.9.0}/src/runapi/core/py.typed +0 -0
- {runapi_core-0.8.2 → runapi_core-0.9.0}/src/runapi/core/resource.py +0 -0
- {runapi_core-0.8.2 → runapi_core-0.9.0}/src/runapi/core/response.py +0 -0
- {runapi_core-0.8.2 → runapi_core-0.9.0}/src/runapi/core/uploads.py +0 -0
- {runapi_core-0.8.2 → runapi_core-0.9.0}/tests/test_account.py +0 -0
- {runapi_core-0.8.2 → runapi_core-0.9.0}/tests/test_auth.py +0 -0
- {runapi_core-0.8.2 → runapi_core-0.9.0}/tests/test_config.py +0 -0
- {runapi_core-0.8.2 → runapi_core-0.9.0}/tests/test_errors.py +0 -0
- {runapi_core-0.8.2 → runapi_core-0.9.0}/tests/test_files.py +0 -0
- {runapi_core-0.8.2 → runapi_core-0.9.0}/tests/test_http_client.py +0 -0
- {runapi_core-0.8.2 → runapi_core-0.9.0}/tests/test_polling.py +0 -0
- {runapi_core-0.8.2 → runapi_core-0.9.0}/tests/test_pricing.py +0 -0
- {runapi_core-0.8.2 → runapi_core-0.9.0}/tests/test_uploads.py +0 -0
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: runapi-core
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.9.0
|
|
4
4
|
Summary: RunAPI core SDK for JavaScript, Python, Ruby, Go, Java, and PHP
|
|
5
5
|
Project-URL: Homepage, https://runapi.ai/models
|
|
6
6
|
Project-URL: Documentation, https://runapi.ai/docs/resources/sdks
|
|
7
7
|
Project-URL: Source, https://github.com/runapi-ai/core-sdk
|
|
8
8
|
Project-URL: Issues, https://github.com/runapi-ai/core-sdk/issues
|
|
9
9
|
Project-URL: Changelog, https://github.com/runapi-ai/core-sdk/blob/main/CHANGELOG.md
|
|
10
|
-
Project-URL: Release Notes, https://github.com/runapi-ai/core-sdk/releases/tag/python%2Fv0.
|
|
10
|
+
Project-URL: Release Notes, https://github.com/runapi-ai/core-sdk/releases/tag/python%2Fv0.9.0
|
|
11
11
|
Author-email: RunAPI <contact@runapi.ai>
|
|
12
12
|
License-Expression: Apache-2.0
|
|
13
13
|
Keywords: api,core,golang,gradle,java,maven,pypi,python,ruby,runapi,runapi-ai,sdk,typescript
|
|
@@ -134,7 +134,7 @@ quote = client.pricing.create_quote(
|
|
|
134
134
|
)
|
|
135
135
|
```
|
|
136
136
|
|
|
137
|
-
Task
|
|
137
|
+
Completed Task query and webhook envelopes expose `usage.cost` as a float USD amount for that Task. Create, processing, and failed envelopes omit `usage`. The value is the recorded settlement for that Task and is never recalculated from the current price schedule.
|
|
138
138
|
|
|
139
139
|
## License
|
|
140
140
|
|
|
@@ -117,7 +117,7 @@ quote = client.pricing.create_quote(
|
|
|
117
117
|
)
|
|
118
118
|
```
|
|
119
119
|
|
|
120
|
-
Task
|
|
120
|
+
Completed Task query and webhook envelopes expose `usage.cost` as a float USD amount for that Task. Create, processing, and failed envelopes omit `usage`. The value is the recorded settlement for that Task and is never recalculated from the current price schedule.
|
|
121
121
|
|
|
122
122
|
## License
|
|
123
123
|
|
|
@@ -19,7 +19,7 @@ Documentation = "https://runapi.ai/docs/resources/sdks"
|
|
|
19
19
|
Source = "https://github.com/runapi-ai/core-sdk"
|
|
20
20
|
Issues = "https://github.com/runapi-ai/core-sdk/issues"
|
|
21
21
|
Changelog = "https://github.com/runapi-ai/core-sdk/blob/main/CHANGELOG.md"
|
|
22
|
-
"Release Notes" = "https://github.com/runapi-ai/core-sdk/releases/tag/python%2Fv0.
|
|
22
|
+
"Release Notes" = "https://github.com/runapi-ai/core-sdk/releases/tag/python%2Fv0.9.0"
|
|
23
23
|
|
|
24
24
|
[tool.hatch.version]
|
|
25
25
|
path = "src/runapi/core/version.py"
|
|
@@ -29,14 +29,11 @@ from .files import DeletedFile, FileList, FileObject, FilesClient, UploadRespons
|
|
|
29
29
|
from .http_client import HttpClient
|
|
30
30
|
from .models import (
|
|
31
31
|
BaseModel,
|
|
32
|
-
BillingRefund,
|
|
33
|
-
BillingReservation,
|
|
34
|
-
BillingSettlement,
|
|
35
32
|
DynamicModel,
|
|
36
|
-
TaskBillingFacts,
|
|
37
33
|
TaskResult,
|
|
38
34
|
TaskResultResponse,
|
|
39
35
|
TaskResponse,
|
|
36
|
+
TaskUsage,
|
|
40
37
|
optional,
|
|
41
38
|
required,
|
|
42
39
|
)
|
|
@@ -86,10 +83,7 @@ __all__ = [
|
|
|
86
83
|
"TaskResponse",
|
|
87
84
|
"TaskResult",
|
|
88
85
|
"TaskResultResponse",
|
|
89
|
-
"
|
|
90
|
-
"BillingSettlement",
|
|
91
|
-
"BillingRefund",
|
|
92
|
-
"TaskBillingFacts",
|
|
86
|
+
"TaskUsage",
|
|
93
87
|
"required",
|
|
94
88
|
"optional",
|
|
95
89
|
"MultipartBody",
|
|
@@ -1686,6 +1686,12 @@ CONTRACT = {
|
|
|
1686
1686
|
}
|
|
1687
1687
|
}
|
|
1688
1688
|
},
|
|
1689
|
+
"suno/audio-exports": {
|
|
1690
|
+
"models": [],
|
|
1691
|
+
"fields_by_model": {
|
|
1692
|
+
"_": {}
|
|
1693
|
+
}
|
|
1694
|
+
},
|
|
1689
1695
|
"suno/blend-lyrics": {
|
|
1690
1696
|
"models": [],
|
|
1691
1697
|
"fields_by_model": {
|
|
@@ -1711,7 +1717,7 @@ CONTRACT = {
|
|
|
1711
1717
|
}
|
|
1712
1718
|
},
|
|
1713
1719
|
"suno/cover-audio": {
|
|
1714
|
-
"models": ["suno-v4", "suno-v4.5", "suno-v4.5-all", "suno-v4.5-plus", "suno-v5", "suno-v5.5"],
|
|
1720
|
+
"models": ["suno-v4", "suno-v4.5", "suno-v4.5-all", "suno-v4.5-plus", "suno-v5", "suno-v5.5", "suno-v6", "suno-v6-mini", "suno-v6-wild"],
|
|
1715
1721
|
"fields_by_model": {
|
|
1716
1722
|
"suno-v4": {
|
|
1717
1723
|
"persona_type": {
|
|
@@ -1778,11 +1784,44 @@ CONTRACT = {
|
|
|
1778
1784
|
"vocal_mode": {
|
|
1779
1785
|
"enum": ["auto_lyrics", "exact_lyrics", "instrumental"]
|
|
1780
1786
|
}
|
|
1787
|
+
},
|
|
1788
|
+
"suno-v6": {
|
|
1789
|
+
"persona_type": {
|
|
1790
|
+
"enum": ["style", "voice"]
|
|
1791
|
+
},
|
|
1792
|
+
"vocal_gender": {
|
|
1793
|
+
"enum": ["male", "female"]
|
|
1794
|
+
},
|
|
1795
|
+
"vocal_mode": {
|
|
1796
|
+
"enum": ["auto_lyrics", "exact_lyrics", "instrumental"]
|
|
1797
|
+
}
|
|
1798
|
+
},
|
|
1799
|
+
"suno-v6-mini": {
|
|
1800
|
+
"persona_type": {
|
|
1801
|
+
"enum": ["style", "voice"]
|
|
1802
|
+
},
|
|
1803
|
+
"vocal_gender": {
|
|
1804
|
+
"enum": ["male", "female"]
|
|
1805
|
+
},
|
|
1806
|
+
"vocal_mode": {
|
|
1807
|
+
"enum": ["auto_lyrics", "exact_lyrics", "instrumental"]
|
|
1808
|
+
}
|
|
1809
|
+
},
|
|
1810
|
+
"suno-v6-wild": {
|
|
1811
|
+
"persona_type": {
|
|
1812
|
+
"enum": ["style", "voice"]
|
|
1813
|
+
},
|
|
1814
|
+
"vocal_gender": {
|
|
1815
|
+
"enum": ["male", "female"]
|
|
1816
|
+
},
|
|
1817
|
+
"vocal_mode": {
|
|
1818
|
+
"enum": ["auto_lyrics", "exact_lyrics", "instrumental"]
|
|
1819
|
+
}
|
|
1781
1820
|
}
|
|
1782
1821
|
}
|
|
1783
1822
|
},
|
|
1784
1823
|
"suno/create-mashup": {
|
|
1785
|
-
"models": ["suno-v4", "suno-v4.5", "suno-v4.5-all", "suno-v4.5-plus", "suno-v5", "suno-v5.5"],
|
|
1824
|
+
"models": ["suno-v4", "suno-v4.5", "suno-v4.5-all", "suno-v4.5-plus", "suno-v5", "suno-v5.5", "suno-v6", "suno-v6-mini", "suno-v6-wild"],
|
|
1786
1825
|
"fields_by_model": {
|
|
1787
1826
|
"suno-v4": {
|
|
1788
1827
|
"persona_type": {
|
|
@@ -1849,11 +1888,44 @@ CONTRACT = {
|
|
|
1849
1888
|
"vocal_mode": {
|
|
1850
1889
|
"enum": ["auto_lyrics", "exact_lyrics", "instrumental"]
|
|
1851
1890
|
}
|
|
1891
|
+
},
|
|
1892
|
+
"suno-v6": {
|
|
1893
|
+
"persona_type": {
|
|
1894
|
+
"enum": ["style", "voice"]
|
|
1895
|
+
},
|
|
1896
|
+
"vocal_gender": {
|
|
1897
|
+
"enum": ["male", "female"]
|
|
1898
|
+
},
|
|
1899
|
+
"vocal_mode": {
|
|
1900
|
+
"enum": ["auto_lyrics", "exact_lyrics", "instrumental"]
|
|
1901
|
+
}
|
|
1902
|
+
},
|
|
1903
|
+
"suno-v6-mini": {
|
|
1904
|
+
"persona_type": {
|
|
1905
|
+
"enum": ["style", "voice"]
|
|
1906
|
+
},
|
|
1907
|
+
"vocal_gender": {
|
|
1908
|
+
"enum": ["male", "female"]
|
|
1909
|
+
},
|
|
1910
|
+
"vocal_mode": {
|
|
1911
|
+
"enum": ["auto_lyrics", "exact_lyrics", "instrumental"]
|
|
1912
|
+
}
|
|
1913
|
+
},
|
|
1914
|
+
"suno-v6-wild": {
|
|
1915
|
+
"persona_type": {
|
|
1916
|
+
"enum": ["style", "voice"]
|
|
1917
|
+
},
|
|
1918
|
+
"vocal_gender": {
|
|
1919
|
+
"enum": ["male", "female"]
|
|
1920
|
+
},
|
|
1921
|
+
"vocal_mode": {
|
|
1922
|
+
"enum": ["auto_lyrics", "exact_lyrics", "instrumental"]
|
|
1923
|
+
}
|
|
1852
1924
|
}
|
|
1853
1925
|
}
|
|
1854
1926
|
},
|
|
1855
1927
|
"suno/extend-music": {
|
|
1856
|
-
"models": ["suno-v4", "suno-v4.5", "suno-v4.5-all", "suno-v4.5-plus", "suno-v5", "suno-v5.5"],
|
|
1928
|
+
"models": ["suno-v4", "suno-v4.5", "suno-v4.5-all", "suno-v4.5-plus", "suno-v5", "suno-v5.5", "suno-v6", "suno-v6-mini", "suno-v6-wild"],
|
|
1857
1929
|
"fields_by_model": {
|
|
1858
1930
|
"suno-v4": {
|
|
1859
1931
|
"parameter_mode": {
|
|
@@ -1920,6 +1992,39 @@ CONTRACT = {
|
|
|
1920
1992
|
"vocal_gender": {
|
|
1921
1993
|
"enum": ["male", "female"]
|
|
1922
1994
|
}
|
|
1995
|
+
},
|
|
1996
|
+
"suno-v6": {
|
|
1997
|
+
"parameter_mode": {
|
|
1998
|
+
"enum": ["source", "custom"]
|
|
1999
|
+
},
|
|
2000
|
+
"persona_type": {
|
|
2001
|
+
"enum": ["style", "voice"]
|
|
2002
|
+
},
|
|
2003
|
+
"vocal_gender": {
|
|
2004
|
+
"enum": ["male", "female"]
|
|
2005
|
+
}
|
|
2006
|
+
},
|
|
2007
|
+
"suno-v6-mini": {
|
|
2008
|
+
"parameter_mode": {
|
|
2009
|
+
"enum": ["source", "custom"]
|
|
2010
|
+
},
|
|
2011
|
+
"persona_type": {
|
|
2012
|
+
"enum": ["style", "voice"]
|
|
2013
|
+
},
|
|
2014
|
+
"vocal_gender": {
|
|
2015
|
+
"enum": ["male", "female"]
|
|
2016
|
+
}
|
|
2017
|
+
},
|
|
2018
|
+
"suno-v6-wild": {
|
|
2019
|
+
"parameter_mode": {
|
|
2020
|
+
"enum": ["source", "custom"]
|
|
2021
|
+
},
|
|
2022
|
+
"persona_type": {
|
|
2023
|
+
"enum": ["style", "voice"]
|
|
2024
|
+
},
|
|
2025
|
+
"vocal_gender": {
|
|
2026
|
+
"enum": ["male", "female"]
|
|
2027
|
+
}
|
|
1923
2028
|
}
|
|
1924
2029
|
}
|
|
1925
2030
|
},
|
|
@@ -1973,6 +2078,28 @@ CONTRACT = {
|
|
|
1973
2078
|
"suno-v5.5": {}
|
|
1974
2079
|
}
|
|
1975
2080
|
},
|
|
2081
|
+
"suno/music-from-sample": {
|
|
2082
|
+
"models": ["suno-v4", "suno-v4.5", "suno-v4.5-plus", "suno-v5", "suno-v5.5"],
|
|
2083
|
+
"fields_by_model": {
|
|
2084
|
+
"suno-v4": {},
|
|
2085
|
+
"suno-v4.5": {},
|
|
2086
|
+
"suno-v4.5-plus": {},
|
|
2087
|
+
"suno-v5": {},
|
|
2088
|
+
"suno-v5.5": {}
|
|
2089
|
+
}
|
|
2090
|
+
},
|
|
2091
|
+
"suno/music-visualizations": {
|
|
2092
|
+
"models": [],
|
|
2093
|
+
"fields_by_model": {
|
|
2094
|
+
"_": {}
|
|
2095
|
+
}
|
|
2096
|
+
},
|
|
2097
|
+
"suno/personas": {
|
|
2098
|
+
"models": [],
|
|
2099
|
+
"fields_by_model": {
|
|
2100
|
+
"_": {}
|
|
2101
|
+
}
|
|
2102
|
+
},
|
|
1976
2103
|
"suno/regenerate-validation-phrase": {
|
|
1977
2104
|
"models": [],
|
|
1978
2105
|
"fields_by_model": {
|
|
@@ -1982,11 +2109,31 @@ CONTRACT = {
|
|
|
1982
2109
|
"suno/remaster-audio": {
|
|
1983
2110
|
"models": ["suno-v4", "suno-v4.5", "suno-v4.5-plus", "suno-v5", "suno-v5.5"],
|
|
1984
2111
|
"fields_by_model": {
|
|
1985
|
-
"suno-v4": {
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
2112
|
+
"suno-v4": {
|
|
2113
|
+
"variation_category": {
|
|
2114
|
+
"enum": ["subtle", "normal", "high"]
|
|
2115
|
+
}
|
|
2116
|
+
},
|
|
2117
|
+
"suno-v4.5": {
|
|
2118
|
+
"variation_category": {
|
|
2119
|
+
"enum": ["subtle", "normal", "high"]
|
|
2120
|
+
}
|
|
2121
|
+
},
|
|
2122
|
+
"suno-v4.5-plus": {
|
|
2123
|
+
"variation_category": {
|
|
2124
|
+
"enum": ["subtle", "normal", "high"]
|
|
2125
|
+
}
|
|
2126
|
+
},
|
|
2127
|
+
"suno-v5": {
|
|
2128
|
+
"variation_category": {
|
|
2129
|
+
"enum": ["subtle", "normal", "high"]
|
|
2130
|
+
}
|
|
2131
|
+
},
|
|
2132
|
+
"suno-v5.5": {
|
|
2133
|
+
"variation_category": {
|
|
2134
|
+
"enum": ["subtle", "normal", "high"]
|
|
2135
|
+
}
|
|
2136
|
+
}
|
|
1990
2137
|
}
|
|
1991
2138
|
},
|
|
1992
2139
|
"suno/replace-section": {
|
|
@@ -1994,7 +2141,7 @@ CONTRACT = {
|
|
|
1994
2141
|
"fields_by_model": {
|
|
1995
2142
|
"_": {
|
|
1996
2143
|
"model": {
|
|
1997
|
-
"enum": ["suno-v4", "suno-v4.5", "suno-v4.5-all", "suno-v4.5-plus", "suno-v5", "suno-v5.5"]
|
|
2144
|
+
"enum": ["suno-v6", "suno-v6-wild", "suno-v6-mini", "suno-v4", "suno-v4.5", "suno-v4.5-all", "suno-v4.5-plus", "suno-v5", "suno-v5.5"]
|
|
1998
2145
|
}
|
|
1999
2146
|
}
|
|
2000
2147
|
}
|
|
@@ -2022,8 +2169,14 @@ CONTRACT = {
|
|
|
2022
2169
|
"suno-v5.5": {}
|
|
2023
2170
|
}
|
|
2024
2171
|
},
|
|
2172
|
+
"suno/style-expansions": {
|
|
2173
|
+
"models": [],
|
|
2174
|
+
"fields_by_model": {
|
|
2175
|
+
"_": {}
|
|
2176
|
+
}
|
|
2177
|
+
},
|
|
2025
2178
|
"suno/text-to-music": {
|
|
2026
|
-
"models": ["suno-v4", "suno-v4.5", "suno-v4.5-all", "suno-v4.5-plus", "suno-v5", "suno-v5.5"],
|
|
2179
|
+
"models": ["suno-v4", "suno-v4.5", "suno-v4.5-all", "suno-v4.5-plus", "suno-v5", "suno-v5.5", "suno-v6", "suno-v6-mini", "suno-v6-wild"],
|
|
2027
2180
|
"fields_by_model": {
|
|
2028
2181
|
"suno-v4": {
|
|
2029
2182
|
"persona_type": {
|
|
@@ -2090,6 +2243,39 @@ CONTRACT = {
|
|
|
2090
2243
|
"vocal_mode": {
|
|
2091
2244
|
"enum": ["auto_lyrics", "exact_lyrics", "instrumental"]
|
|
2092
2245
|
}
|
|
2246
|
+
},
|
|
2247
|
+
"suno-v6": {
|
|
2248
|
+
"persona_type": {
|
|
2249
|
+
"enum": ["style", "voice"]
|
|
2250
|
+
},
|
|
2251
|
+
"vocal_gender": {
|
|
2252
|
+
"enum": ["male", "female"]
|
|
2253
|
+
},
|
|
2254
|
+
"vocal_mode": {
|
|
2255
|
+
"enum": ["auto_lyrics", "exact_lyrics", "instrumental"]
|
|
2256
|
+
}
|
|
2257
|
+
},
|
|
2258
|
+
"suno-v6-mini": {
|
|
2259
|
+
"persona_type": {
|
|
2260
|
+
"enum": ["style", "voice"]
|
|
2261
|
+
},
|
|
2262
|
+
"vocal_gender": {
|
|
2263
|
+
"enum": ["male", "female"]
|
|
2264
|
+
},
|
|
2265
|
+
"vocal_mode": {
|
|
2266
|
+
"enum": ["auto_lyrics", "exact_lyrics", "instrumental"]
|
|
2267
|
+
}
|
|
2268
|
+
},
|
|
2269
|
+
"suno-v6-wild": {
|
|
2270
|
+
"persona_type": {
|
|
2271
|
+
"enum": ["style", "voice"]
|
|
2272
|
+
},
|
|
2273
|
+
"vocal_gender": {
|
|
2274
|
+
"enum": ["male", "female"]
|
|
2275
|
+
},
|
|
2276
|
+
"vocal_mode": {
|
|
2277
|
+
"enum": ["auto_lyrics", "exact_lyrics", "instrumental"]
|
|
2278
|
+
}
|
|
2093
2279
|
}
|
|
2094
2280
|
}
|
|
2095
2281
|
},
|
|
@@ -2108,6 +2294,12 @@ CONTRACT = {
|
|
|
2108
2294
|
}
|
|
2109
2295
|
}
|
|
2110
2296
|
},
|
|
2297
|
+
"suno/timestamped-lyrics": {
|
|
2298
|
+
"models": [],
|
|
2299
|
+
"fields_by_model": {
|
|
2300
|
+
"_": {}
|
|
2301
|
+
}
|
|
2302
|
+
},
|
|
2111
2303
|
"suno/visualize-music": {
|
|
2112
2304
|
"models": [],
|
|
2113
2305
|
"fields_by_model": {
|
|
@@ -2124,6 +2316,12 @@ CONTRACT = {
|
|
|
2124
2316
|
}
|
|
2125
2317
|
}
|
|
2126
2318
|
},
|
|
2319
|
+
"suno/voices": {
|
|
2320
|
+
"models": [],
|
|
2321
|
+
"fields_by_model": {
|
|
2322
|
+
"_": {}
|
|
2323
|
+
}
|
|
2324
|
+
},
|
|
2127
2325
|
"topaz/upscale-image": {
|
|
2128
2326
|
"models": ["topaz-upscale-image"],
|
|
2129
2327
|
"fields_by_model": {
|
|
@@ -2144,6 +2342,16 @@ CONTRACT = {
|
|
|
2144
2342
|
}
|
|
2145
2343
|
}
|
|
2146
2344
|
},
|
|
2345
|
+
"typesafe/system-one": {
|
|
2346
|
+
"models": ["jev-latest"],
|
|
2347
|
+
"fields_by_model": {
|
|
2348
|
+
"jev-latest": {
|
|
2349
|
+
"model": {
|
|
2350
|
+
"enum": ["jev-latest"]
|
|
2351
|
+
}
|
|
2352
|
+
}
|
|
2353
|
+
}
|
|
2354
|
+
},
|
|
2147
2355
|
"veo-3-1/extend-video": {
|
|
2148
2356
|
"models": [],
|
|
2149
2357
|
"fields_by_model": {
|
|
@@ -263,7 +263,7 @@ class TaskResponse(BaseModel):
|
|
|
263
263
|
id = optional(str)
|
|
264
264
|
status = optional(str)
|
|
265
265
|
error = optional(str)
|
|
266
|
-
|
|
266
|
+
usage = optional(lambda: TaskUsage)
|
|
267
267
|
|
|
268
268
|
|
|
269
269
|
class TaskResultResponse(BaseModel):
|
|
@@ -275,28 +275,16 @@ class TaskResultResponse(BaseModel):
|
|
|
275
275
|
body = optional()
|
|
276
276
|
|
|
277
277
|
|
|
278
|
-
class TaskResult(
|
|
278
|
+
class TaskResult(BaseModel):
|
|
279
279
|
"""The account-scoped Task Result resource returned from an opaque Location."""
|
|
280
280
|
|
|
281
|
+
Status = TaskResponse.Status
|
|
282
|
+
|
|
281
283
|
id = required(str)
|
|
282
|
-
status = required(str, enum=lambda:
|
|
284
|
+
status = required(str, enum=lambda: TaskResult.Status.ALL)
|
|
285
|
+
error = optional(str)
|
|
283
286
|
response = optional(lambda: TaskResultResponse)
|
|
284
287
|
|
|
285
288
|
|
|
286
|
-
class
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
class BillingSettlement(BaseModel):
|
|
291
|
-
charged_amount_cents = required(int)
|
|
292
|
-
amount_micro_cents = required(int)
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
class BillingRefund(BaseModel):
|
|
296
|
-
refunded_at = required(str)
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
class TaskBillingFacts(BaseModel):
|
|
300
|
-
reservation = optional(BillingReservation)
|
|
301
|
-
settlement = optional(BillingSettlement)
|
|
302
|
-
refund = optional(BillingRefund)
|
|
289
|
+
class TaskUsage(BaseModel):
|
|
290
|
+
cost = required(float)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.9.0"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import pytest
|
|
2
2
|
|
|
3
|
-
from runapi.core import BaseModel, DynamicModel,
|
|
3
|
+
from runapi.core import BaseModel, DynamicModel, TaskResult, TaskResponse, TaskUsage, optional, required
|
|
4
4
|
from runapi.core.errors import ValidationError
|
|
5
5
|
|
|
6
6
|
|
|
@@ -34,7 +34,7 @@ def test_required_field_missing_raises():
|
|
|
34
34
|
|
|
35
35
|
|
|
36
36
|
def test_item_and_dot_access():
|
|
37
|
-
model = Sample({"id": "abc", "status": "completed"})
|
|
37
|
+
model = Sample({"id": "abc", "status": "completed", "usage": {"cost": 0.05}})
|
|
38
38
|
assert model["id"] == "abc"
|
|
39
39
|
assert model.status == "completed"
|
|
40
40
|
|
|
@@ -45,8 +45,7 @@ def test_coerces_nested_hashes_and_arrays():
|
|
|
45
45
|
"id": "abc",
|
|
46
46
|
"meta": {"count": 2},
|
|
47
47
|
"items": [{"name": "first"}],
|
|
48
|
-
"extra_field": {"nested": True}
|
|
49
|
-
}
|
|
48
|
+
"extra_field": {"nested": True}}
|
|
50
49
|
)
|
|
51
50
|
assert isinstance(model.meta, DynamicModel)
|
|
52
51
|
assert model.meta.count == 2
|
|
@@ -70,8 +69,8 @@ def test_to_dict_serializes_recursively():
|
|
|
70
69
|
|
|
71
70
|
|
|
72
71
|
def test_equality_with_dict():
|
|
73
|
-
model = Sample({"id": "abc", "status": "completed"})
|
|
74
|
-
assert model == {"id": "abc", "status": "completed"}
|
|
72
|
+
model = Sample({"id": "abc", "status": "completed", "usage": {"cost": 0.05}})
|
|
73
|
+
assert model == {"id": "abc", "status": "completed", "usage": {"cost": 0.05}}
|
|
75
74
|
|
|
76
75
|
|
|
77
76
|
def test_optional_absent_field_is_none():
|
|
@@ -119,14 +118,32 @@ def test_response_headers_stay_outside_serialized_body():
|
|
|
119
118
|
assert model.to_dict() == {"id": "abc"}
|
|
120
119
|
|
|
121
120
|
|
|
122
|
-
def
|
|
121
|
+
def test_task_response_coerces_typed_usage_and_preserves_unknown_fields():
|
|
123
122
|
response = TaskResponse(
|
|
124
123
|
{
|
|
125
124
|
"id": "task_1",
|
|
126
|
-
"
|
|
127
|
-
|
|
125
|
+
"status": "completed",
|
|
126
|
+
"usage": {"cost": 0.05, "future_fact": "retained"}}
|
|
128
127
|
)
|
|
129
128
|
|
|
130
|
-
assert isinstance(response.
|
|
131
|
-
assert response.
|
|
132
|
-
assert response.
|
|
129
|
+
assert isinstance(response.usage, TaskUsage)
|
|
130
|
+
assert response.usage.cost == 0.05
|
|
131
|
+
assert response.usage.future_fact == "retained"
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
def test_task_result_preserves_public_status_constants_without_task_usage():
|
|
135
|
+
assert [
|
|
136
|
+
TaskResult.Status.PENDING,
|
|
137
|
+
TaskResult.Status.PROCESSING,
|
|
138
|
+
TaskResult.Status.COMPLETED,
|
|
139
|
+
TaskResult.Status.FAILED,
|
|
140
|
+
] == ["pending", "processing", "completed", "failed"]
|
|
141
|
+
|
|
142
|
+
result = TaskResult({"id": "task_1", "status": TaskResult.Status.COMPLETED})
|
|
143
|
+
assert result.status == "completed"
|
|
144
|
+
assert "usage" not in result.to_dict()
|
|
145
|
+
with pytest.raises(AttributeError):
|
|
146
|
+
_ = result.usage
|
|
147
|
+
|
|
148
|
+
with pytest.raises(ValidationError, match="Invalid status"):
|
|
149
|
+
TaskResult({"id": "task_1", "status": "unknown"})
|
|
@@ -91,10 +91,8 @@ INT_SCHEMA = {
|
|
|
91
91
|
"fields_by_model": {
|
|
92
92
|
"m": {
|
|
93
93
|
"duration_int": {"type": "integer", "min": 4, "max": 12},
|
|
94
|
-
"tolerance": {"type": "integer"}
|
|
95
|
-
|
|
96
|
-
},
|
|
97
|
-
}
|
|
94
|
+
"tolerance": {"type": "integer"}}
|
|
95
|
+
}}
|
|
98
96
|
|
|
99
97
|
|
|
100
98
|
def _run_validate(params):
|
|
@@ -130,10 +128,8 @@ def test_validate_functional_action_uses_underscore_fields():
|
|
|
130
128
|
"fields_by_model": {
|
|
131
129
|
"_": {
|
|
132
130
|
"prompt": {"required": True},
|
|
133
|
-
"mode": {"enum": ["fast", "quality"]}
|
|
134
|
-
|
|
135
|
-
},
|
|
136
|
-
}
|
|
131
|
+
"mode": {"enum": ["fast", "quality"]}}
|
|
132
|
+
}}
|
|
137
133
|
resource._validate_contract(schema, {"prompt": "hello", "mode": "fast"})
|
|
138
134
|
with pytest.raises(ValidationError, match="prompt is required"):
|
|
139
135
|
resource._validate_contract(schema, {"mode": "fast"})
|
|
@@ -164,10 +160,8 @@ def test_validate_array_item_count_constraints():
|
|
|
164
160
|
"models": ["m"],
|
|
165
161
|
"fields_by_model": {
|
|
166
162
|
"m": {
|
|
167
|
-
"reference_image_urls": {"min_items": 1, "max_items": 3}
|
|
168
|
-
|
|
169
|
-
},
|
|
170
|
-
}
|
|
163
|
+
"reference_image_urls": {"min_items": 1, "max_items": 3}}
|
|
164
|
+
}}
|
|
171
165
|
resource = SampleResource(FakeHttp())
|
|
172
166
|
|
|
173
167
|
with pytest.raises(ValidationError, match="^reference_image_urls must be an array$"):
|
|
@@ -187,8 +181,7 @@ def test_validate_contract_runs_rules_before_field_requirements():
|
|
|
187
181
|
schema = {
|
|
188
182
|
"models": ["m"],
|
|
189
183
|
"rules": [{"when": {"model": "m"}, "forbidden": ["source_task_id"]}],
|
|
190
|
-
"fields_by_model": {"m": {"source_image_urls": {"required": True}}}
|
|
191
|
-
}
|
|
184
|
+
"fields_by_model": {"m": {"source_image_urls": {"required": True}}}}
|
|
192
185
|
resource = SampleResource(FakeHttp())
|
|
193
186
|
with pytest.raises(ValidationError, match="source_task_id is not allowed when model is m"):
|
|
194
187
|
resource._validate_contract(schema, {"model": "m", "source_task_id": "src_1"})
|
|
@@ -196,7 +189,7 @@ def test_validate_contract_runs_rules_before_field_requirements():
|
|
|
196
189
|
|
|
197
190
|
def test_poll_recoerces_to_completed_class():
|
|
198
191
|
resource = SampleResource(FakeHttp())
|
|
199
|
-
response = TaskResponse({"id": "1", "status": "completed", "images": [{"url": "u"}]})
|
|
192
|
+
response = TaskResponse({"id": "1", "status": "completed", "usage": {"cost": 0.05}, "images": [{"url": "u"}]})
|
|
200
193
|
result = resource._poll_until_complete(lambda: response, PollingOptions(poll_interval=0, max_wait=1))
|
|
201
194
|
assert isinstance(result, CompletedResponse)
|
|
202
195
|
assert result.images[0].url == "u"
|
|
@@ -215,14 +208,12 @@ def test_run_hybrid_uses_opaque_location_and_decodes_completed_json(monkeypatch)
|
|
|
215
208
|
ApiResponse(
|
|
216
209
|
{
|
|
217
210
|
"id": "task_1",
|
|
218
|
-
"status": "completed",
|
|
211
|
+
"status": "completed", "usage": {"cost": 0.05},
|
|
219
212
|
"response": {
|
|
220
213
|
"status": 200,
|
|
221
214
|
"content_type": "application/json",
|
|
222
215
|
"headers": {"Location": "https://runapi.ai/result"},
|
|
223
|
-
"body": {"id": "task_1", "status": "completed", "prompts": ["short prompt"]}
|
|
224
|
-
},
|
|
225
|
-
}
|
|
216
|
+
"body": {"id": "task_1", "status": "completed", "usage": {"cost": 0.05}, "prompts": ["short prompt"]}}}
|
|
226
217
|
),
|
|
227
218
|
)
|
|
228
219
|
|
|
@@ -234,8 +225,7 @@ def test_run_hybrid_uses_opaque_location_and_decodes_completed_json(monkeypatch)
|
|
|
234
225
|
assert [call[:2] for call in http.calls] == [
|
|
235
226
|
("post", "/shorten"),
|
|
236
227
|
("get", "https://runapi.ai/api/v1/tasks/task_1"),
|
|
237
|
-
("get", "https://runapi.ai/api/v1/tasks/task_1")
|
|
238
|
-
]
|
|
228
|
+
("get", "https://runapi.ai/api/v1/tasks/task_1")]
|
|
239
229
|
assert slept == [3.0, 2.0]
|
|
240
230
|
|
|
241
231
|
|
|
@@ -248,7 +238,7 @@ def test_run_hybrid_honors_http_date_retry_after(monkeypatch):
|
|
|
248
238
|
http = FakeHttp(
|
|
249
239
|
ApiResponse({"id": "task_1", "status": "processing"}, {"Location": "/api/v1/tasks/task_1", "Retry-After": initial_retry_after}, status_code=202),
|
|
250
240
|
ApiResponse({"id": "task_1", "status": "processing"}, {"Retry-After": polling_retry_after}),
|
|
251
|
-
ApiResponse({"id": "task_1", "status": "completed", "response": {"status": 200, "content_type": "application/json", "headers": {}, "body": {"id": "task_1", "status": "completed", "prompts": ["short prompt"]}}}),
|
|
241
|
+
ApiResponse({"id": "task_1", "status": "completed", "usage": {"cost": 0.05}, "response": {"status": 200, "content_type": "application/json", "headers": {}, "body": {"id": "task_1", "status": "completed", "usage": {"cost": 0.05}, "prompts": ["short prompt"]}}}),
|
|
252
242
|
)
|
|
253
243
|
|
|
254
244
|
HybridResource(http)._run_hybrid("post", "/shorten", {"prompt": "long"})
|
|
@@ -273,14 +263,12 @@ def test_run_hybrid_follows_a_real_http_stub_and_reuses_generated_key(monkeypatc
|
|
|
273
263
|
200,
|
|
274
264
|
json={
|
|
275
265
|
"id": "task_1",
|
|
276
|
-
"status": "completed",
|
|
266
|
+
"status": "completed", "usage": {"cost": 0.05},
|
|
277
267
|
"response": {
|
|
278
268
|
"status": 200,
|
|
279
269
|
"content_type": "application/json",
|
|
280
270
|
"headers": {},
|
|
281
|
-
"body": {"id": "task_1", "status": "completed", "prompts": ["short prompt"]},
|
|
282
|
-
},
|
|
283
|
-
},
|
|
271
|
+
"body": {"id": "task_1", "status": "completed", "usage": {"cost": 0.05}, "prompts": ["short prompt"]}}},
|
|
284
272
|
)
|
|
285
273
|
|
|
286
274
|
http = HttpClient(
|
|
@@ -383,14 +371,12 @@ def test_subscribe_returns_text_srt_and_vtt_without_coercing_to_bytes(monkeypatc
|
|
|
383
371
|
ApiResponse(
|
|
384
372
|
{
|
|
385
373
|
"id": "task_text",
|
|
386
|
-
"status": "completed",
|
|
374
|
+
"status": "completed", "usage": {"cost": 0.05},
|
|
387
375
|
"response": {
|
|
388
376
|
"status": 200,
|
|
389
377
|
"content_type": "text/vtt; charset=utf-8",
|
|
390
378
|
"headers": {},
|
|
391
|
-
"body": "WEBVTT\n\n00:00.000 --> 00:01.000\nHello"
|
|
392
|
-
},
|
|
393
|
-
}
|
|
379
|
+
"body": "WEBVTT\n\n00:00.000 --> 00:01.000\nHello"}}
|
|
394
380
|
)
|
|
395
381
|
)
|
|
396
382
|
|
|
@@ -410,9 +396,7 @@ def test_subscribe_maps_failed_task_checkpoint_to_public_error(monkeypatch):
|
|
|
410
396
|
"status": 422,
|
|
411
397
|
"content_type": "application/json",
|
|
412
398
|
"headers": {},
|
|
413
|
-
"body": {"error": "Prompt rejected"}
|
|
414
|
-
},
|
|
415
|
-
}
|
|
399
|
+
"body": {"error": "Prompt rejected"}}}
|
|
416
400
|
)
|
|
417
401
|
)
|
|
418
402
|
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.8.2"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|