fal 1.0.8__py3-none-any.whl → 1.1.1__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.

Potentially problematic release.


This version of fal might be problematic. Click here for more details.

Files changed (48) hide show
  1. fal/_fal_version.py +2 -2
  2. fal/api.py +27 -26
  3. fal/cli/deploy.py +18 -8
  4. fal/toolkit/file/file.py +2 -0
  5. fal/toolkit/file/providers/fal.py +15 -3
  6. fal/toolkit/file/types.py +1 -1
  7. fal/workflows.py +1 -1
  8. {fal-1.0.8.dist-info → fal-1.1.1.dist-info}/METADATA +1 -1
  9. {fal-1.0.8.dist-info → fal-1.1.1.dist-info}/RECORD +47 -26
  10. {fal-1.0.8.dist-info → fal-1.1.1.dist-info}/WHEEL +1 -1
  11. openapi_fal_rest/api/comfy/__init__.py +0 -0
  12. openapi_fal_rest/api/comfy/create_workflow.py +172 -0
  13. openapi_fal_rest/api/comfy/delete_workflow.py +175 -0
  14. openapi_fal_rest/api/comfy/get_workflow.py +181 -0
  15. openapi_fal_rest/api/comfy/list_user_workflows.py +189 -0
  16. openapi_fal_rest/api/comfy/update_workflow.py +198 -0
  17. openapi_fal_rest/api/users/__init__.py +0 -0
  18. openapi_fal_rest/api/users/get_current_user.py +143 -0
  19. openapi_fal_rest/api/workflows/{create_or_update_workflow_workflows_post.py → create_workflow.py} +4 -4
  20. openapi_fal_rest/api/workflows/{get_workflows_workflows_get.py → list_user_workflows.py} +4 -4
  21. openapi_fal_rest/api/workflows/update_workflow.py +198 -0
  22. openapi_fal_rest/models/__init__.py +32 -10
  23. openapi_fal_rest/models/comfy_workflow_detail.py +109 -0
  24. openapi_fal_rest/models/comfy_workflow_item.py +88 -0
  25. openapi_fal_rest/models/comfy_workflow_schema.py +119 -0
  26. openapi_fal_rest/models/{execute_workflow_workflows_user_id_workflow_name_post_json_body_type_0.py → comfy_workflow_schema_extra_data.py} +5 -5
  27. openapi_fal_rest/models/{execute_workflow_workflows_user_id_workflow_name_post_response_200_type_0.py → comfy_workflow_schema_fal_inputs.py} +5 -5
  28. openapi_fal_rest/models/comfy_workflow_schema_fal_inputs_dev_info.py +44 -0
  29. openapi_fal_rest/models/{workflow_detail_contents_type_0.py → comfy_workflow_schema_prompt.py} +5 -5
  30. openapi_fal_rest/models/current_user.py +138 -0
  31. openapi_fal_rest/models/customer_details.py +8 -8
  32. openapi_fal_rest/models/lock_reason.py +3 -0
  33. openapi_fal_rest/models/page_comfy_workflow_item.py +107 -0
  34. openapi_fal_rest/models/team_role.py +10 -0
  35. openapi_fal_rest/models/typed_comfy_workflow.py +85 -0
  36. openapi_fal_rest/models/typed_comfy_workflow_update.py +95 -0
  37. openapi_fal_rest/models/typed_workflow_update.py +95 -0
  38. openapi_fal_rest/models/user_member.py +87 -0
  39. openapi_fal_rest/models/workflow_contents.py +20 -1
  40. openapi_fal_rest/models/workflow_contents_metadata.py +44 -0
  41. openapi_fal_rest/models/workflow_detail.py +18 -59
  42. openapi_fal_rest/models/workflow_detail_contents.py +44 -0
  43. openapi_fal_rest/models/workflow_item.py +19 -1
  44. openapi_fal_rest/api/workflows/execute_workflow_workflows_user_id_workflow_name_post.py +0 -268
  45. {fal-1.0.8.dist-info → fal-1.1.1.dist-info}/entry_points.txt +0 -0
  46. {fal-1.0.8.dist-info → fal-1.1.1.dist-info}/top_level.txt +0 -0
  47. /openapi_fal_rest/api/workflows/{delete_workflow_workflows_user_id_workflow_name_delete.py → delete_workflow.py} +0 -0
  48. /openapi_fal_rest/api/workflows/{get_workflow_workflows_user_id_workflow_name_get.py → get_workflow.py} +0 -0
fal/_fal_version.py CHANGED
@@ -12,5 +12,5 @@ __version__: str
12
12
  __version_tuple__: VERSION_TUPLE
13
13
  version_tuple: VERSION_TUPLE
14
14
 
15
- __version__ = version = '1.0.8'
16
- __version_tuple__ = version_tuple = (1, 0, 8)
15
+ __version__ = version = '1.1.1'
16
+ __version_tuple__ = version_tuple = (1, 1, 1)
fal/api.py CHANGED
@@ -75,6 +75,7 @@ SERVE_REQUIREMENTS = [
75
75
 
76
76
  THREAD_POOL = ThreadPoolExecutor()
77
77
 
78
+
78
79
  @dataclass
79
80
  class FalServerlessError(FalServerlessException):
80
81
  message: str
@@ -86,8 +87,7 @@ class InternalFalServerlessError(FalServerlessException):
86
87
 
87
88
 
88
89
  @dataclass
89
- class FalMissingDependencyError(FalServerlessError):
90
- ...
90
+ class FalMissingDependencyError(FalServerlessError): ...
91
91
 
92
92
 
93
93
  @dataclass
@@ -548,7 +548,6 @@ class FalServerlessHost(Host):
548
548
 
549
549
  return cast(ReturnT, return_value)
550
550
 
551
-
552
551
  def run(
553
552
  self,
554
553
  func: Callable[..., ReturnT],
@@ -644,8 +643,7 @@ def function(
644
643
  max_concurrency: int | None = None,
645
644
  ) -> Callable[
646
645
  [Callable[Concatenate[ArgsT], ReturnT]], IsolatedFunction[ArgsT, ReturnT]
647
- ]:
648
- ...
646
+ ]: ...
649
647
 
650
648
 
651
649
  @overload
@@ -661,8 +659,7 @@ def function(
661
659
  max_concurrency: int | None = None,
662
660
  ) -> Callable[
663
661
  [Callable[Concatenate[ArgsT], ReturnT]], ServedIsolatedFunction[ArgsT, ReturnT]
664
- ]:
665
- ...
662
+ ]: ...
666
663
 
667
664
 
668
665
  ### FalServerlessHost
@@ -688,8 +685,7 @@ def function(
688
685
  _scheduler: str | None = None,
689
686
  ) -> Callable[
690
687
  [Callable[Concatenate[ArgsT], ReturnT]], IsolatedFunction[ArgsT, ReturnT]
691
- ]:
692
- ...
688
+ ]: ...
693
689
 
694
690
 
695
691
  @overload
@@ -714,8 +710,7 @@ def function(
714
710
  _scheduler: str | None = None,
715
711
  ) -> Callable[
716
712
  [Callable[Concatenate[ArgsT], ReturnT]], ServedIsolatedFunction[ArgsT, ReturnT]
717
- ]:
718
- ...
713
+ ]: ...
719
714
 
720
715
 
721
716
  ## conda
@@ -738,8 +733,7 @@ def function(
738
733
  max_concurrency: int | None = None,
739
734
  ) -> Callable[
740
735
  [Callable[Concatenate[ArgsT], ReturnT]], IsolatedFunction[ArgsT, ReturnT]
741
- ]:
742
- ...
736
+ ]: ...
743
737
 
744
738
 
745
739
  @overload
@@ -760,8 +754,7 @@ def function(
760
754
  max_concurrency: int | None = None,
761
755
  ) -> Callable[
762
756
  [Callable[Concatenate[ArgsT], ReturnT]], ServedIsolatedFunction[ArgsT, ReturnT]
763
- ]:
764
- ...
757
+ ]: ...
765
758
 
766
759
 
767
760
  ### FalServerlessHost
@@ -792,8 +785,7 @@ def function(
792
785
  _scheduler: str | None = None,
793
786
  ) -> Callable[
794
787
  [Callable[Concatenate[ArgsT], ReturnT]], IsolatedFunction[ArgsT, ReturnT]
795
- ]:
796
- ...
788
+ ]: ...
797
789
 
798
790
 
799
791
  @overload
@@ -967,6 +959,9 @@ class BaseServable:
967
959
  yield
968
960
 
969
961
  def _build_app(self) -> FastAPI:
962
+ import json
963
+ import traceback
964
+
970
965
  from fastapi import HTTPException, Request
971
966
  from fastapi.middleware.cors import CORSMiddleware
972
967
  from fastapi.responses import JSONResponse
@@ -1007,6 +1002,15 @@ class BaseServable:
1007
1002
  # If it's not a generic 404, just return the original message.
1008
1003
  return JSONResponse({"detail": exc.detail}, 404)
1009
1004
 
1005
+ @_app.exception_handler(Exception)
1006
+ async def traceback_logging_exception_handler(request: Request, exc: Exception):
1007
+ print(
1008
+ json.dumps(
1009
+ {"traceback": "".join(traceback.format_exception(exc)[::-1])} # type: ignore
1010
+ )
1011
+ )
1012
+ return JSONResponse({"detail": "Internal Server Error"}, 500)
1013
+
1010
1014
  routes = self.collect_routes()
1011
1015
  if not routes:
1012
1016
  raise ValueError("An application must have at least one route!")
@@ -1056,7 +1060,8 @@ class BaseServable:
1056
1060
  }
1057
1061
 
1058
1062
  _, pending = await asyncio.wait(
1059
- tasks.keys(), return_when=asyncio.FIRST_COMPLETED,
1063
+ tasks.keys(),
1064
+ return_when=asyncio.FIRST_COMPLETED,
1060
1065
  )
1061
1066
  if not pending:
1062
1067
  return
@@ -1175,14 +1180,12 @@ class IsolatedFunction(Generic[ArgsT, ReturnT]):
1175
1180
  @overload
1176
1181
  def on(
1177
1182
  self, host: Host | None = None, *, serve: Literal[False] = False, **config: Any
1178
- ) -> IsolatedFunction[ArgsT, ReturnT]:
1179
- ...
1183
+ ) -> IsolatedFunction[ArgsT, ReturnT]: ...
1180
1184
 
1181
1185
  @overload
1182
1186
  def on(
1183
1187
  self, host: Host | None = None, *, serve: Literal[True], **config: Any
1184
- ) -> ServedIsolatedFunction[ArgsT, ReturnT]:
1185
- ...
1188
+ ) -> ServedIsolatedFunction[ArgsT, ReturnT]: ...
1186
1189
 
1187
1190
  def on(self, host: Host | None = None, **config: Any): # type: ignore
1188
1191
  host = host or self.host
@@ -1236,14 +1239,12 @@ class ServedIsolatedFunction(
1236
1239
  @overload # type: ignore[override,no-overload-impl]
1237
1240
  def on( # type: ignore[no-overload-impl]
1238
1241
  self, host: Host | None = None, *, serve: Literal[True] = True, **config: Any
1239
- ) -> ServedIsolatedFunction[ArgsT, ReturnT]:
1240
- ...
1242
+ ) -> ServedIsolatedFunction[ArgsT, ReturnT]: ...
1241
1243
 
1242
1244
  @overload
1243
1245
  def on(
1244
1246
  self, host: Host | None = None, *, serve: Literal[False], **config: Any
1245
- ) -> IsolatedFunction[ArgsT, ReturnT]:
1246
- ...
1247
+ ) -> IsolatedFunction[ArgsT, ReturnT]: ...
1247
1248
 
1248
1249
 
1249
1250
  class Server(uvicorn.Server):
fal/cli/deploy.py CHANGED
@@ -1,7 +1,11 @@
1
+ import argparse
2
+ from collections import namedtuple
1
3
  from pathlib import Path
2
4
 
3
5
  from .parser import FalClientParser, RefAction
4
6
 
7
+ User = namedtuple("User", ["user_id", "username"])
8
+
5
9
 
6
10
  def _remove_http_and_port_from_url(url):
7
11
  # Remove http://
@@ -20,17 +24,17 @@ def _remove_http_and_port_from_url(url):
20
24
  return url
21
25
 
22
26
 
23
- def _get_user_id() -> str:
27
+ def _get_user() -> User:
24
28
  import json
25
29
  from http import HTTPStatus
26
30
 
27
- import openapi_fal_rest.api.billing.get_user_details as get_user_details
31
+ import openapi_fal_rest.api.users.get_current_user as get_current_user
28
32
 
29
33
  from fal.api import FalServerlessError
30
34
  from fal.rest_client import REST_CLIENT
31
35
 
32
36
  try:
33
- user_details_response = get_user_details.sync_detailed(
37
+ user_details_response = get_current_user.sync_detailed(
34
38
  client=REST_CLIENT,
35
39
  )
36
40
  except Exception as e:
@@ -51,7 +55,7 @@ def _get_user_id() -> str:
51
55
  if not user_id:
52
56
  user_id = full_user_id
53
57
 
54
- return user_id
58
+ return User(user_id=user_id, username=user_details_response.parsed.nickname)
55
59
  except Exception as e:
56
60
  raise FalServerlessError(f"Could not parse the user data: {e}")
57
61
 
@@ -77,7 +81,7 @@ def _deploy(args):
77
81
  [file_path] = options
78
82
  file_path = str(file_path)
79
83
 
80
- user_id = _get_user_id()
84
+ user = _get_user()
81
85
  host = FalServerlessHost(args.host)
82
86
  isolated_function, app_name = load_function_from(
83
87
  host,
@@ -103,12 +107,18 @@ def _deploy(args):
103
107
  "Registered a new revision for function "
104
108
  f"'{app_name}' (revision='{app_id}')."
105
109
  )
106
- args.console.print(f"URL: https://{gateway_host}/{user_id}/{app_name}")
110
+ args.console.print(f"Playground: https://fal.ai/models/{user.username}/{app_name}")
111
+ args.console.print(f"Endpoint: https://{gateway_host}/{user.username}/{app_name}")
107
112
 
108
113
 
109
114
  def add_parser(main_subparsers, parents):
110
115
  from fal.sdk import ALIAS_AUTH_MODES
111
116
 
117
+ def valid_auth_option(option):
118
+ if option not in ALIAS_AUTH_MODES:
119
+ raise argparse.ArgumentTypeError(f"{option} is not a auth option")
120
+ return option
121
+
112
122
  deploy_help = "Deploy a fal application."
113
123
  epilog = (
114
124
  "Examples:\n"
@@ -139,8 +149,8 @@ def add_parser(main_subparsers, parents):
139
149
  )
140
150
  parser.add_argument(
141
151
  "--auth",
142
- choices=ALIAS_AUTH_MODES,
152
+ type=valid_auth_option,
143
153
  default="private",
144
- help="Application authentication mode.",
154
+ help="Application authentication mode (private, public).",
145
155
  )
146
156
  parser.set_defaults(func=_deploy)
fal/toolkit/file/file.py CHANGED
@@ -22,6 +22,7 @@ from pydantic import BaseModel, Field
22
22
  from fal.toolkit.file.providers.fal import (
23
23
  FalCDNFileRepository,
24
24
  FalFileRepository,
25
+ FalFileRepositoryV2,
25
26
  InMemoryRepository,
26
27
  )
27
28
  from fal.toolkit.file.providers.gcp import GoogleStorageRepository
@@ -33,6 +34,7 @@ FileRepositoryFactory = Callable[[], FileRepository]
33
34
 
34
35
  BUILT_IN_REPOSITORIES: dict[RepositoryId, FileRepositoryFactory] = {
35
36
  "fal": lambda: FalFileRepository(),
37
+ "fal_v2": lambda: FalFileRepositoryV2(),
36
38
  "in_memory": lambda: InMemoryRepository(),
37
39
  "gcp_storage": lambda: GoogleStorageRepository(),
38
40
  "r2": lambda: R2Repository(),
@@ -26,8 +26,8 @@ GLOBAL_LIFECYCLE_PREFERENCE = ObjectLifecyclePreference(
26
26
 
27
27
 
28
28
  @dataclass
29
- class FalFileRepository(FileRepository):
30
- def save(self, file: FileData) -> str:
29
+ class FalFileRepositoryBase(FileRepository):
30
+ def _save(self, file: FileData, storage_type: str) -> str:
31
31
  key_creds = key_credentials()
32
32
  if not key_creds:
33
33
  raise FileUploadException("FAL_KEY must be set")
@@ -41,7 +41,7 @@ class FalFileRepository(FileRepository):
41
41
 
42
42
  grpc_host = os.environ.get("FAL_HOST", "api.alpha.fal.ai")
43
43
  rest_host = grpc_host.replace("api", "rest", 1)
44
- storage_url = f"https://{rest_host}/storage/upload/initiate"
44
+ storage_url = f"https://{rest_host}/storage/upload/initiate?storage_type={storage_type}"
45
45
 
46
46
  try:
47
47
  req = Request(
@@ -79,6 +79,18 @@ class FalFileRepository(FileRepository):
79
79
  return
80
80
 
81
81
 
82
+ @dataclass
83
+ class FalFileRepository(FalFileRepositoryBase):
84
+ def save(self, file: FileData) -> str:
85
+ return self._save(file, "gcs")
86
+
87
+
88
+ @dataclass
89
+ class FalFileRepositoryV2(FalFileRepositoryBase):
90
+ def save(self, file: FileData) -> str:
91
+ return self._save(file, "fal-cdn")
92
+
93
+
82
94
  @dataclass
83
95
  class InMemoryRepository(FileRepository):
84
96
  def save(
fal/toolkit/file/types.py CHANGED
@@ -28,7 +28,7 @@ class FileData:
28
28
  self.file_name = file_name
29
29
 
30
30
 
31
- RepositoryId = Literal["fal", "in_memory", "gcp_storage", "r2", "cdn"]
31
+ RepositoryId = Literal["fal", "fal_v2", "in_memory", "gcp_storage", "r2", "cdn"]
32
32
 
33
33
 
34
34
  @dataclass
fal/workflows.py CHANGED
@@ -10,7 +10,7 @@ from typing import Any, Iterator, Union, cast
10
10
  import graphlib
11
11
  import rich
12
12
  from openapi_fal_rest.api.workflows import (
13
- create_or_update_workflow_workflows_post as publish_workflow,
13
+ create_workflow as publish_workflow,
14
14
  )
15
15
  from openapi_fal_rest.models.http_validation_error import HTTPValidationError
16
16
  from pydantic import BaseModel
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: fal
3
- Version: 1.0.8
3
+ Version: 1.1.1
4
4
  Summary: fal is an easy-to-use Serverless Python Framework
5
5
  Author: Features & Labels <support@fal.ai>
6
6
  Requires-Python: >=3.8
@@ -1,9 +1,9 @@
1
1
  fal/__init__.py,sha256=wXs1G0gSc7ZK60-bHe-B2m0l_sA6TrFk4BxY0tMoLe8,784
2
2
  fal/__main__.py,sha256=MSmt_5Xg84uHqzTN38JwgseJK8rsJn_11A8WD99VtEo,61
3
- fal/_fal_version.py,sha256=vy0P95Si-KzUl6NsixjrWEHfr5xcmkA_oO_S3bQRmvE,411
3
+ fal/_fal_version.py,sha256=EPoWF0em1tKJgBz5dbBF-r29860VBk-SsdiXh6E1aO0,411
4
4
  fal/_serialization.py,sha256=7urrZXw99qmsK-RkjCurk6Va4TMEfDIMajkzKbSW4j4,7655
5
5
  fal/_version.py,sha256=EBGqrknaf1WygENX-H4fBefLvHryvJBBGtVJetaB0NY,266
6
- fal/api.py,sha256=Qkp97ozww5EBXHq1oSikuDMGB0m7ZaYb5TCvROAknsA,40174
6
+ fal/api.py,sha256=x60GlBWynDd1yhHsVWeqf07WVTzgbwNC6cqCjhlTiFQ,40556
7
7
  fal/app.py,sha256=duOf_YKE8o30hmhNtF9zvkT8wlKYXW7hdQLJtPrXHik,15793
8
8
  fal/apps.py,sha256=UhR6mq8jBiTAp-QvUnvbnMNcuJ5wHIKSqdlfyx8aBQ8,6829
9
9
  fal/container.py,sha256=V7riyyq8AZGwEX9QaqRQDZyDN_bUKeRKV1OOZArXjL0,622
@@ -13,7 +13,7 @@ fal/rest_client.py,sha256=kGBGmuyHfX1lR910EoKCYPjsyU8MdXawT_cW2q8Sajc,568
13
13
  fal/sdk.py,sha256=_1aK9VSzHPoDPbLm3nbhE4213zI66qAsgYs1Y1Wc3J8,20077
14
14
  fal/sync.py,sha256=ZuIJA2-hTPNANG9B_NNJZUsO68EIdTH0dc9MzeVE2VU,4340
15
15
  fal/utils.py,sha256=MFDs-eO3rBgc3jqIwBpfBtvvK5tbzAYWMzHV-tTVLic,1754
16
- fal/workflows.py,sha256=4rjqL4xB6GHLJsqTplJmAvpd6uHZJ28sc8su33BFXEo,14682
16
+ fal/workflows.py,sha256=jx3tGy2R7cN6lLvOzT6lhhlcjmiq64iZls2smVrmQj0,14657
17
17
  fal/auth/__init__.py,sha256=r8iA2-5ih7-Fik3gEC4HEWNFbGoxpYnXpZu1icPIoS0,3561
18
18
  fal/auth/auth0.py,sha256=rSG1mgH-QGyKfzd7XyAaj1AYsWt-ho8Y_LZ-FUVWzh4,5421
19
19
  fal/auth/local.py,sha256=sndkM6vKpeVny6NHTacVlTbiIFqaksOmw0Viqs_RN1U,1790
@@ -21,7 +21,7 @@ fal/cli/__init__.py,sha256=padK4o0BFqq61kxAA1qQ0jYr2SuhA2mf90B3AaRkmJA,37
21
21
  fal/cli/apps.py,sha256=Dqcx7ewUNY6dh0bYqRlOCHVDzmkdpFxe9CNThEz7HX4,8144
22
22
  fal/cli/auth.py,sha256=--MhfHGwxmtHbRkGioyn1prKn_U-pBzbz0G_QeZou-U,1352
23
23
  fal/cli/debug.py,sha256=1doDNwoaPDfLQginGNBxpC20dZYs5UxIojflDvV1Q04,1342
24
- fal/cli/deploy.py,sha256=S_HIMLqDpGyzDdbiIxudRizwjGoAaHpN-sXcl2uCaQ4,4329
24
+ fal/cli/deploy.py,sha256=yx7QDv4PTrqLCUODgK3glMRs58of9nlCM1_a_GYaZBk,4783
25
25
  fal/cli/doctor.py,sha256=U4ne9LX5gQwNblsYQ27XdO8AYDgbYjTO39EtxhwexRM,983
26
26
  fal/cli/keys.py,sha256=-9N6ZY6rW-_IE9tpupgaBPDGjGdKB3HKqU2g9daM3Xc,3109
27
27
  fal/cli/main.py,sha256=MxETDhqIT37quMbmofSMxBcAFOhnEHjpQ_pYEtOhApM,1993
@@ -43,9 +43,9 @@ fal/toolkit/__init__.py,sha256=sV95wiUzKoiDqF9vDgq4q-BLa2sD6IpuKSqp5kdTQNE,658
43
43
  fal/toolkit/exceptions.py,sha256=elHZ7dHCJG5zlHGSBbz-ilkZe9QUvQMomJFi8Pt91LA,198
44
44
  fal/toolkit/optimize.py,sha256=p75sovF0SmRP6zxzpIaaOmqlxvXB_xEz3XPNf59EF7w,1339
45
45
  fal/toolkit/file/__init__.py,sha256=FbNl6wD-P0aSSTUwzHt4HujBXrbC3ABmaigPQA4hRfg,70
46
- fal/toolkit/file/file.py,sha256=r8PzNCgv8Gkj6s1zM0yW-pcMKIouyaiEH06iBue8MwM,6066
47
- fal/toolkit/file/types.py,sha256=9CqDh8SmNJNzfsrvtj468uo2SprJH9rOk8KMhhfU73c,1050
48
- fal/toolkit/file/providers/fal.py,sha256=ACxkfQ9kmMJ1xP8dNUHzkLkJJLZvoybTpVt8avGb8Nw,3747
46
+ fal/toolkit/file/file.py,sha256=S-So4RNSfcKgESFKnCFmQxdCpEov-JqbO2vIW73ZyC8,6136
47
+ fal/toolkit/file/types.py,sha256=bJCeV5NPcpJYJoglailiRgFsuNAfcextYA8Et5-XUag,1060
48
+ fal/toolkit/file/providers/fal.py,sha256=C0j2bRf_xwKNjwv4awdVCggQ-2fBNGPRClTeHbG79v4,4091
49
49
  fal/toolkit/file/providers/gcp.py,sha256=7Lg7BXoHKkFu0jkGv3_vKh2Ks6eRfDMbw31N3mvDUtk,1913
50
50
  fal/toolkit/file/providers/r2.py,sha256=YW5aJBOX41MQxfx1rA_f-IiJhAPMZ5md0cxBcg3y08I,2537
51
51
  fal/toolkit/image/__init__.py,sha256=qNLyXsBWysionUjbeWbohLqWlw3G_UpzunamkZd_JLQ,71
@@ -62,40 +62,61 @@ openapi_fal_rest/api/applications/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeR
62
62
  openapi_fal_rest/api/applications/app_metadata.py,sha256=GqG6Q7jt8Jcyhb3ms_6i0M1B3cy205y3_A8W-AGEapY,5120
63
63
  openapi_fal_rest/api/billing/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
64
64
  openapi_fal_rest/api/billing/get_user_details.py,sha256=2HQHRUQj8QwqSKgiV_USBdXCxGlfaVTBbLiPaDsMBUM,4013
65
+ openapi_fal_rest/api/comfy/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
66
+ openapi_fal_rest/api/comfy/create_workflow.py,sha256=3TTnMB3s2IQSMvECzQx6c68mcEO4ZwU8s8MfrQyCU7o,4689
67
+ openapi_fal_rest/api/comfy/delete_workflow.py,sha256=eiK1usnC16mUtRyrWrys-7nrMepEir9FxQaVb7BkVIs,4406
68
+ openapi_fal_rest/api/comfy/get_workflow.py,sha256=nAkEi8XnJGb1q7FySoqDEzVR1aIh28hK-ZedijbpUwc,4645
69
+ openapi_fal_rest/api/comfy/list_user_workflows.py,sha256=ty6OBZkR8pz6KJJZ4BbI_Gt-WWDRIDhFldOMkWp2_3s,5328
70
+ openapi_fal_rest/api/comfy/update_workflow.py,sha256=ACUt2IU22AR7MXLcA9ffFstzSB43YQ2X-HQ25YVw1p4,5322
65
71
  openapi_fal_rest/api/files/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
66
72
  openapi_fal_rest/api/files/check_dir_hash.py,sha256=zPNlOwG4YVvnhgfrleQtYLhI1lG0t8YQ1CU3TyvXvfk,4747
67
73
  openapi_fal_rest/api/files/upload_local_file.py,sha256=p2lM7hswGbs8KNLg1Pp6vwV7x-1PKtWX-aYmaHUHSDU,5649
74
+ openapi_fal_rest/api/users/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
75
+ openapi_fal_rest/api/users/get_current_user.py,sha256=PpOBI3q1mGjAjb-SMWbV6xKounZXWNlsO62ZxOa5Oys,3942
68
76
  openapi_fal_rest/api/workflows/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
69
- openapi_fal_rest/api/workflows/create_or_update_workflow_workflows_post.py,sha256=bS-CUo3CMsBxkXBEVOoa_GqL-EDgVMW9FHUMyYBneug,4611
70
- openapi_fal_rest/api/workflows/delete_workflow_workflows_user_id_workflow_name_delete.py,sha256=svJcV5q2e8caxuLJKIld3M7-raQFqSIxPNq58e3AgaA,4590
71
- openapi_fal_rest/api/workflows/execute_workflow_workflows_user_id_workflow_name_post.py,sha256=kofDDU3TEVQ8Fmua_K2-lk5xh16g6_FNFHQ0KzoFMcM,8743
72
- openapi_fal_rest/api/workflows/get_workflow_workflows_user_id_workflow_name_get.py,sha256=-E-TELi9Q_-yqobdHAcTHVm-8HithJRUGk7wc1mLA18,4763
73
- openapi_fal_rest/api/workflows/get_workflows_workflows_get.py,sha256=iJF3lNYp22p8-JbbBMDoHO9iXQB8779lSnH2fNimYP4,5242
74
- openapi_fal_rest/models/__init__.py,sha256=pGB91qXG3VDxob4DPAh3OMa2fyJFYBxc-jQ-9A4y3Gs,2037
77
+ openapi_fal_rest/api/workflows/create_workflow.py,sha256=ICeiqkVJtzuBp9BruZzMqgrqbZBiLmY_uVQhOWILZ-o,4571
78
+ openapi_fal_rest/api/workflows/delete_workflow.py,sha256=svJcV5q2e8caxuLJKIld3M7-raQFqSIxPNq58e3AgaA,4590
79
+ openapi_fal_rest/api/workflows/get_workflow.py,sha256=-E-TELi9Q_-yqobdHAcTHVm-8HithJRUGk7wc1mLA18,4763
80
+ openapi_fal_rest/api/workflows/list_user_workflows.py,sha256=aO7Wa0ogMgoKBDxbG7NMBbPs74Pp7XyM71b9mOuYEbc,5262
81
+ openapi_fal_rest/api/workflows/update_workflow.py,sha256=Q3-FnFnCGNBjYGgip-6L4QMWVOcZuODmAM1HPfKiYyI,5384
82
+ openapi_fal_rest/models/__init__.py,sha256=JNBQjkcf5E_vaeYvEtdEHzxSSk6H1d0Fop8s4Mk8R1c,2872
75
83
  openapi_fal_rest/models/app_metadata_response_app_metadata.py,sha256=1vx_5cp8V0jyE8iBRIe8TfngaeXMojfEpMCpT6i3qvs,1252
76
84
  openapi_fal_rest/models/body_upload_local_file.py,sha256=rOTEbYBXfwZk8TsywZWSPPQQEfJgvsLIufT6A40RJZs,1980
77
- openapi_fal_rest/models/customer_details.py,sha256=_zvJ_Y2uLowpXqhUnkcpoZpyIB0s8kc5pWSdlBA2_7o,3913
78
- openapi_fal_rest/models/execute_workflow_workflows_user_id_workflow_name_post_json_body_type_0.py,sha256=84MkDJeOgxwPozZZuP8Fb2dqlF57fmXuRGlrvMKxUew,1418
79
- openapi_fal_rest/models/execute_workflow_workflows_user_id_workflow_name_post_response_200_type_0.py,sha256=SAGhH0grz3tYISHqsTr-MeiKWqTQsi8gFwSK2ksBoqY,1433
85
+ openapi_fal_rest/models/comfy_workflow_detail.py,sha256=GR3Ft0iGlk3MTzJ-DyWJP0et2fxcS2aPMrbjzFd49kQ,2885
86
+ openapi_fal_rest/models/comfy_workflow_item.py,sha256=ZqFfqxr-BBWy-GBuPmyzzaSER6CaJFRIR2FevzV0OZs,2249
87
+ openapi_fal_rest/models/comfy_workflow_schema.py,sha256=SW8XYfYCZ0GUq5bOaxSeDrBh0cS-uA1jBajYV1mdj08,4586
88
+ openapi_fal_rest/models/comfy_workflow_schema_extra_data.py,sha256=DImMZQEmwPl3VTyZUK_dGIjwbhiQYYTbTizU3QB3LN8,1242
89
+ openapi_fal_rest/models/comfy_workflow_schema_fal_inputs.py,sha256=ZbM4bR77-Bzknwz6NBHSk0F3-oYAX8lxJ5dn1qUABKw,1242
90
+ openapi_fal_rest/models/comfy_workflow_schema_fal_inputs_dev_info.py,sha256=2n_NQZD5HfNa7-FPhoxGbrgCj5BbmYSZAPioGg35PWM,1283
91
+ openapi_fal_rest/models/comfy_workflow_schema_prompt.py,sha256=akFEhmHHaLiC3dJJcePKpnWF7G_G00ugl13lHVkRsGw,1224
92
+ openapi_fal_rest/models/current_user.py,sha256=MjEnWZGBs2TjyjeDOJ9QFF06phLxYcX50psEi86w7qY,4044
93
+ openapi_fal_rest/models/customer_details.py,sha256=dxo1c6Eh5Sht5cFxtWIzh52PYEF5N7_hpxaqiC7KhrE,4073
80
94
  openapi_fal_rest/models/hash_check.py,sha256=T9R7n4EdadCxbFUZvresZZFPYwDfyJMZVNxY6wIJEE8,1352
81
95
  openapi_fal_rest/models/http_validation_error.py,sha256=2nhqlv8RX2qp6VR7hb8-SKtzJWXSZ0J95ThW9J4agJo,2131
82
- openapi_fal_rest/models/lock_reason.py,sha256=3b_foCV6bZKvsbyic3hM1_qzvJk_9ZD_5mS1GzSawdw,703
96
+ openapi_fal_rest/models/lock_reason.py,sha256=f3m_JdFhY4pmSyYH9tL4fJmpzIzGIikLlOoc32wdLgk,846
97
+ openapi_fal_rest/models/page_comfy_workflow_item.py,sha256=kw6mYOcLkMv5MdfKme7IXzuhYmSlmwIIzmBJ3zD1grs,2877
83
98
  openapi_fal_rest/models/page_workflow_item.py,sha256=5DCUMQ2b8LAH8So6nQJW8mhlxZbedM4ixAJqbf-KZNE,2812
99
+ openapi_fal_rest/models/team_role.py,sha256=SY1MjPLsXeLE7nb6Zz9MzKucSLbO8fQVhugY7mjEvWg,185
100
+ openapi_fal_rest/models/typed_comfy_workflow.py,sha256=2UmQnZneQI0za4mwQSw4luzMseYyvdK5XtIBIQUtxj0,2170
101
+ openapi_fal_rest/models/typed_comfy_workflow_update.py,sha256=6ym6WKSvqxeiUnVhUX9JHWiWywe8ZDra7Hy6rJpV96c,2821
84
102
  openapi_fal_rest/models/typed_workflow.py,sha256=haE4Sa16s4iea_VNYtVR7cP3A8Z2ja2KNywYJhc6GmQ,2119
103
+ openapi_fal_rest/models/typed_workflow_update.py,sha256=u0omx2jSdf4UaFoio2IIJZuDckYSR4SJYF47zJ3bhPY,2767
104
+ openapi_fal_rest/models/user_member.py,sha256=WrErlZpCsQtLZVOJrdSpcIOqnBfEycig-oZVIu8KGeA,2212
85
105
  openapi_fal_rest/models/validation_error.py,sha256=I6tB-HbEOmE0ua27erDX5PX5YUynENv_dgPN3SrwTrQ,2091
86
- openapi_fal_rest/models/workflow_contents.py,sha256=TIockMwkpjeUjbWtZmtzcC327akwD4XgnTskgdsHQFQ,2703
106
+ openapi_fal_rest/models/workflow_contents.py,sha256=3n14xb_irIBWBrsbI0X3kKIPj8NNiWI4bwQb9m2sMmY,3542
107
+ openapi_fal_rest/models/workflow_contents_metadata.py,sha256=JNuIQ70mSHASUW4suVbr5Z-WZWzh_l7eQB6QWOT8xI0,1216
87
108
  openapi_fal_rest/models/workflow_contents_nodes.py,sha256=mMeQO_DlQZQPSwyGKTNC9eBovFVCVQNFbrB60k7tTtU,1695
88
109
  openapi_fal_rest/models/workflow_contents_output.py,sha256=2m4ITxXcQxTt8iiY5bos0QQW_uMYOGAR1xAcm1rzrcI,1206
89
- openapi_fal_rest/models/workflow_detail.py,sha256=lxlPkiOgc9_Dz6c0v3mDJNFXa4CWDkMWw9on-9McojE,4597
90
- openapi_fal_rest/models/workflow_detail_contents_type_0.py,sha256=DUQg0mDQKczL5g76rJMYvFK_RFcQaQPC1BoTr43eheA,1237
91
- openapi_fal_rest/models/workflow_item.py,sha256=M_8ojGsBpnKUe3l9yDnciPPgEjmfq1v-Bn9kVHPxT-0,1988
110
+ openapi_fal_rest/models/workflow_detail.py,sha256=DrCvgCaZJT-P8Zj48Iza3fF5wEh-Wo7MbGqfP7k33QM,2877
111
+ openapi_fal_rest/models/workflow_detail_contents.py,sha256=Dy2bxIuh4Sls30oRggbMA4QBnF-toWh_lJLu9mC-hkA,1206
112
+ openapi_fal_rest/models/workflow_item.py,sha256=fUCx9lM0USogxwn-ymxXt1uKakNxjGsSEcM04GXbYps,2584
92
113
  openapi_fal_rest/models/workflow_node.py,sha256=DZ3i-auxvm2cWFTBE52YSoLOEIVFvLPW9MyzyR91e78,1797
93
114
  openapi_fal_rest/models/workflow_node_type.py,sha256=-FzyeY2bxcNmizKbJI8joG7byRiPyAthdBLlioLH8Zw,161
94
115
  openapi_fal_rest/models/workflow_schema.py,sha256=4K5gsv9u9pxx2ItkffoyHeNjBBYf6ur5bN4m_zePZNY,2019
95
116
  openapi_fal_rest/models/workflow_schema_input.py,sha256=2OkOXWHTNsCXHWS6EGDFzcJKkW5FIap-2gfO233EvZQ,1191
96
117
  openapi_fal_rest/models/workflow_schema_output.py,sha256=EblwSPAGfWfYVWw_WSSaBzQVju296is9o28rMBAd0mc,1196
97
- fal-1.0.8.dist-info/METADATA,sha256=J6Lpic62ohISriecQ7IwHdL2PjZrNhrWVumFV7vhhJE,3777
98
- fal-1.0.8.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
99
- fal-1.0.8.dist-info/entry_points.txt,sha256=32zwTUC1U1E7nSTIGCoANQOQ3I7-qHG5wI6gsVz5pNU,37
100
- fal-1.0.8.dist-info/top_level.txt,sha256=r257X1L57oJL8_lM0tRrfGuXFwm66i1huwQygbpLmHw,21
101
- fal-1.0.8.dist-info/RECORD,,
118
+ fal-1.1.1.dist-info/METADATA,sha256=oygGKONaPZI7r2VFFwKzOyGfV2ljvWwFchw2Tz5UG3E,3777
119
+ fal-1.1.1.dist-info/WHEEL,sha256=mguMlWGMX-VHnMpKOjjQidIo1ssRlCFu4a4mBpz1s2M,91
120
+ fal-1.1.1.dist-info/entry_points.txt,sha256=32zwTUC1U1E7nSTIGCoANQOQ3I7-qHG5wI6gsVz5pNU,37
121
+ fal-1.1.1.dist-info/top_level.txt,sha256=r257X1L57oJL8_lM0tRrfGuXFwm66i1huwQygbpLmHw,21
122
+ fal-1.1.1.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.43.0)
2
+ Generator: setuptools (70.1.1)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
File without changes
@@ -0,0 +1,172 @@
1
+ from http import HTTPStatus
2
+ from typing import Any, Dict, Optional, Union
3
+
4
+ import httpx
5
+
6
+ from ... import errors
7
+ from ...client import Client
8
+ from ...models.comfy_workflow_detail import ComfyWorkflowDetail
9
+ from ...models.http_validation_error import HTTPValidationError
10
+ from ...models.typed_comfy_workflow import TypedComfyWorkflow
11
+ from ...types import Response
12
+
13
+
14
+ def _get_kwargs(
15
+ *,
16
+ client: Client,
17
+ json_body: TypedComfyWorkflow,
18
+ ) -> Dict[str, Any]:
19
+ url = "{}/comfy/".format(client.base_url)
20
+
21
+ headers: Dict[str, str] = client.get_headers()
22
+ cookies: Dict[str, Any] = client.get_cookies()
23
+
24
+ json_json_body = json_body.to_dict()
25
+
26
+ return {
27
+ "method": "post",
28
+ "url": url,
29
+ "headers": headers,
30
+ "cookies": cookies,
31
+ "timeout": client.get_timeout(),
32
+ "follow_redirects": client.follow_redirects,
33
+ "json": json_json_body,
34
+ }
35
+
36
+
37
+ def _parse_response(
38
+ *, client: Client, response: httpx.Response
39
+ ) -> Optional[Union[ComfyWorkflowDetail, HTTPValidationError]]:
40
+ if response.status_code == HTTPStatus.CREATED:
41
+ response_201 = ComfyWorkflowDetail.from_dict(response.json())
42
+
43
+ return response_201
44
+ if response.status_code == HTTPStatus.UNPROCESSABLE_ENTITY:
45
+ response_422 = HTTPValidationError.from_dict(response.json())
46
+
47
+ return response_422
48
+ if client.raise_on_unexpected_status:
49
+ raise errors.UnexpectedStatus(response.status_code, response.content)
50
+ else:
51
+ return None
52
+
53
+
54
+ def _build_response(
55
+ *, client: Client, response: httpx.Response
56
+ ) -> Response[Union[ComfyWorkflowDetail, HTTPValidationError]]:
57
+ return Response(
58
+ status_code=HTTPStatus(response.status_code),
59
+ content=response.content,
60
+ headers=response.headers,
61
+ parsed=_parse_response(client=client, response=response),
62
+ )
63
+
64
+
65
+ def sync_detailed(
66
+ *,
67
+ client: Client,
68
+ json_body: TypedComfyWorkflow,
69
+ ) -> Response[Union[ComfyWorkflowDetail, HTTPValidationError]]:
70
+ """Create Workflow
71
+
72
+ Args:
73
+ json_body (TypedComfyWorkflow):
74
+
75
+ Raises:
76
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
77
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
78
+
79
+ Returns:
80
+ Response[Union[ComfyWorkflowDetail, HTTPValidationError]]
81
+ """
82
+
83
+ kwargs = _get_kwargs(
84
+ client=client,
85
+ json_body=json_body,
86
+ )
87
+
88
+ response = httpx.request(
89
+ verify=client.verify_ssl,
90
+ **kwargs,
91
+ )
92
+
93
+ return _build_response(client=client, response=response)
94
+
95
+
96
+ def sync(
97
+ *,
98
+ client: Client,
99
+ json_body: TypedComfyWorkflow,
100
+ ) -> Optional[Union[ComfyWorkflowDetail, HTTPValidationError]]:
101
+ """Create Workflow
102
+
103
+ Args:
104
+ json_body (TypedComfyWorkflow):
105
+
106
+ Raises:
107
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
108
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
109
+
110
+ Returns:
111
+ Union[ComfyWorkflowDetail, HTTPValidationError]
112
+ """
113
+
114
+ return sync_detailed(
115
+ client=client,
116
+ json_body=json_body,
117
+ ).parsed
118
+
119
+
120
+ async def asyncio_detailed(
121
+ *,
122
+ client: Client,
123
+ json_body: TypedComfyWorkflow,
124
+ ) -> Response[Union[ComfyWorkflowDetail, HTTPValidationError]]:
125
+ """Create Workflow
126
+
127
+ Args:
128
+ json_body (TypedComfyWorkflow):
129
+
130
+ Raises:
131
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
132
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
133
+
134
+ Returns:
135
+ Response[Union[ComfyWorkflowDetail, HTTPValidationError]]
136
+ """
137
+
138
+ kwargs = _get_kwargs(
139
+ client=client,
140
+ json_body=json_body,
141
+ )
142
+
143
+ async with httpx.AsyncClient(verify=client.verify_ssl) as _client:
144
+ response = await _client.request(**kwargs)
145
+
146
+ return _build_response(client=client, response=response)
147
+
148
+
149
+ async def asyncio(
150
+ *,
151
+ client: Client,
152
+ json_body: TypedComfyWorkflow,
153
+ ) -> Optional[Union[ComfyWorkflowDetail, HTTPValidationError]]:
154
+ """Create Workflow
155
+
156
+ Args:
157
+ json_body (TypedComfyWorkflow):
158
+
159
+ Raises:
160
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
161
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
162
+
163
+ Returns:
164
+ Union[ComfyWorkflowDetail, HTTPValidationError]
165
+ """
166
+
167
+ return (
168
+ await asyncio_detailed(
169
+ client=client,
170
+ json_body=json_body,
171
+ )
172
+ ).parsed