fal 1.9.4__tar.gz → 1.11.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.

Potentially problematic release.


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

Files changed (174) hide show
  1. {fal-1.9.4/fal.egg-info → fal-1.11.0}/PKG-INFO +3 -3
  2. {fal-1.9.4 → fal-1.11.0/fal.egg-info}/PKG-INFO +3 -3
  3. {fal-1.9.4 → fal-1.11.0}/fal.egg-info/SOURCES.txt +2 -0
  4. {fal-1.9.4 → fal-1.11.0}/fal.egg-info/requires.txt +1 -1
  5. {fal-1.9.4 → fal-1.11.0}/pyproject.toml +1 -1
  6. {fal-1.9.4 → fal-1.11.0}/src/fal/_fal_version.py +2 -2
  7. {fal-1.9.4 → fal-1.11.0}/src/fal/api.py +12 -0
  8. fal-1.11.0/src/fal/cli/api.py +72 -0
  9. {fal-1.9.4 → fal-1.11.0}/src/fal/cli/apps.py +39 -1
  10. fal-1.11.0/src/fal/cli/cli_nested_json.py +421 -0
  11. {fal-1.9.4 → fal-1.11.0}/src/fal/cli/deploy.py +3 -3
  12. {fal-1.9.4 → fal-1.11.0}/src/fal/cli/main.py +14 -1
  13. {fal-1.9.4 → fal-1.11.0}/src/fal/container.py +6 -0
  14. {fal-1.9.4 → fal-1.11.0}/src/fal/sdk.py +10 -0
  15. {fal-1.9.4 → fal-1.11.0}/src/fal/toolkit/file/providers/fal.py +283 -0
  16. {fal-1.9.4 → fal-1.11.0}/tests/cli/test_apps.py +3 -0
  17. {fal-1.9.4 → fal-1.11.0}/tests/test_apps.py +61 -30
  18. {fal-1.9.4 → fal-1.11.0}/.gitignore +0 -0
  19. {fal-1.9.4 → fal-1.11.0}/Makefile +0 -0
  20. {fal-1.9.4 → fal-1.11.0}/README.md +0 -0
  21. {fal-1.9.4 → fal-1.11.0}/docs/conf.py +0 -0
  22. {fal-1.9.4 → fal-1.11.0}/docs/index.rst +0 -0
  23. {fal-1.9.4 → fal-1.11.0}/fal.egg-info/dependency_links.txt +0 -0
  24. {fal-1.9.4 → fal-1.11.0}/fal.egg-info/entry_points.txt +0 -0
  25. {fal-1.9.4 → fal-1.11.0}/fal.egg-info/top_level.txt +0 -0
  26. {fal-1.9.4 → fal-1.11.0}/openapi-fal-rest/README.md +0 -0
  27. {fal-1.9.4 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/__init__.py +0 -0
  28. {fal-1.9.4 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/api/__init__.py +0 -0
  29. {fal-1.9.4 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/api/applications/__init__.py +0 -0
  30. {fal-1.9.4 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/api/applications/app_metadata.py +0 -0
  31. {fal-1.9.4 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/api/billing/__init__.py +0 -0
  32. {fal-1.9.4 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/api/billing/get_user_details.py +0 -0
  33. {fal-1.9.4 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/api/comfy/__init__.py +0 -0
  34. {fal-1.9.4 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/api/comfy/create_workflow.py +0 -0
  35. {fal-1.9.4 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/api/comfy/delete_workflow.py +0 -0
  36. {fal-1.9.4 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/api/comfy/get_workflow.py +0 -0
  37. {fal-1.9.4 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/api/comfy/list_user_workflows.py +0 -0
  38. {fal-1.9.4 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/api/comfy/update_workflow.py +0 -0
  39. {fal-1.9.4 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/api/files/__init__.py +0 -0
  40. {fal-1.9.4 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/api/files/check_dir_hash.py +0 -0
  41. {fal-1.9.4 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/api/files/upload_local_file.py +0 -0
  42. {fal-1.9.4 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/api/users/__init__.py +0 -0
  43. {fal-1.9.4 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/api/users/get_current_user.py +0 -0
  44. {fal-1.9.4 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/api/workflows/__init__.py +0 -0
  45. {fal-1.9.4 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/api/workflows/create_workflow.py +0 -0
  46. {fal-1.9.4 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/api/workflows/delete_workflow.py +0 -0
  47. {fal-1.9.4 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/api/workflows/get_workflow.py +0 -0
  48. {fal-1.9.4 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/api/workflows/list_user_workflows.py +0 -0
  49. {fal-1.9.4 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/api/workflows/update_workflow.py +0 -0
  50. {fal-1.9.4 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/client.py +0 -0
  51. {fal-1.9.4 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/errors.py +0 -0
  52. {fal-1.9.4 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/models/__init__.py +0 -0
  53. {fal-1.9.4 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/models/app_metadata_response_app_metadata.py +0 -0
  54. {fal-1.9.4 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/models/body_upload_local_file.py +0 -0
  55. {fal-1.9.4 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/models/comfy_workflow_detail.py +0 -0
  56. {fal-1.9.4 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/models/comfy_workflow_item.py +0 -0
  57. {fal-1.9.4 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/models/comfy_workflow_schema.py +0 -0
  58. {fal-1.9.4 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/models/comfy_workflow_schema_extra_data.py +0 -0
  59. {fal-1.9.4 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/models/comfy_workflow_schema_fal_inputs.py +0 -0
  60. {fal-1.9.4 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/models/comfy_workflow_schema_fal_inputs_dev_info.py +0 -0
  61. {fal-1.9.4 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/models/comfy_workflow_schema_prompt.py +0 -0
  62. {fal-1.9.4 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/models/current_user.py +0 -0
  63. {fal-1.9.4 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/models/customer_details.py +0 -0
  64. {fal-1.9.4 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/models/hash_check.py +0 -0
  65. {fal-1.9.4 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/models/http_validation_error.py +0 -0
  66. {fal-1.9.4 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/models/lock_reason.py +0 -0
  67. {fal-1.9.4 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/models/page_comfy_workflow_item.py +0 -0
  68. {fal-1.9.4 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/models/page_workflow_item.py +0 -0
  69. {fal-1.9.4 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/models/team_role.py +0 -0
  70. {fal-1.9.4 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/models/typed_comfy_workflow.py +0 -0
  71. {fal-1.9.4 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/models/typed_comfy_workflow_update.py +0 -0
  72. {fal-1.9.4 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/models/typed_workflow.py +0 -0
  73. {fal-1.9.4 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/models/typed_workflow_update.py +0 -0
  74. {fal-1.9.4 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/models/user_member.py +0 -0
  75. {fal-1.9.4 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/models/validation_error.py +0 -0
  76. {fal-1.9.4 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/models/workflow_contents.py +0 -0
  77. {fal-1.9.4 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/models/workflow_contents_metadata.py +0 -0
  78. {fal-1.9.4 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/models/workflow_contents_nodes.py +0 -0
  79. {fal-1.9.4 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/models/workflow_contents_output.py +0 -0
  80. {fal-1.9.4 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/models/workflow_detail.py +0 -0
  81. {fal-1.9.4 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/models/workflow_detail_contents.py +0 -0
  82. {fal-1.9.4 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/models/workflow_item.py +0 -0
  83. {fal-1.9.4 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/models/workflow_node.py +0 -0
  84. {fal-1.9.4 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/models/workflow_node_type.py +0 -0
  85. {fal-1.9.4 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/models/workflow_schema.py +0 -0
  86. {fal-1.9.4 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/models/workflow_schema_input.py +0 -0
  87. {fal-1.9.4 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/models/workflow_schema_output.py +0 -0
  88. {fal-1.9.4 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/py.typed +0 -0
  89. {fal-1.9.4 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/types.py +0 -0
  90. {fal-1.9.4 → fal-1.11.0}/openapi-fal-rest/pyproject.toml +0 -0
  91. {fal-1.9.4 → fal-1.11.0}/openapi_rest.config.yaml +0 -0
  92. {fal-1.9.4 → fal-1.11.0}/setup.cfg +0 -0
  93. {fal-1.9.4 → fal-1.11.0}/src/fal/__init__.py +0 -0
  94. {fal-1.9.4 → fal-1.11.0}/src/fal/__main__.py +0 -0
  95. {fal-1.9.4 → fal-1.11.0}/src/fal/_serialization.py +0 -0
  96. {fal-1.9.4 → fal-1.11.0}/src/fal/_version.py +0 -0
  97. {fal-1.9.4 → fal-1.11.0}/src/fal/app.py +0 -0
  98. {fal-1.9.4 → fal-1.11.0}/src/fal/apps.py +0 -0
  99. {fal-1.9.4 → fal-1.11.0}/src/fal/auth/__init__.py +0 -0
  100. {fal-1.9.4 → fal-1.11.0}/src/fal/auth/auth0.py +0 -0
  101. {fal-1.9.4 → fal-1.11.0}/src/fal/auth/local.py +0 -0
  102. {fal-1.9.4 → fal-1.11.0}/src/fal/cli/__init__.py +0 -0
  103. {fal-1.9.4 → fal-1.11.0}/src/fal/cli/_utils.py +0 -0
  104. {fal-1.9.4 → fal-1.11.0}/src/fal/cli/auth.py +0 -0
  105. {fal-1.9.4 → fal-1.11.0}/src/fal/cli/create.py +0 -0
  106. {fal-1.9.4 → fal-1.11.0}/src/fal/cli/debug.py +0 -0
  107. {fal-1.9.4 → fal-1.11.0}/src/fal/cli/doctor.py +0 -0
  108. {fal-1.9.4 → fal-1.11.0}/src/fal/cli/keys.py +0 -0
  109. {fal-1.9.4 → fal-1.11.0}/src/fal/cli/parser.py +0 -0
  110. {fal-1.9.4 → fal-1.11.0}/src/fal/cli/profile.py +0 -0
  111. {fal-1.9.4 → fal-1.11.0}/src/fal/cli/run.py +0 -0
  112. {fal-1.9.4 → fal-1.11.0}/src/fal/cli/runners.py +0 -0
  113. {fal-1.9.4 → fal-1.11.0}/src/fal/cli/secrets.py +0 -0
  114. {fal-1.9.4 → fal-1.11.0}/src/fal/config.py +0 -0
  115. {fal-1.9.4 → fal-1.11.0}/src/fal/console/__init__.py +0 -0
  116. {fal-1.9.4 → fal-1.11.0}/src/fal/console/icons.py +0 -0
  117. {fal-1.9.4 → fal-1.11.0}/src/fal/console/ux.py +0 -0
  118. {fal-1.9.4 → fal-1.11.0}/src/fal/exceptions/__init__.py +0 -0
  119. {fal-1.9.4 → fal-1.11.0}/src/fal/exceptions/_base.py +0 -0
  120. {fal-1.9.4 → fal-1.11.0}/src/fal/exceptions/_cuda.py +0 -0
  121. {fal-1.9.4 → fal-1.11.0}/src/fal/exceptions/auth.py +0 -0
  122. {fal-1.9.4 → fal-1.11.0}/src/fal/files.py +0 -0
  123. {fal-1.9.4 → fal-1.11.0}/src/fal/flags.py +0 -0
  124. {fal-1.9.4 → fal-1.11.0}/src/fal/logging/__init__.py +0 -0
  125. {fal-1.9.4 → fal-1.11.0}/src/fal/logging/isolate.py +0 -0
  126. {fal-1.9.4 → fal-1.11.0}/src/fal/logging/style.py +0 -0
  127. {fal-1.9.4 → fal-1.11.0}/src/fal/logging/trace.py +0 -0
  128. {fal-1.9.4 → fal-1.11.0}/src/fal/logging/user.py +0 -0
  129. {fal-1.9.4 → fal-1.11.0}/src/fal/py.typed +0 -0
  130. {fal-1.9.4 → fal-1.11.0}/src/fal/rest_client.py +0 -0
  131. {fal-1.9.4 → fal-1.11.0}/src/fal/sync.py +0 -0
  132. {fal-1.9.4 → fal-1.11.0}/src/fal/toolkit/__init__.py +0 -0
  133. {fal-1.9.4 → fal-1.11.0}/src/fal/toolkit/exceptions.py +0 -0
  134. {fal-1.9.4 → fal-1.11.0}/src/fal/toolkit/file/__init__.py +0 -0
  135. {fal-1.9.4 → fal-1.11.0}/src/fal/toolkit/file/file.py +0 -0
  136. {fal-1.9.4 → fal-1.11.0}/src/fal/toolkit/file/providers/gcp.py +0 -0
  137. {fal-1.9.4 → fal-1.11.0}/src/fal/toolkit/file/providers/r2.py +0 -0
  138. {fal-1.9.4 → fal-1.11.0}/src/fal/toolkit/file/providers/s3.py +0 -0
  139. {fal-1.9.4 → fal-1.11.0}/src/fal/toolkit/file/types.py +0 -0
  140. {fal-1.9.4 → fal-1.11.0}/src/fal/toolkit/image/__init__.py +0 -0
  141. {fal-1.9.4 → fal-1.11.0}/src/fal/toolkit/image/image.py +0 -0
  142. {fal-1.9.4 → fal-1.11.0}/src/fal/toolkit/image/nsfw_filter/__init__.py +0 -0
  143. {fal-1.9.4 → fal-1.11.0}/src/fal/toolkit/image/nsfw_filter/env.py +0 -0
  144. {fal-1.9.4 → fal-1.11.0}/src/fal/toolkit/image/nsfw_filter/inference.py +0 -0
  145. {fal-1.9.4 → fal-1.11.0}/src/fal/toolkit/image/nsfw_filter/model.py +0 -0
  146. {fal-1.9.4 → fal-1.11.0}/src/fal/toolkit/image/nsfw_filter/requirements.txt +0 -0
  147. {fal-1.9.4 → fal-1.11.0}/src/fal/toolkit/image/safety_checker.py +0 -0
  148. {fal-1.9.4 → fal-1.11.0}/src/fal/toolkit/optimize.py +0 -0
  149. {fal-1.9.4 → fal-1.11.0}/src/fal/toolkit/types.py +0 -0
  150. {fal-1.9.4 → fal-1.11.0}/src/fal/toolkit/utils/__init__.py +0 -0
  151. {fal-1.9.4 → fal-1.11.0}/src/fal/toolkit/utils/download_utils.py +0 -0
  152. {fal-1.9.4 → fal-1.11.0}/src/fal/toolkit/utils/retry.py +0 -0
  153. {fal-1.9.4 → fal-1.11.0}/src/fal/utils.py +0 -0
  154. {fal-1.9.4 → fal-1.11.0}/src/fal/workflows.py +0 -0
  155. {fal-1.9.4 → fal-1.11.0}/tests/__init__.py +0 -0
  156. {fal-1.9.4 → fal-1.11.0}/tests/assets/cat.png +0 -0
  157. {fal-1.9.4 → fal-1.11.0}/tests/cli/__init__.py +0 -0
  158. {fal-1.9.4 → fal-1.11.0}/tests/cli/test_auth.py +0 -0
  159. {fal-1.9.4 → fal-1.11.0}/tests/cli/test_deploy.py +0 -0
  160. {fal-1.9.4 → fal-1.11.0}/tests/cli/test_keys.py +0 -0
  161. {fal-1.9.4 → fal-1.11.0}/tests/cli/test_run.py +0 -0
  162. {fal-1.9.4 → fal-1.11.0}/tests/cli/test_secrets.py +0 -0
  163. {fal-1.9.4 → fal-1.11.0}/tests/conftest.py +0 -0
  164. {fal-1.9.4 → fal-1.11.0}/tests/integration_test.py +0 -0
  165. {fal-1.9.4 → fal-1.11.0}/tests/mainify_package/__init__.py +0 -0
  166. {fal-1.9.4 → fal-1.11.0}/tests/mainify_package/impl.py +0 -0
  167. {fal-1.9.4 → fal-1.11.0}/tests/mainify_package/utils.py +0 -0
  168. {fal-1.9.4 → fal-1.11.0}/tests/mainify_target.py +0 -0
  169. {fal-1.9.4 → fal-1.11.0}/tests/test_stability.py +0 -0
  170. {fal-1.9.4 → fal-1.11.0}/tests/toolkit/file_test.py +0 -0
  171. {fal-1.9.4 → fal-1.11.0}/tests/toolkit/image_test.py +0 -0
  172. {fal-1.9.4 → fal-1.11.0}/tests/toolkit/test_types.py +0 -0
  173. {fal-1.9.4 → fal-1.11.0}/tests/toolkit/utils/retry.py +0 -0
  174. {fal-1.9.4 → fal-1.11.0}/tools/demo_script.py +0 -0
@@ -1,12 +1,12 @@
1
- Metadata-Version: 2.2
1
+ Metadata-Version: 2.4
2
2
  Name: fal
3
- Version: 1.9.4
3
+ Version: 1.11.0
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
7
7
  Description-Content-Type: text/markdown
8
8
  Requires-Dist: isolate[build]<0.17.0,>=0.16.1
9
- Requires-Dist: isolate-proto<0.7.0,>=0.6.7
9
+ Requires-Dist: isolate-proto<0.8.0,>=0.7.0
10
10
  Requires-Dist: grpcio==1.64.0
11
11
  Requires-Dist: dill==0.3.7
12
12
  Requires-Dist: cloudpickle==3.0.0
@@ -1,12 +1,12 @@
1
- Metadata-Version: 2.2
1
+ Metadata-Version: 2.4
2
2
  Name: fal
3
- Version: 1.9.4
3
+ Version: 1.11.0
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
7
7
  Description-Content-Type: text/markdown
8
8
  Requires-Dist: isolate[build]<0.17.0,>=0.16.1
9
- Requires-Dist: isolate-proto<0.7.0,>=0.6.7
9
+ Requires-Dist: isolate-proto<0.8.0,>=0.7.0
10
10
  Requires-Dist: grpcio==1.64.0
11
11
  Requires-Dist: dill==0.3.7
12
12
  Requires-Dist: cloudpickle==3.0.0
@@ -99,8 +99,10 @@ src/fal/auth/auth0.py
99
99
  src/fal/auth/local.py
100
100
  src/fal/cli/__init__.py
101
101
  src/fal/cli/_utils.py
102
+ src/fal/cli/api.py
102
103
  src/fal/cli/apps.py
103
104
  src/fal/cli/auth.py
105
+ src/fal/cli/cli_nested_json.py
104
106
  src/fal/cli/create.py
105
107
  src/fal/cli/debug.py
106
108
  src/fal/cli/deploy.py
@@ -1,5 +1,5 @@
1
1
  isolate[build]<0.17.0,>=0.16.1
2
- isolate-proto<0.7.0,>=0.6.7
2
+ isolate-proto<0.8.0,>=0.7.0
3
3
  grpcio==1.64.0
4
4
  dill==0.3.7
5
5
  cloudpickle==3.0.0
@@ -23,7 +23,7 @@ readme = "README.md"
23
23
  requires-python = ">=3.8"
24
24
  dependencies = [
25
25
  "isolate[build]>=0.16.1,<0.17.0",
26
- "isolate-proto>=0.6.7,<0.7.0",
26
+ "isolate-proto>=0.7.0,<0.8.0",
27
27
  "grpcio==1.64.0",
28
28
  "dill==0.3.7",
29
29
  "cloudpickle==3.0.0",
@@ -17,5 +17,5 @@ __version__: str
17
17
  __version_tuple__: VERSION_TUPLE
18
18
  version_tuple: VERSION_TUPLE
19
19
 
20
- __version__ = version = '1.9.4'
21
- __version_tuple__ = version_tuple = (1, 9, 4)
20
+ __version__ = version = '1.11.0'
21
+ __version_tuple__ = version_tuple = (1, 11, 0)
@@ -53,6 +53,7 @@ from fal.exceptions import (
53
53
  from fal.exceptions._cuda import _is_cuda_oom_exception
54
54
  from fal.logging.isolate import IsolateLogPrinter
55
55
  from fal.sdk import (
56
+ FAL_SERVERLESS_DEFAULT_CONCURRENCY_BUFFER,
56
57
  FAL_SERVERLESS_DEFAULT_KEEP_ALIVE,
57
58
  FAL_SERVERLESS_DEFAULT_MAX_MULTIPLEXING,
58
59
  FAL_SERVERLESS_DEFAULT_MIN_CONCURRENCY,
@@ -400,6 +401,7 @@ class FalServerlessHost(Host):
400
401
  "keep_alive",
401
402
  "max_concurrency",
402
403
  "min_concurrency",
404
+ "concurrency_buffer",
403
405
  "max_multiplexing",
404
406
  "setup_function",
405
407
  "metadata",
@@ -451,6 +453,7 @@ class FalServerlessHost(Host):
451
453
  scheduler_options = options.host.get("_scheduler_options", None)
452
454
  max_concurrency = options.host.get("max_concurrency")
453
455
  min_concurrency = options.host.get("min_concurrency")
456
+ concurrency_buffer = options.host.get("concurrency_buffer")
454
457
  max_multiplexing = options.host.get("max_multiplexing")
455
458
  exposed_port = options.get_exposed_port()
456
459
  request_timeout = options.host.get("request_timeout")
@@ -466,6 +469,7 @@ class FalServerlessHost(Host):
466
469
  max_multiplexing=max_multiplexing,
467
470
  max_concurrency=max_concurrency,
468
471
  min_concurrency=min_concurrency,
472
+ concurrency_buffer=concurrency_buffer,
469
473
  request_timeout=request_timeout,
470
474
  startup_timeout=startup_timeout,
471
475
  )
@@ -523,6 +527,7 @@ class FalServerlessHost(Host):
523
527
  keep_alive = options.host.get("keep_alive", FAL_SERVERLESS_DEFAULT_KEEP_ALIVE)
524
528
  max_concurrency = options.host.get("max_concurrency")
525
529
  min_concurrency = options.host.get("min_concurrency")
530
+ concurrency_buffer = options.host.get("concurrency_buffer")
526
531
  max_multiplexing = options.host.get("max_multiplexing")
527
532
  base_image = options.host.get("_base_image", None)
528
533
  scheduler = options.host.get("_scheduler", None)
@@ -542,6 +547,7 @@ class FalServerlessHost(Host):
542
547
  max_multiplexing=max_multiplexing,
543
548
  max_concurrency=max_concurrency,
544
549
  min_concurrency=min_concurrency,
550
+ concurrency_buffer=concurrency_buffer,
545
551
  request_timeout=request_timeout,
546
552
  startup_timeout=startup_timeout,
547
553
  )
@@ -709,6 +715,7 @@ def function(
709
715
  keep_alive: int = FAL_SERVERLESS_DEFAULT_KEEP_ALIVE,
710
716
  max_multiplexing: int = FAL_SERVERLESS_DEFAULT_MAX_MULTIPLEXING,
711
717
  min_concurrency: int = FAL_SERVERLESS_DEFAULT_MIN_CONCURRENCY,
718
+ concurrency_buffer: int = FAL_SERVERLESS_DEFAULT_CONCURRENCY_BUFFER,
712
719
  request_timeout: int | None = None,
713
720
  startup_timeout: int | None = None,
714
721
  setup_function: Callable[..., None] | None = None,
@@ -737,6 +744,7 @@ def function(
737
744
  keep_alive: int = FAL_SERVERLESS_DEFAULT_KEEP_ALIVE,
738
745
  max_multiplexing: int = FAL_SERVERLESS_DEFAULT_MAX_MULTIPLEXING,
739
746
  min_concurrency: int = FAL_SERVERLESS_DEFAULT_MIN_CONCURRENCY,
747
+ concurrency_buffer: int = FAL_SERVERLESS_DEFAULT_CONCURRENCY_BUFFER,
740
748
  request_timeout: int | None = None,
741
749
  startup_timeout: int | None = None,
742
750
  setup_function: Callable[..., None] | None = None,
@@ -815,6 +823,7 @@ def function(
815
823
  keep_alive: int = FAL_SERVERLESS_DEFAULT_KEEP_ALIVE,
816
824
  max_multiplexing: int = FAL_SERVERLESS_DEFAULT_MAX_MULTIPLEXING,
817
825
  min_concurrency: int = FAL_SERVERLESS_DEFAULT_MIN_CONCURRENCY,
826
+ concurrency_buffer: int = FAL_SERVERLESS_DEFAULT_CONCURRENCY_BUFFER,
818
827
  request_timeout: int | None = None,
819
828
  startup_timeout: int | None = None,
820
829
  setup_function: Callable[..., None] | None = None,
@@ -848,6 +857,7 @@ def function(
848
857
  keep_alive: int = FAL_SERVERLESS_DEFAULT_KEEP_ALIVE,
849
858
  max_multiplexing: int = FAL_SERVERLESS_DEFAULT_MAX_MULTIPLEXING,
850
859
  min_concurrency: int = FAL_SERVERLESS_DEFAULT_MIN_CONCURRENCY,
860
+ concurrency_buffer: int = FAL_SERVERLESS_DEFAULT_CONCURRENCY_BUFFER,
851
861
  request_timeout: int | None = None,
852
862
  startup_timeout: int | None = None,
853
863
  setup_function: Callable[..., None] | None = None,
@@ -875,6 +885,7 @@ def function(
875
885
  keep_alive: int = FAL_SERVERLESS_DEFAULT_KEEP_ALIVE,
876
886
  max_multiplexing: int = FAL_SERVERLESS_DEFAULT_MAX_MULTIPLEXING,
877
887
  min_concurrency: int = FAL_SERVERLESS_DEFAULT_MIN_CONCURRENCY,
888
+ concurrency_buffer: int = FAL_SERVERLESS_DEFAULT_CONCURRENCY_BUFFER,
878
889
  request_timeout: int | None = None,
879
890
  startup_timeout: int | None = None,
880
891
  setup_function: Callable[..., None] | None = None,
@@ -902,6 +913,7 @@ def function(
902
913
  keep_alive: int = FAL_SERVERLESS_DEFAULT_KEEP_ALIVE,
903
914
  max_multiplexing: int = FAL_SERVERLESS_DEFAULT_MAX_MULTIPLEXING,
904
915
  min_concurrency: int = FAL_SERVERLESS_DEFAULT_MIN_CONCURRENCY,
916
+ concurrency_buffer: int = FAL_SERVERLESS_DEFAULT_CONCURRENCY_BUFFER,
905
917
  request_timeout: int | None = None,
906
918
  startup_timeout: int | None = None,
907
919
  setup_function: Callable[..., None] | None = None,
@@ -0,0 +1,72 @@
1
+ import re
2
+
3
+ import rich
4
+
5
+ import fal.apps
6
+
7
+ # = or := only
8
+ KV_SPLIT_RE = re.compile(r"(=|:=)")
9
+
10
+
11
+ def _api(args):
12
+ """Handle the api command execution."""
13
+ from rich.console import Group
14
+ from rich.live import Live
15
+ from rich.panel import Panel
16
+ from rich.text import Text
17
+
18
+ from . import cli_nested_json
19
+
20
+ params = [KV_SPLIT_RE.split(param) for param in args.params]
21
+ params = cli_nested_json.interpret_nested_json( # type: ignore
22
+ [(key, value) for key, _, value in params]
23
+ )
24
+
25
+ handle = fal.apps.submit(args.model_id, params) # type: ignore
26
+ logs = [] # type: ignore
27
+
28
+ with Live(auto_refresh=False) as live:
29
+ for event in handle.iter_events(logs=True):
30
+ if isinstance(event, fal.apps.Queued):
31
+ status = Text(f"⏳ Queued (position: {event.position})", style="yellow")
32
+ elif isinstance(event, fal.apps.InProgress):
33
+ status = Text("🔄 In Progress", style="blue")
34
+ if event.logs:
35
+ logs.extend(log.get("message", str(log)) for log in event.logs)
36
+ logs = logs[-10:] # Keep only last 10 logs
37
+ else:
38
+ status = Text("✅ Done", style="green")
39
+
40
+ status_panel = Panel(status, title="Status")
41
+ logs_panel = Panel("\n".join(logs), title="Logs")
42
+
43
+ live.update(Group(status_panel, logs_panel))
44
+ live.refresh()
45
+
46
+ # Show final result
47
+ result = handle.get()
48
+ live.update(rich.pretty.Pretty(result))
49
+
50
+
51
+ def add_parser(main_subparsers, parents):
52
+ """Add the api command to the main parser."""
53
+ api_help = "Call a fal API endpoint directly"
54
+ parser = main_subparsers.add_parser(
55
+ "api",
56
+ description=api_help,
57
+ help=api_help,
58
+ parents=parents,
59
+ )
60
+
61
+ parser.add_argument(
62
+ "model_id",
63
+ help="Name of the Model ID to call",
64
+ )
65
+
66
+ parser.add_argument(
67
+ "params",
68
+ nargs="*",
69
+ help="Key-value pairs (e.g. key=value or nested[a][b]=value)",
70
+ )
71
+
72
+ parser.set_defaults(func=_api)
@@ -17,6 +17,7 @@ def _apps_table(apps: list[AliasInfo]):
17
17
  table.add_column("Auth")
18
18
  table.add_column("Min Concurrency")
19
19
  table.add_column("Max Concurrency")
20
+ table.add_column("Concurrency Buffer")
20
21
  table.add_column("Max Multiplexing")
21
22
  table.add_column("Keep Alive")
22
23
  table.add_column("Request Timeout")
@@ -32,6 +33,7 @@ def _apps_table(apps: list[AliasInfo]):
32
33
  app.auth_mode,
33
34
  str(app.min_concurrency),
34
35
  str(app.max_concurrency),
36
+ str(app.concurrency_buffer),
35
37
  str(app.max_multiplexing),
36
38
  str(app.keep_alive),
37
39
  str(app.request_timeout),
@@ -50,6 +52,15 @@ def _list(args):
50
52
  client = FalServerlessClient(args.host)
51
53
  with client.connect() as connection:
52
54
  apps = connection.list_aliases()
55
+
56
+ if args.filter:
57
+ apps = [app for app in apps if args.filter in app.alias]
58
+
59
+ if args.sort_by_runners:
60
+ apps.sort(key=lambda x: x.active_runners)
61
+ else:
62
+ apps.sort(key=lambda x: x.alias)
63
+
53
64
  table = _apps_table(apps)
54
65
 
55
66
  args.console.print(table)
@@ -63,6 +74,16 @@ def _add_list_parser(subparsers, parents):
63
74
  help=list_help,
64
75
  parents=parents,
65
76
  )
77
+ parser.add_argument(
78
+ "--sort-by-runners",
79
+ action="store_true",
80
+ help="Sort by number of runners ascending",
81
+ )
82
+ parser.add_argument(
83
+ "--filter",
84
+ type=str,
85
+ help="Filter applications by alias contents",
86
+ )
66
87
  parser.set_defaults(func=_list)
67
88
 
68
89
 
@@ -130,6 +151,7 @@ def _scale(args):
130
151
  and args.max_multiplexing is None
131
152
  and args.max_concurrency is None
132
153
  and args.min_concurrency is None
154
+ and args.concurrency_buffer is None
133
155
  and args.request_timeout is None
134
156
  and args.startup_timeout is None
135
157
  and args.machine_types is None
@@ -144,6 +166,7 @@ def _scale(args):
144
166
  max_multiplexing=args.max_multiplexing,
145
167
  max_concurrency=args.max_concurrency,
146
168
  min_concurrency=args.min_concurrency,
169
+ concurrency_buffer=args.concurrency_buffer,
147
170
  request_timeout=args.request_timeout,
148
171
  startup_timeout=args.startup_timeout,
149
172
  machine_types=args.machine_types,
@@ -186,6 +209,11 @@ def _add_scale_parser(subparsers, parents):
186
209
  type=int,
187
210
  help="Minimum concurrency",
188
211
  )
212
+ parser.add_argument(
213
+ "--concurrency-buffer",
214
+ type=int,
215
+ help="Concurrency buffer",
216
+ )
189
217
  parser.add_argument(
190
218
  "--request-timeout",
191
219
  type=int,
@@ -258,13 +286,23 @@ def _runners(args):
258
286
  table = Table()
259
287
  table.add_column("Runner ID")
260
288
  table.add_column("In Flight Requests")
261
- table.add_column("Expires in")
289
+ table.add_column("Missing Leases")
290
+ table.add_column("Expires In")
262
291
  table.add_column("Uptime")
263
292
 
264
293
  for runner in runners:
294
+ num_leases_with_request = len(
295
+ [
296
+ lease
297
+ for lease in runner.external_metadata.get("leases", [])
298
+ if lease.get("request_id") is not None
299
+ ]
300
+ )
301
+
265
302
  table.add_row(
266
303
  runner.runner_id,
267
304
  str(runner.in_flight_requests),
305
+ str(runner.in_flight_requests - num_leases_with_request),
268
306
  (
269
307
  "N/A (active)"
270
308
  if runner.expiration_countdown is None