runapi-core 0.1.3__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 (28) hide show
  1. {runapi_core-0.1.3 → runapi_core-0.1.4}/PKG-INFO +1 -1
  2. {runapi_core-0.1.3 → runapi_core-0.1.4}/src/runapi/core/contract_gen.py +77 -5
  3. {runapi_core-0.1.3 → runapi_core-0.1.4}/src/runapi/core/resource.py +4 -5
  4. runapi_core-0.1.4/src/runapi/core/version.py +1 -0
  5. {runapi_core-0.1.3 → runapi_core-0.1.4}/tests/test_resource.py +11 -0
  6. runapi_core-0.1.3/src/runapi/core/version.py +0 -1
  7. {runapi_core-0.1.3 → runapi_core-0.1.4}/README.md +0 -0
  8. {runapi_core-0.1.3 → runapi_core-0.1.4}/pyproject.toml +0 -0
  9. {runapi_core-0.1.3 → runapi_core-0.1.4}/src/runapi/core/__init__.py +0 -0
  10. {runapi_core-0.1.3 → runapi_core-0.1.4}/src/runapi/core/auth.py +0 -0
  11. {runapi_core-0.1.3 → runapi_core-0.1.4}/src/runapi/core/config.py +0 -0
  12. {runapi_core-0.1.3 → runapi_core-0.1.4}/src/runapi/core/constants.py +0 -0
  13. {runapi_core-0.1.3 → runapi_core-0.1.4}/src/runapi/core/errors.py +0 -0
  14. {runapi_core-0.1.3 → runapi_core-0.1.4}/src/runapi/core/files.py +0 -0
  15. {runapi_core-0.1.3 → runapi_core-0.1.4}/src/runapi/core/http_client.py +0 -0
  16. {runapi_core-0.1.3 → runapi_core-0.1.4}/src/runapi/core/models.py +0 -0
  17. {runapi_core-0.1.3 → runapi_core-0.1.4}/src/runapi/core/multipart.py +0 -0
  18. {runapi_core-0.1.3 → runapi_core-0.1.4}/src/runapi/core/options.py +0 -0
  19. {runapi_core-0.1.3 → runapi_core-0.1.4}/src/runapi/core/polling.py +0 -0
  20. {runapi_core-0.1.3 → runapi_core-0.1.4}/src/runapi/core/py.typed +0 -0
  21. {runapi_core-0.1.3 → runapi_core-0.1.4}/src/runapi/core/response.py +0 -0
  22. {runapi_core-0.1.3 → runapi_core-0.1.4}/tests/test_auth.py +0 -0
  23. {runapi_core-0.1.3 → runapi_core-0.1.4}/tests/test_config.py +0 -0
  24. {runapi_core-0.1.3 → runapi_core-0.1.4}/tests/test_errors.py +0 -0
  25. {runapi_core-0.1.3 → runapi_core-0.1.4}/tests/test_files.py +0 -0
  26. {runapi_core-0.1.3 → runapi_core-0.1.4}/tests/test_http_client.py +0 -0
  27. {runapi_core-0.1.3 → runapi_core-0.1.4}/tests/test_models.py +0 -0
  28. {runapi_core-0.1.3 → runapi_core-0.1.4}/tests/test_polling.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: runapi-core
3
- Version: 0.1.3
3
+ Version: 0.1.4
4
4
  Summary: Core module for the RunAPI Python SDK
5
5
  Project-URL: Homepage, https://runapi.ai
6
6
  Project-URL: Documentation, https://runapi.ai/docs#sdk
@@ -211,7 +211,7 @@ CONTRACT = {
211
211
  }
212
212
  },
213
213
  "grok-imagine/image-to-video": {
214
- "models": ["grok-imagine-image-to-video"],
214
+ "models": ["grok-imagine-image-to-video", "grok-imagine-video-1.5-preview"],
215
215
  "fields_by_model": {
216
216
  "grok-imagine-image-to-video": {
217
217
  "aspect_ratio": {
@@ -223,6 +223,14 @@ CONTRACT = {
223
223
  "output_resolution": {
224
224
  "enum": ["480p", "720p"]
225
225
  }
226
+ },
227
+ "grok-imagine-video-1.5-preview": {
228
+ "aspect_ratio": {
229
+ "enum": ["1:1", "16:9", "9:16", "3:2", "2:3", "auto"]
230
+ },
231
+ "output_resolution": {
232
+ "enum": ["480p", "720p"]
233
+ }
226
234
  }
227
235
  }
228
236
  },
@@ -237,7 +245,7 @@ CONTRACT = {
237
245
  }
238
246
  },
239
247
  "grok-imagine/text-to-video": {
240
- "models": ["grok-imagine-text-to-video"],
248
+ "models": ["grok-imagine-text-to-video", "grok-imagine-video-1.5-preview"],
241
249
  "fields_by_model": {
242
250
  "grok-imagine-text-to-video": {
243
251
  "aspect_ratio": {
@@ -249,6 +257,14 @@ CONTRACT = {
249
257
  "output_resolution": {
250
258
  "enum": ["480p", "720p"]
251
259
  }
260
+ },
261
+ "grok-imagine-video-1.5-preview": {
262
+ "aspect_ratio": {
263
+ "enum": ["1:1", "16:9", "9:16", "3:2", "2:3", "auto"]
264
+ },
265
+ "output_resolution": {
266
+ "enum": ["480p", "720p"]
267
+ }
252
268
  }
253
269
  }
254
270
  },
@@ -508,7 +524,7 @@ CONTRACT = {
508
524
  }
509
525
  },
510
526
  "kling/image-to-video": {
511
- "models": ["kling-v2.1-master-image-to-video", "kling-v2.1-pro", "kling-v2.1-standard", "kling-v2.5-turbo-image-to-video-pro"],
527
+ "models": ["kling-v2.1-master-image-to-video", "kling-v2.1-pro", "kling-v2.1-standard", "kling-v2.5-turbo-image-to-video-pro", "kling-v3-turbo-image-to-video"],
512
528
  "fields_by_model": {
513
529
  "kling-v2.1-master-image-to-video": {
514
530
  "duration_seconds": {
@@ -529,6 +545,14 @@ CONTRACT = {
529
545
  "duration_seconds": {
530
546
  "enum": [5, 10]
531
547
  }
548
+ },
549
+ "kling-v3-turbo-image-to-video": {
550
+ "duration_seconds": {
551
+ "enum": [3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
552
+ },
553
+ "output_resolution": {
554
+ "enum": ["720p", "1080p"]
555
+ }
532
556
  }
533
557
  }
534
558
  },
@@ -549,7 +573,7 @@ CONTRACT = {
549
573
  }
550
574
  },
551
575
  "kling/text-to-video": {
552
- "models": ["kling-3.0", "kling-v2.1-master-text-to-video", "kling-v2.5-turbo-text-to-video-pro"],
576
+ "models": ["kling-3.0", "kling-v2.1-master-text-to-video", "kling-v2.5-turbo-text-to-video-pro", "kling-v3-turbo-text-to-video"],
553
577
  "fields_by_model": {
554
578
  "kling-3.0": {
555
579
  "aspect_ratio": {
@@ -577,6 +601,17 @@ CONTRACT = {
577
601
  "duration_seconds": {
578
602
  "enum": [5, 10]
579
603
  }
604
+ },
605
+ "kling-v3-turbo-text-to-video": {
606
+ "aspect_ratio": {
607
+ "enum": ["16:9", "9:16", "1:1"]
608
+ },
609
+ "duration_seconds": {
610
+ "enum": [3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
611
+ },
612
+ "output_resolution": {
613
+ "enum": ["720p", "1080p"]
614
+ }
580
615
  }
581
616
  }
582
617
  },
@@ -587,8 +622,13 @@ CONTRACT = {
587
622
  }
588
623
  },
589
624
  "nano-banana/edit-image": {
590
- "models": ["nano-banana-edit"],
625
+ "models": ["nano-banana-2-lite", "nano-banana-edit"],
591
626
  "fields_by_model": {
627
+ "nano-banana-2-lite": {
628
+ "aspect_ratio": {
629
+ "enum": ["1:1", "1:4", "1:8", "2:3", "3:2", "3:4", "4:1", "4:3", "4:5", "5:4", "8:1", "9:16", "16:9", "21:9", "auto"]
630
+ }
631
+ },
592
632
  "nano-banana-edit": {
593
633
  "aspect_ratio": {
594
634
  "enum": ["1:1", "9:16", "16:9", "3:4", "4:3", "3:2", "2:3", "5:4", "4:5", "21:9", "auto"]
@@ -639,6 +679,28 @@ CONTRACT = {
639
679
  }
640
680
  }
641
681
  },
682
+ "omnihuman/audio-to-video": {
683
+ "models": ["omnihuman-1.5"],
684
+ "fields_by_model": {
685
+ "omnihuman-1.5": {
686
+ "output_resolution": {
687
+ "enum": ["720p", "1080p"]
688
+ }
689
+ }
690
+ }
691
+ },
692
+ "omnihuman/human-identification": {
693
+ "models": ["omnihuman-1.5-human-identification"],
694
+ "fields_by_model": {
695
+ "omnihuman-1.5-human-identification": {}
696
+ }
697
+ },
698
+ "omnihuman/subject-detection": {
699
+ "models": ["omnihuman-1.5-subject-detection"],
700
+ "fields_by_model": {
701
+ "omnihuman-1.5-subject-detection": {}
702
+ }
703
+ },
642
704
  "qwen-2/edit-image": {
643
705
  "models": ["qwen-2-edit-image"],
644
706
  "fields_by_model": {
@@ -1350,6 +1412,16 @@ CONTRACT = {
1350
1412
  }
1351
1413
  }
1352
1414
  },
1415
+ "volcengine-lip-sync/lip-sync-video": {
1416
+ "models": ["volcengine-lip-sync"],
1417
+ "fields_by_model": {
1418
+ "volcengine-lip-sync": {
1419
+ "mode": {
1420
+ "enum": ["lite", "basic"]
1421
+ }
1422
+ }
1423
+ }
1424
+ },
1353
1425
  "wan/animate": {
1354
1426
  "models": ["wan-2.2-animate-move", "wan-2.2-animate-replace"],
1355
1427
  "fields_by_model": {
@@ -59,8 +59,8 @@ class Resource:
59
59
 
60
60
  # ---- Contract validation -------------------------------------------
61
61
  # Validates request params against the generated contract: model
62
- # membership, then per-field required/enum/integer/min/max/length, then
63
- # declared cross-field rules. `schema` is one action entry from the generated
62
+ # membership, then declared cross-field rules, then per-field
63
+ # required/enum/integer/min/max/length. `schema` is one action entry from the generated
64
64
  # per-package CONTRACT (CONTRACT["<action>"]).
65
65
 
66
66
  def _validate_contract(self, schema: Dict[str, Any], params: Dict[str, Any]) -> None:
@@ -73,11 +73,10 @@ class Resource:
73
73
  else:
74
74
  fields = schema.get("fields_by_model", {}).get("_", {})
75
75
 
76
- for field, rules in fields.items():
77
- self._validate_schema_field(params, field, rules)
78
-
79
76
  for rule in schema.get("rules", []):
80
77
  self._enforce_rule(params, rule)
78
+ for field, rules in fields.items():
79
+ self._validate_schema_field(params, field, rules)
81
80
 
82
81
  def _validate_schema_field(self, params: Dict[str, Any], field: str, rules: Dict[str, Any]) -> None:
83
82
  present = self._field_present(params, field)
@@ -0,0 +1 @@
1
+ __version__ = "0.1.4"
@@ -135,6 +135,17 @@ def test_validate_integer_rejects_bool_and_whole_float():
135
135
  assert _run_validate({"model": "m", "tolerance": 5}) == ""
136
136
 
137
137
 
138
+ def test_validate_contract_runs_rules_before_field_requirements():
139
+ schema = {
140
+ "models": ["m"],
141
+ "rules": [{"when": {"model": "m"}, "forbidden": ["source_task_id"]}],
142
+ "fields_by_model": {"m": {"source_image_urls": {"required": True}}},
143
+ }
144
+ resource = SampleResource(FakeHttp())
145
+ with pytest.raises(ValidationError, match="source_task_id is not allowed when model is m"):
146
+ resource._validate_contract(schema, {"model": "m", "source_task_id": "src_1"})
147
+
148
+
138
149
  def test_poll_recoerces_to_completed_class():
139
150
  resource = SampleResource(FakeHttp())
140
151
  response = TaskResponse({"id": "1", "status": "completed", "images": [{"url": "u"}]})
@@ -1 +0,0 @@
1
- __version__ = "0.1.3"
File without changes
File without changes