فهرست منبع

Merge remote-tracking branch 'upstream/main' into minify-state-names-v2

Benedikt Bartscher 6 ماه پیش
والد
کامیت
d8def13530

+ 119 - 111
poetry.lock

@@ -1656,22 +1656,19 @@ files = [
 
 
 [[package]]
 [[package]]
 name = "pydantic"
 name = "pydantic"
-version = "2.9.2"
+version = "2.10.1"
 description = "Data validation using Python type hints"
 description = "Data validation using Python type hints"
 optional = false
 optional = false
 python-versions = ">=3.8"
 python-versions = ">=3.8"
 files = [
 files = [
-    {file = "pydantic-2.9.2-py3-none-any.whl", hash = "sha256:f048cec7b26778210e28a0459867920654d48e5e62db0958433636cde4254f12"},
-    {file = "pydantic-2.9.2.tar.gz", hash = "sha256:d155cef71265d1e9807ed1c32b4c8deec042a44a50a4188b25ac67ecd81a9c0f"},
+    {file = "pydantic-2.10.1-py3-none-any.whl", hash = "sha256:a8d20db84de64cf4a7d59e899c2caf0fe9d660c7cfc482528e7020d7dd189a7e"},
+    {file = "pydantic-2.10.1.tar.gz", hash = "sha256:a4daca2dc0aa429555e0656d6bf94873a7dc5f54ee42b1f5873d666fb3f35560"},
 ]
 ]
 
 
 [package.dependencies]
 [package.dependencies]
 annotated-types = ">=0.6.0"
 annotated-types = ">=0.6.0"
-pydantic-core = "2.23.4"
-typing-extensions = [
-    {version = ">=4.6.1", markers = "python_version < \"3.13\""},
-    {version = ">=4.12.2", markers = "python_version >= \"3.13\""},
-]
+pydantic-core = "2.27.1"
+typing-extensions = ">=4.12.2"
 
 
 [package.extras]
 [package.extras]
 email = ["email-validator (>=2.0.0)"]
 email = ["email-validator (>=2.0.0)"]
@@ -1679,100 +1676,111 @@ timezone = ["tzdata"]
 
 
 [[package]]
 [[package]]
 name = "pydantic-core"
 name = "pydantic-core"
-version = "2.23.4"
+version = "2.27.1"
 description = "Core functionality for Pydantic validation and serialization"
 description = "Core functionality for Pydantic validation and serialization"
 optional = false
 optional = false
 python-versions = ">=3.8"
 python-versions = ">=3.8"
 files = [
 files = [
-    {file = "pydantic_core-2.23.4-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:b10bd51f823d891193d4717448fab065733958bdb6a6b351967bd349d48d5c9b"},
-    {file = "pydantic_core-2.23.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:4fc714bdbfb534f94034efaa6eadd74e5b93c8fa6315565a222f7b6f42ca1166"},
-    {file = "pydantic_core-2.23.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:63e46b3169866bd62849936de036f901a9356e36376079b05efa83caeaa02ceb"},
-    {file = "pydantic_core-2.23.4-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ed1a53de42fbe34853ba90513cea21673481cd81ed1be739f7f2efb931b24916"},
-    {file = "pydantic_core-2.23.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cfdd16ab5e59fc31b5e906d1a3f666571abc367598e3e02c83403acabc092e07"},
-    {file = "pydantic_core-2.23.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:255a8ef062cbf6674450e668482456abac99a5583bbafb73f9ad469540a3a232"},
-    {file = "pydantic_core-2.23.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4a7cd62e831afe623fbb7aabbb4fe583212115b3ef38a9f6b71869ba644624a2"},
-    {file = "pydantic_core-2.23.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f09e2ff1f17c2b51f2bc76d1cc33da96298f0a036a137f5440ab3ec5360b624f"},
-    {file = "pydantic_core-2.23.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:e38e63e6f3d1cec5a27e0afe90a085af8b6806ee208b33030e65b6516353f1a3"},
-    {file = "pydantic_core-2.23.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:0dbd8dbed2085ed23b5c04afa29d8fd2771674223135dc9bc937f3c09284d071"},
-    {file = "pydantic_core-2.23.4-cp310-none-win32.whl", hash = "sha256:6531b7ca5f951d663c339002e91aaebda765ec7d61b7d1e3991051906ddde119"},
-    {file = "pydantic_core-2.23.4-cp310-none-win_amd64.whl", hash = "sha256:7c9129eb40958b3d4500fa2467e6a83356b3b61bfff1b414c7361d9220f9ae8f"},
-    {file = "pydantic_core-2.23.4-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:77733e3892bb0a7fa797826361ce8a9184d25c8dffaec60b7ffe928153680ba8"},
-    {file = "pydantic_core-2.23.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1b84d168f6c48fabd1f2027a3d1bdfe62f92cade1fb273a5d68e621da0e44e6d"},
-    {file = "pydantic_core-2.23.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:df49e7a0861a8c36d089c1ed57d308623d60416dab2647a4a17fe050ba85de0e"},
-    {file = "pydantic_core-2.23.4-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ff02b6d461a6de369f07ec15e465a88895f3223eb75073ffea56b84d9331f607"},
-    {file = "pydantic_core-2.23.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:996a38a83508c54c78a5f41456b0103c30508fed9abcad0a59b876d7398f25fd"},
-    {file = "pydantic_core-2.23.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d97683ddee4723ae8c95d1eddac7c192e8c552da0c73a925a89fa8649bf13eea"},
-    {file = "pydantic_core-2.23.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:216f9b2d7713eb98cb83c80b9c794de1f6b7e3145eef40400c62e86cee5f4e1e"},
-    {file = "pydantic_core-2.23.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6f783e0ec4803c787bcea93e13e9932edab72068f68ecffdf86a99fd5918878b"},
-    {file = "pydantic_core-2.23.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:d0776dea117cf5272382634bd2a5c1b6eb16767c223c6a5317cd3e2a757c61a0"},
-    {file = "pydantic_core-2.23.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d5f7a395a8cf1621939692dba2a6b6a830efa6b3cee787d82c7de1ad2930de64"},
-    {file = "pydantic_core-2.23.4-cp311-none-win32.whl", hash = "sha256:74b9127ffea03643e998e0c5ad9bd3811d3dac8c676e47db17b0ee7c3c3bf35f"},
-    {file = "pydantic_core-2.23.4-cp311-none-win_amd64.whl", hash = "sha256:98d134c954828488b153d88ba1f34e14259284f256180ce659e8d83e9c05eaa3"},
-    {file = "pydantic_core-2.23.4-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:f3e0da4ebaef65158d4dfd7d3678aad692f7666877df0002b8a522cdf088f231"},
-    {file = "pydantic_core-2.23.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f69a8e0b033b747bb3e36a44e7732f0c99f7edd5cea723d45bc0d6e95377ffee"},
-    {file = "pydantic_core-2.23.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:723314c1d51722ab28bfcd5240d858512ffd3116449c557a1336cbe3919beb87"},
-    {file = "pydantic_core-2.23.4-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bb2802e667b7051a1bebbfe93684841cc9351004e2badbd6411bf357ab8d5ac8"},
-    {file = "pydantic_core-2.23.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d18ca8148bebe1b0a382a27a8ee60350091a6ddaf475fa05ef50dc35b5df6327"},
-    {file = "pydantic_core-2.23.4-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:33e3d65a85a2a4a0dc3b092b938a4062b1a05f3a9abde65ea93b233bca0e03f2"},
-    {file = "pydantic_core-2.23.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:128585782e5bfa515c590ccee4b727fb76925dd04a98864182b22e89a4e6ed36"},
-    {file = "pydantic_core-2.23.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:68665f4c17edcceecc112dfed5dbe6f92261fb9d6054b47d01bf6371a6196126"},
-    {file = "pydantic_core-2.23.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:20152074317d9bed6b7a95ade3b7d6054845d70584216160860425f4fbd5ee9e"},
-    {file = "pydantic_core-2.23.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:9261d3ce84fa1d38ed649c3638feefeae23d32ba9182963e465d58d62203bd24"},
-    {file = "pydantic_core-2.23.4-cp312-none-win32.whl", hash = "sha256:4ba762ed58e8d68657fc1281e9bb72e1c3e79cc5d464be146e260c541ec12d84"},
-    {file = "pydantic_core-2.23.4-cp312-none-win_amd64.whl", hash = "sha256:97df63000f4fea395b2824da80e169731088656d1818a11b95f3b173747b6cd9"},
-    {file = "pydantic_core-2.23.4-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:7530e201d10d7d14abce4fb54cfe5b94a0aefc87da539d0346a484ead376c3cc"},
-    {file = "pydantic_core-2.23.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:df933278128ea1cd77772673c73954e53a1c95a4fdf41eef97c2b779271bd0bd"},
-    {file = "pydantic_core-2.23.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0cb3da3fd1b6a5d0279a01877713dbda118a2a4fc6f0d821a57da2e464793f05"},
-    {file = "pydantic_core-2.23.4-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:42c6dcb030aefb668a2b7009c85b27f90e51e6a3b4d5c9bc4c57631292015b0d"},
-    {file = "pydantic_core-2.23.4-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:696dd8d674d6ce621ab9d45b205df149399e4bb9aa34102c970b721554828510"},
-    {file = "pydantic_core-2.23.4-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2971bb5ffe72cc0f555c13e19b23c85b654dd2a8f7ab493c262071377bfce9f6"},
-    {file = "pydantic_core-2.23.4-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8394d940e5d400d04cad4f75c0598665cbb81aecefaca82ca85bd28264af7f9b"},
-    {file = "pydantic_core-2.23.4-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0dff76e0602ca7d4cdaacc1ac4c005e0ce0dcfe095d5b5259163a80d3a10d327"},
-    {file = "pydantic_core-2.23.4-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:7d32706badfe136888bdea71c0def994644e09fff0bfe47441deaed8e96fdbc6"},
-    {file = "pydantic_core-2.23.4-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:ed541d70698978a20eb63d8c5d72f2cc6d7079d9d90f6b50bad07826f1320f5f"},
-    {file = "pydantic_core-2.23.4-cp313-none-win32.whl", hash = "sha256:3d5639516376dce1940ea36edf408c554475369f5da2abd45d44621cb616f769"},
-    {file = "pydantic_core-2.23.4-cp313-none-win_amd64.whl", hash = "sha256:5a1504ad17ba4210df3a045132a7baeeba5a200e930f57512ee02909fc5c4cb5"},
-    {file = "pydantic_core-2.23.4-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:d4488a93b071c04dc20f5cecc3631fc78b9789dd72483ba15d423b5b3689b555"},
-    {file = "pydantic_core-2.23.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:81965a16b675b35e1d09dd14df53f190f9129c0202356ed44ab2728b1c905658"},
-    {file = "pydantic_core-2.23.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4ffa2ebd4c8530079140dd2d7f794a9d9a73cbb8e9d59ffe24c63436efa8f271"},
-    {file = "pydantic_core-2.23.4-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:61817945f2fe7d166e75fbfb28004034b48e44878177fc54d81688e7b85a3665"},
-    {file = "pydantic_core-2.23.4-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:29d2c342c4bc01b88402d60189f3df065fb0dda3654744d5a165a5288a657368"},
-    {file = "pydantic_core-2.23.4-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5e11661ce0fd30a6790e8bcdf263b9ec5988e95e63cf901972107efc49218b13"},
-    {file = "pydantic_core-2.23.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9d18368b137c6295db49ce7218b1a9ba15c5bc254c96d7c9f9e924a9bc7825ad"},
-    {file = "pydantic_core-2.23.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ec4e55f79b1c4ffb2eecd8a0cfba9955a2588497d96851f4c8f99aa4a1d39b12"},
-    {file = "pydantic_core-2.23.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:374a5e5049eda9e0a44c696c7ade3ff355f06b1fe0bb945ea3cac2bc336478a2"},
-    {file = "pydantic_core-2.23.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:5c364564d17da23db1106787675fc7af45f2f7b58b4173bfdd105564e132e6fb"},
-    {file = "pydantic_core-2.23.4-cp38-none-win32.whl", hash = "sha256:d7a80d21d613eec45e3d41eb22f8f94ddc758a6c4720842dc74c0581f54993d6"},
-    {file = "pydantic_core-2.23.4-cp38-none-win_amd64.whl", hash = "sha256:5f5ff8d839f4566a474a969508fe1c5e59c31c80d9e140566f9a37bba7b8d556"},
-    {file = "pydantic_core-2.23.4-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:a4fa4fc04dff799089689f4fd502ce7d59de529fc2f40a2c8836886c03e0175a"},
-    {file = "pydantic_core-2.23.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0a7df63886be5e270da67e0966cf4afbae86069501d35c8c1b3b6c168f42cb36"},
-    {file = "pydantic_core-2.23.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dcedcd19a557e182628afa1d553c3895a9f825b936415d0dbd3cd0bbcfd29b4b"},
-    {file = "pydantic_core-2.23.4-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5f54b118ce5de9ac21c363d9b3caa6c800341e8c47a508787e5868c6b79c9323"},
-    {file = "pydantic_core-2.23.4-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:86d2f57d3e1379a9525c5ab067b27dbb8a0642fb5d454e17a9ac434f9ce523e3"},
-    {file = "pydantic_core-2.23.4-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:de6d1d1b9e5101508cb37ab0d972357cac5235f5c6533d1071964c47139257df"},
-    {file = "pydantic_core-2.23.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1278e0d324f6908e872730c9102b0112477a7f7cf88b308e4fc36ce1bdb6d58c"},
-    {file = "pydantic_core-2.23.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9a6b5099eeec78827553827f4c6b8615978bb4b6a88e5d9b93eddf8bb6790f55"},
-    {file = "pydantic_core-2.23.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:e55541f756f9b3ee346b840103f32779c695a19826a4c442b7954550a0972040"},
-    {file = "pydantic_core-2.23.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a5c7ba8ffb6d6f8f2ab08743be203654bb1aaa8c9dcb09f82ddd34eadb695605"},
-    {file = "pydantic_core-2.23.4-cp39-none-win32.whl", hash = "sha256:37b0fe330e4a58d3c58b24d91d1eb102aeec675a3db4c292ec3928ecd892a9a6"},
-    {file = "pydantic_core-2.23.4-cp39-none-win_amd64.whl", hash = "sha256:1498bec4c05c9c787bde9125cfdcc63a41004ff167f495063191b863399b1a29"},
-    {file = "pydantic_core-2.23.4-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:f455ee30a9d61d3e1a15abd5068827773d6e4dc513e795f380cdd59932c782d5"},
-    {file = "pydantic_core-2.23.4-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:1e90d2e3bd2c3863d48525d297cd143fe541be8bbf6f579504b9712cb6b643ec"},
-    {file = "pydantic_core-2.23.4-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2e203fdf807ac7e12ab59ca2bfcabb38c7cf0b33c41efeb00f8e5da1d86af480"},
-    {file = "pydantic_core-2.23.4-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e08277a400de01bc72436a0ccd02bdf596631411f592ad985dcee21445bd0068"},
-    {file = "pydantic_core-2.23.4-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f220b0eea5965dec25480b6333c788fb72ce5f9129e8759ef876a1d805d00801"},
-    {file = "pydantic_core-2.23.4-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:d06b0c8da4f16d1d1e352134427cb194a0a6e19ad5db9161bf32b2113409e728"},
-    {file = "pydantic_core-2.23.4-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:ba1a0996f6c2773bd83e63f18914c1de3c9dd26d55f4ac302a7efe93fb8e7433"},
-    {file = "pydantic_core-2.23.4-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:9a5bce9d23aac8f0cf0836ecfc033896aa8443b501c58d0602dbfd5bd5b37753"},
-    {file = "pydantic_core-2.23.4-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:78ddaaa81421a29574a682b3179d4cf9e6d405a09b99d93ddcf7e5239c742e21"},
-    {file = "pydantic_core-2.23.4-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:883a91b5dd7d26492ff2f04f40fbb652de40fcc0afe07e8129e8ae779c2110eb"},
-    {file = "pydantic_core-2.23.4-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:88ad334a15b32a791ea935af224b9de1bf99bcd62fabf745d5f3442199d86d59"},
-    {file = "pydantic_core-2.23.4-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:233710f069d251feb12a56da21e14cca67994eab08362207785cf8c598e74577"},
-    {file = "pydantic_core-2.23.4-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:19442362866a753485ba5e4be408964644dd6a09123d9416c54cd49171f50744"},
-    {file = "pydantic_core-2.23.4-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:624e278a7d29b6445e4e813af92af37820fafb6dcc55c012c834f9e26f9aaaef"},
-    {file = "pydantic_core-2.23.4-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f5ef8f42bec47f21d07668a043f077d507e5bf4e668d5c6dfe6aaba89de1a5b8"},
-    {file = "pydantic_core-2.23.4-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:aea443fffa9fbe3af1a9ba721a87f926fe548d32cab71d188a6ede77d0ff244e"},
-    {file = "pydantic_core-2.23.4.tar.gz", hash = "sha256:2584f7cf844ac4d970fba483a717dbe10c1c1c96a969bf65d61ffe94df1b2863"},
+    {file = "pydantic_core-2.27.1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:71a5e35c75c021aaf400ac048dacc855f000bdfed91614b4a726f7432f1f3d6a"},
+    {file = "pydantic_core-2.27.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f82d068a2d6ecfc6e054726080af69a6764a10015467d7d7b9f66d6ed5afa23b"},
+    {file = "pydantic_core-2.27.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:121ceb0e822f79163dd4699e4c54f5ad38b157084d97b34de8b232bcaad70278"},
+    {file = "pydantic_core-2.27.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4603137322c18eaf2e06a4495f426aa8d8388940f3c457e7548145011bb68e05"},
+    {file = "pydantic_core-2.27.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a33cd6ad9017bbeaa9ed78a2e0752c5e250eafb9534f308e7a5f7849b0b1bfb4"},
+    {file = "pydantic_core-2.27.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:15cc53a3179ba0fcefe1e3ae50beb2784dede4003ad2dfd24f81bba4b23a454f"},
+    {file = "pydantic_core-2.27.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:45d9c5eb9273aa50999ad6adc6be5e0ecea7e09dbd0d31bd0c65a55a2592ca08"},
+    {file = "pydantic_core-2.27.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8bf7b66ce12a2ac52d16f776b31d16d91033150266eb796967a7e4621707e4f6"},
+    {file = "pydantic_core-2.27.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:655d7dd86f26cb15ce8a431036f66ce0318648f8853d709b4167786ec2fa4807"},
+    {file = "pydantic_core-2.27.1-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:5556470f1a2157031e676f776c2bc20acd34c1990ca5f7e56f1ebf938b9ab57c"},
+    {file = "pydantic_core-2.27.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:f69ed81ab24d5a3bd93861c8c4436f54afdf8e8cc421562b0c7504cf3be58206"},
+    {file = "pydantic_core-2.27.1-cp310-none-win32.whl", hash = "sha256:f5a823165e6d04ccea61a9f0576f345f8ce40ed533013580e087bd4d7442b52c"},
+    {file = "pydantic_core-2.27.1-cp310-none-win_amd64.whl", hash = "sha256:57866a76e0b3823e0b56692d1a0bf722bffb324839bb5b7226a7dbd6c9a40b17"},
+    {file = "pydantic_core-2.27.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:ac3b20653bdbe160febbea8aa6c079d3df19310d50ac314911ed8cc4eb7f8cb8"},
+    {file = "pydantic_core-2.27.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a5a8e19d7c707c4cadb8c18f5f60c843052ae83c20fa7d44f41594c644a1d330"},
+    {file = "pydantic_core-2.27.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7f7059ca8d64fea7f238994c97d91f75965216bcbe5f695bb44f354893f11d52"},
+    {file = "pydantic_core-2.27.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bed0f8a0eeea9fb72937ba118f9db0cb7e90773462af7962d382445f3005e5a4"},
+    {file = "pydantic_core-2.27.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a3cb37038123447cf0f3ea4c74751f6a9d7afef0eb71aa07bf5f652b5e6a132c"},
+    {file = "pydantic_core-2.27.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:84286494f6c5d05243456e04223d5a9417d7f443c3b76065e75001beb26f88de"},
+    {file = "pydantic_core-2.27.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:acc07b2cfc5b835444b44a9956846b578d27beeacd4b52e45489e93276241025"},
+    {file = "pydantic_core-2.27.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4fefee876e07a6e9aad7a8c8c9f85b0cdbe7df52b8a9552307b09050f7512c7e"},
+    {file = "pydantic_core-2.27.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:258c57abf1188926c774a4c94dd29237e77eda19462e5bb901d88adcab6af919"},
+    {file = "pydantic_core-2.27.1-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:35c14ac45fcfdf7167ca76cc80b2001205a8d5d16d80524e13508371fb8cdd9c"},
+    {file = "pydantic_core-2.27.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d1b26e1dff225c31897696cab7d4f0a315d4c0d9e8666dbffdb28216f3b17fdc"},
+    {file = "pydantic_core-2.27.1-cp311-none-win32.whl", hash = "sha256:2cdf7d86886bc6982354862204ae3b2f7f96f21a3eb0ba5ca0ac42c7b38598b9"},
+    {file = "pydantic_core-2.27.1-cp311-none-win_amd64.whl", hash = "sha256:3af385b0cee8df3746c3f406f38bcbfdc9041b5c2d5ce3e5fc6637256e60bbc5"},
+    {file = "pydantic_core-2.27.1-cp311-none-win_arm64.whl", hash = "sha256:81f2ec23ddc1b476ff96563f2e8d723830b06dceae348ce02914a37cb4e74b89"},
+    {file = "pydantic_core-2.27.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:9cbd94fc661d2bab2bc702cddd2d3370bbdcc4cd0f8f57488a81bcce90c7a54f"},
+    {file = "pydantic_core-2.27.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5f8c4718cd44ec1580e180cb739713ecda2bdee1341084c1467802a417fe0f02"},
+    {file = "pydantic_core-2.27.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:15aae984e46de8d376df515f00450d1522077254ef6b7ce189b38ecee7c9677c"},
+    {file = "pydantic_core-2.27.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:1ba5e3963344ff25fc8c40da90f44b0afca8cfd89d12964feb79ac1411a260ac"},
+    {file = "pydantic_core-2.27.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:992cea5f4f3b29d6b4f7f1726ed8ee46c8331c6b4eed6db5b40134c6fe1768bb"},
+    {file = "pydantic_core-2.27.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0325336f348dbee6550d129b1627cb8f5351a9dc91aad141ffb96d4937bd9529"},
+    {file = "pydantic_core-2.27.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7597c07fbd11515f654d6ece3d0e4e5093edc30a436c63142d9a4b8e22f19c35"},
+    {file = "pydantic_core-2.27.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:3bbd5d8cc692616d5ef6fbbbd50dbec142c7e6ad9beb66b78a96e9c16729b089"},
+    {file = "pydantic_core-2.27.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:dc61505e73298a84a2f317255fcc72b710b72980f3a1f670447a21efc88f8381"},
+    {file = "pydantic_core-2.27.1-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:e1f735dc43da318cad19b4173dd1ffce1d84aafd6c9b782b3abc04a0d5a6f5bb"},
+    {file = "pydantic_core-2.27.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:f4e5658dbffe8843a0f12366a4c2d1c316dbe09bb4dfbdc9d2d9cd6031de8aae"},
+    {file = "pydantic_core-2.27.1-cp312-none-win32.whl", hash = "sha256:672ebbe820bb37988c4d136eca2652ee114992d5d41c7e4858cdd90ea94ffe5c"},
+    {file = "pydantic_core-2.27.1-cp312-none-win_amd64.whl", hash = "sha256:66ff044fd0bb1768688aecbe28b6190f6e799349221fb0de0e6f4048eca14c16"},
+    {file = "pydantic_core-2.27.1-cp312-none-win_arm64.whl", hash = "sha256:9a3b0793b1bbfd4146304e23d90045f2a9b5fd5823aa682665fbdaf2a6c28f3e"},
+    {file = "pydantic_core-2.27.1-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:f216dbce0e60e4d03e0c4353c7023b202d95cbaeff12e5fd2e82ea0a66905073"},
+    {file = "pydantic_core-2.27.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a2e02889071850bbfd36b56fd6bc98945e23670773bc7a76657e90e6b6603c08"},
+    {file = "pydantic_core-2.27.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42b0e23f119b2b456d07ca91b307ae167cc3f6c846a7b169fca5326e32fdc6cf"},
+    {file = "pydantic_core-2.27.1-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:764be71193f87d460a03f1f7385a82e226639732214b402f9aa61f0d025f0737"},
+    {file = "pydantic_core-2.27.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1c00666a3bd2f84920a4e94434f5974d7bbc57e461318d6bb34ce9cdbbc1f6b2"},
+    {file = "pydantic_core-2.27.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3ccaa88b24eebc0f849ce0a4d09e8a408ec5a94afff395eb69baf868f5183107"},
+    {file = "pydantic_core-2.27.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c65af9088ac534313e1963443d0ec360bb2b9cba6c2909478d22c2e363d98a51"},
+    {file = "pydantic_core-2.27.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:206b5cf6f0c513baffaeae7bd817717140770c74528f3e4c3e1cec7871ddd61a"},
+    {file = "pydantic_core-2.27.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:062f60e512fc7fff8b8a9d680ff0ddaaef0193dba9fa83e679c0c5f5fbd018bc"},
+    {file = "pydantic_core-2.27.1-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:a0697803ed7d4af5e4c1adf1670af078f8fcab7a86350e969f454daf598c4960"},
+    {file = "pydantic_core-2.27.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:58ca98a950171f3151c603aeea9303ef6c235f692fe555e883591103da709b23"},
+    {file = "pydantic_core-2.27.1-cp313-none-win32.whl", hash = "sha256:8065914ff79f7eab1599bd80406681f0ad08f8e47c880f17b416c9f8f7a26d05"},
+    {file = "pydantic_core-2.27.1-cp313-none-win_amd64.whl", hash = "sha256:ba630d5e3db74c79300d9a5bdaaf6200172b107f263c98a0539eeecb857b2337"},
+    {file = "pydantic_core-2.27.1-cp313-none-win_arm64.whl", hash = "sha256:45cf8588c066860b623cd11c4ba687f8d7175d5f7ef65f7129df8a394c502de5"},
+    {file = "pydantic_core-2.27.1-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:5897bec80a09b4084aee23f9b73a9477a46c3304ad1d2d07acca19723fb1de62"},
+    {file = "pydantic_core-2.27.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:d0165ab2914379bd56908c02294ed8405c252250668ebcb438a55494c69f44ab"},
+    {file = "pydantic_core-2.27.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6b9af86e1d8e4cfc82c2022bfaa6f459381a50b94a29e95dcdda8442d6d83864"},
+    {file = "pydantic_core-2.27.1-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5f6c8a66741c5f5447e047ab0ba7a1c61d1e95580d64bce852e3df1f895c4067"},
+    {file = "pydantic_core-2.27.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9a42d6a8156ff78981f8aa56eb6394114e0dedb217cf8b729f438f643608cbcd"},
+    {file = "pydantic_core-2.27.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:64c65f40b4cd8b0e049a8edde07e38b476da7e3aaebe63287c899d2cff253fa5"},
+    {file = "pydantic_core-2.27.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9fdcf339322a3fae5cbd504edcefddd5a50d9ee00d968696846f089b4432cf78"},
+    {file = "pydantic_core-2.27.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:bf99c8404f008750c846cb4ac4667b798a9f7de673ff719d705d9b2d6de49c5f"},
+    {file = "pydantic_core-2.27.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:8f1edcea27918d748c7e5e4d917297b2a0ab80cad10f86631e488b7cddf76a36"},
+    {file = "pydantic_core-2.27.1-cp38-cp38-musllinux_1_1_armv7l.whl", hash = "sha256:159cac0a3d096f79ab6a44d77a961917219707e2a130739c64d4dd46281f5c2a"},
+    {file = "pydantic_core-2.27.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:029d9757eb621cc6e1848fa0b0310310de7301057f623985698ed7ebb014391b"},
+    {file = "pydantic_core-2.27.1-cp38-none-win32.whl", hash = "sha256:a28af0695a45f7060e6f9b7092558a928a28553366519f64083c63a44f70e618"},
+    {file = "pydantic_core-2.27.1-cp38-none-win_amd64.whl", hash = "sha256:2d4567c850905d5eaaed2f7a404e61012a51caf288292e016360aa2b96ff38d4"},
+    {file = "pydantic_core-2.27.1-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:e9386266798d64eeb19dd3677051f5705bf873e98e15897ddb7d76f477131967"},
+    {file = "pydantic_core-2.27.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4228b5b646caa73f119b1ae756216b59cc6e2267201c27d3912b592c5e323b60"},
+    {file = "pydantic_core-2.27.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0b3dfe500de26c52abe0477dde16192ac39c98f05bf2d80e76102d394bd13854"},
+    {file = "pydantic_core-2.27.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:aee66be87825cdf72ac64cb03ad4c15ffef4143dbf5c113f64a5ff4f81477bf9"},
+    {file = "pydantic_core-2.27.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3b748c44bb9f53031c8cbc99a8a061bc181c1000c60a30f55393b6e9c45cc5bd"},
+    {file = "pydantic_core-2.27.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5ca038c7f6a0afd0b2448941b6ef9d5e1949e999f9e5517692eb6da58e9d44be"},
+    {file = "pydantic_core-2.27.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6e0bd57539da59a3e4671b90a502da9a28c72322a4f17866ba3ac63a82c4498e"},
+    {file = "pydantic_core-2.27.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ac6c2c45c847bbf8f91930d88716a0fb924b51e0c6dad329b793d670ec5db792"},
+    {file = "pydantic_core-2.27.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b94d4ba43739bbe8b0ce4262bcc3b7b9f31459ad120fb595627eaeb7f9b9ca01"},
+    {file = "pydantic_core-2.27.1-cp39-cp39-musllinux_1_1_armv7l.whl", hash = "sha256:00e6424f4b26fe82d44577b4c842d7df97c20be6439e8e685d0d715feceb9fb9"},
+    {file = "pydantic_core-2.27.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:38de0a70160dd97540335b7ad3a74571b24f1dc3ed33f815f0880682e6880131"},
+    {file = "pydantic_core-2.27.1-cp39-none-win32.whl", hash = "sha256:7ccebf51efc61634f6c2344da73e366c75e735960b5654b63d7e6f69a5885fa3"},
+    {file = "pydantic_core-2.27.1-cp39-none-win_amd64.whl", hash = "sha256:a57847b090d7892f123726202b7daa20df6694cbd583b67a592e856bff603d6c"},
+    {file = "pydantic_core-2.27.1-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:3fa80ac2bd5856580e242dbc202db873c60a01b20309c8319b5c5986fbe53ce6"},
+    {file = "pydantic_core-2.27.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:d950caa237bb1954f1b8c9227b5065ba6875ac9771bb8ec790d956a699b78676"},
+    {file = "pydantic_core-2.27.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0e4216e64d203e39c62df627aa882f02a2438d18a5f21d7f721621f7a5d3611d"},
+    {file = "pydantic_core-2.27.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:02a3d637bd387c41d46b002f0e49c52642281edacd2740e5a42f7017feea3f2c"},
+    {file = "pydantic_core-2.27.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:161c27ccce13b6b0c8689418da3885d3220ed2eae2ea5e9b2f7f3d48f1d52c27"},
+    {file = "pydantic_core-2.27.1-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:19910754e4cc9c63bc1c7f6d73aa1cfee82f42007e407c0f413695c2f7ed777f"},
+    {file = "pydantic_core-2.27.1-pp310-pypy310_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:e173486019cc283dc9778315fa29a363579372fe67045e971e89b6365cc035ed"},
+    {file = "pydantic_core-2.27.1-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:af52d26579b308921b73b956153066481f064875140ccd1dfd4e77db89dbb12f"},
+    {file = "pydantic_core-2.27.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:981fb88516bd1ae8b0cbbd2034678a39dedc98752f264ac9bc5839d3923fa04c"},
+    {file = "pydantic_core-2.27.1-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:5fde892e6c697ce3e30c61b239330fc5d569a71fefd4eb6512fc6caec9dd9e2f"},
+    {file = "pydantic_core-2.27.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:816f5aa087094099fff7edabb5e01cc370eb21aa1a1d44fe2d2aefdfb5599b31"},
+    {file = "pydantic_core-2.27.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9c10c309e18e443ddb108f0ef64e8729363adbfd92d6d57beec680f6261556f3"},
+    {file = "pydantic_core-2.27.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:98476c98b02c8e9b2eec76ac4156fd006628b1b2d0ef27e548ffa978393fd154"},
+    {file = "pydantic_core-2.27.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c3027001c28434e7ca5a6e1e527487051136aa81803ac812be51802150d880dd"},
+    {file = "pydantic_core-2.27.1-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:7699b1df36a48169cdebda7ab5a2bac265204003f153b4bd17276153d997670a"},
+    {file = "pydantic_core-2.27.1-pp39-pypy39_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:1c39b07d90be6b48968ddc8c19e7585052088fd7ec8d568bb31ff64c70ae3c97"},
+    {file = "pydantic_core-2.27.1-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:46ccfe3032b3915586e469d4972973f893c0a2bb65669194a5bdea9bacc088c2"},
+    {file = "pydantic_core-2.27.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:62ba45e21cf6571d7f716d903b5b7b6d2617e2d5d67c0923dc47b9d41369f840"},
+    {file = "pydantic_core-2.27.1.tar.gz", hash = "sha256:62a763352879b84aa31058fc931884055fd75089cccbd9d58bb6afd01141b235"},
 ]
 ]
 
 
 [package.dependencies]
 [package.dependencies]
@@ -2198,13 +2206,13 @@ reflex = ">=0.6.0a"
 
 
 [[package]]
 [[package]]
 name = "reflex-hosting-cli"
 name = "reflex-hosting-cli"
-version = "0.1.16"
+version = "0.1.17"
 description = "Reflex Hosting CLI"
 description = "Reflex Hosting CLI"
 optional = false
 optional = false
 python-versions = "<4.0,>=3.8"
 python-versions = "<4.0,>=3.8"
 files = [
 files = [
-    {file = "reflex_hosting_cli-0.1.16-py3-none-any.whl", hash = "sha256:1b12c2a76a27571102cacf5ec3028fb09816a51568bff793735e66aaad886605"},
-    {file = "reflex_hosting_cli-0.1.16.tar.gz", hash = "sha256:9c9826318fd3d388b706be70f1f500a35e355f8f86f54138e7789fd6096a4ab9"},
+    {file = "reflex_hosting_cli-0.1.17-py3-none-any.whl", hash = "sha256:cf1accec70745557a40125ffa2a8929e6ef9834808afe78e4f4a01933ac0cb67"},
+    {file = "reflex_hosting_cli-0.1.17.tar.gz", hash = "sha256:263d8dc217eb24d4198ac0bcfd710980bd7795d9818a5e522027657f94752710"},
 ]
 ]
 
 
 [package.dependencies]
 [package.dependencies]
@@ -2350,23 +2358,23 @@ websocket-client = ">=1.8,<2.0"
 
 
 [[package]]
 [[package]]
 name = "setuptools"
 name = "setuptools"
-version = "75.5.0"
+version = "75.6.0"
 description = "Easily download, build, install, upgrade, and uninstall Python packages"
 description = "Easily download, build, install, upgrade, and uninstall Python packages"
 optional = false
 optional = false
 python-versions = ">=3.9"
 python-versions = ">=3.9"
 files = [
 files = [
-    {file = "setuptools-75.5.0-py3-none-any.whl", hash = "sha256:87cb777c3b96d638ca02031192d40390e0ad97737e27b6b4fa831bea86f2f829"},
-    {file = "setuptools-75.5.0.tar.gz", hash = "sha256:5c4ccb41111392671f02bb5f8436dfc5a9a7185e80500531b133f5775c4163ef"},
+    {file = "setuptools-75.6.0-py3-none-any.whl", hash = "sha256:ce74b49e8f7110f9bf04883b730f4765b774ef3ef28f722cce7c273d253aaf7d"},
+    {file = "setuptools-75.6.0.tar.gz", hash = "sha256:8199222558df7c86216af4f84c30e9b34a61d8ba19366cc914424cdbd28252f6"},
 ]
 ]
 
 
 [package.extras]
 [package.extras]
 check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1)", "ruff (>=0.7.0)"]
 check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1)", "ruff (>=0.7.0)"]
-core = ["importlib-metadata (>=6)", "jaraco.collections", "jaraco.functools (>=4)", "jaraco.text (>=3.7)", "more-itertools", "more-itertools (>=8.8)", "packaging", "packaging (>=24.2)", "platformdirs (>=4.2.2)", "tomli (>=2.0.1)", "wheel (>=0.43.0)"]
+core = ["importlib_metadata (>=6)", "jaraco.collections", "jaraco.functools (>=4)", "jaraco.text (>=3.7)", "more_itertools", "more_itertools (>=8.8)", "packaging", "packaging (>=24.2)", "platformdirs (>=4.2.2)", "tomli (>=2.0.1)", "wheel (>=0.43.0)"]
 cover = ["pytest-cov"]
 cover = ["pytest-cov"]
 doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "pyproject-hooks (!=1.1)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier", "towncrier (<24.7)"]
 doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "pyproject-hooks (!=1.1)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier", "towncrier (<24.7)"]
 enabler = ["pytest-enabler (>=2.2)"]
 enabler = ["pytest-enabler (>=2.2)"]
 test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "jaraco.test (>=5.5)", "packaging (>=24.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-home (>=0.5)", "pytest-perf", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel (>=0.44.0)"]
 test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "jaraco.test (>=5.5)", "packaging (>=24.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-home (>=0.5)", "pytest-perf", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel (>=0.44.0)"]
-type = ["importlib-metadata (>=7.0.2)", "jaraco.develop (>=7.21)", "mypy (>=1.12,<1.14)", "pytest-mypy"]
+type = ["importlib_metadata (>=7.0.2)", "jaraco.develop (>=7.21)", "mypy (>=1.12,<1.14)", "pytest-mypy"]
 
 
 [[package]]
 [[package]]
 name = "shellingham"
 name = "shellingham"
@@ -2773,13 +2781,13 @@ zstd = ["zstandard (>=0.18.0)"]
 
 
 [[package]]
 [[package]]
 name = "uvicorn"
 name = "uvicorn"
-version = "0.32.0"
+version = "0.32.1"
 description = "The lightning-fast ASGI server."
 description = "The lightning-fast ASGI server."
 optional = false
 optional = false
 python-versions = ">=3.8"
 python-versions = ">=3.8"
 files = [
 files = [
-    {file = "uvicorn-0.32.0-py3-none-any.whl", hash = "sha256:60b8f3a5ac027dcd31448f411ced12b5ef452c646f76f02f8cc3f25d8d26fd82"},
-    {file = "uvicorn-0.32.0.tar.gz", hash = "sha256:f78b36b143c16f54ccdb8190d0a26b5f1901fe5a3c777e1ab29f26391af8551e"},
+    {file = "uvicorn-0.32.1-py3-none-any.whl", hash = "sha256:82ad92fd58da0d12af7482ecdb5f2470a04c9c9a53ced65b9bbb4a205377602e"},
+    {file = "uvicorn-0.32.1.tar.gz", hash = "sha256:ee9519c246a72b1c084cea8d3b44ed6026e78a4a309cbedae9c37e4cb9fbb175"},
 ]
 ]
 
 
 [package.dependencies]
 [package.dependencies]
@@ -2788,7 +2796,7 @@ h11 = ">=0.8"
 typing-extensions = {version = ">=4.0", markers = "python_version < \"3.11\""}
 typing-extensions = {version = ">=4.0", markers = "python_version < \"3.11\""}
 
 
 [package.extras]
 [package.extras]
-standard = ["colorama (>=0.4)", "httptools (>=0.5.0)", "python-dotenv (>=0.13)", "pyyaml (>=5.1)", "uvloop (>=0.14.0,!=0.15.0,!=0.15.1)", "watchfiles (>=0.13)", "websockets (>=10.4)"]
+standard = ["colorama (>=0.4)", "httptools (>=0.6.3)", "python-dotenv (>=0.13)", "pyyaml (>=5.1)", "uvloop (>=0.14.0,!=0.15.0,!=0.15.1)", "watchfiles (>=0.13)", "websockets (>=10.4)"]
 
 
 [[package]]
 [[package]]
 name = "virtualenv"
 name = "virtualenv"
@@ -3033,4 +3041,4 @@ type = ["pytest-mypy"]
 [metadata]
 [metadata]
 lock-version = "2.0"
 lock-version = "2.0"
 python-versions = "^3.9"
 python-versions = "^3.9"
-content-hash = "a610d4c4bfd852f30e69ad2fbb288c2d9cbdf49e05b9d4936fe5e9b2a7cdefdb"
+content-hash = "8000601d48cfc1b10d0ae18c6046cc59a50cb6c45e6d3ef4775a3203769f2154"

+ 1 - 1
pyproject.toml

@@ -49,7 +49,7 @@ wrapt = [
     {version = ">=1.11.0,<2.0", python = "<3.11"},
     {version = ">=1.11.0,<2.0", python = "<3.11"},
 ]
 ]
 packaging = ">=23.1,<25.0"
 packaging = ">=23.1,<25.0"
-reflex-hosting-cli = ">=0.1.16,<2.0"
+reflex-hosting-cli = ">=0.1.17,<2.0"
 charset-normalizer = ">=3.3.2,<4.0"
 charset-normalizer = ">=3.3.2,<4.0"
 wheel = ">=0.42.0,<1.0"
 wheel = ">=0.42.0,<1.0"
 build = ">=1.0.3,<2.0"
 build = ">=1.0.3,<2.0"

+ 15 - 1
reflex/.templates/web/utils/state.js

@@ -707,6 +707,11 @@ export const useEventLoop = (
       _e.stopPropagation();
       _e.stopPropagation();
     }
     }
     const combined_name = events.map((e) => e.name).join("+++");
     const combined_name = events.map((e) => e.name).join("+++");
+    if (event_actions?.temporal) {
+      if (!socket.current || !socket.current.connected) {
+        return;  // don't queue when the backend is not connected
+      }
+    }
     if (event_actions?.throttle) {
     if (event_actions?.throttle) {
       // If throttle returns false, the events are not added to the queue.
       // If throttle returns false, the events are not added to the queue.
       if (!throttle(combined_name, event_actions.throttle)) {
       if (!throttle(combined_name, event_actions.throttle)) {
@@ -764,7 +769,7 @@ export const useEventLoop = (
     window.onunhandledrejection = function (event) {
     window.onunhandledrejection = function (event) {
       addEvents([
       addEvents([
         Event(`${exception_state_name}.handle_frontend_exception`, {
         Event(`${exception_state_name}.handle_frontend_exception`, {
-          stack: event.reason.stack,
+          stack: event.reason?.stack,
           component_stack: "",
           component_stack: "",
         }),
         }),
       ]);
       ]);
@@ -839,11 +844,20 @@ export const useEventLoop = (
       }
       }
     };
     };
     const change_complete = () => addEvents(onLoadInternalEvent());
     const change_complete = () => addEvents(onLoadInternalEvent());
+    const change_error = () => {
+      // Remove cached error state from router for this page, otherwise the
+      // page will never send on_load events again.
+      if (router.components[router.pathname].error) {
+        delete router.components[router.pathname].error;
+      }
+    }
     router.events.on("routeChangeStart", change_start);
     router.events.on("routeChangeStart", change_start);
     router.events.on("routeChangeComplete", change_complete);
     router.events.on("routeChangeComplete", change_complete);
+    router.events.on("routeChangeError", change_error);
     return () => {
     return () => {
       router.events.off("routeChangeStart", change_start);
       router.events.off("routeChangeStart", change_start);
       router.events.off("routeChangeComplete", change_complete);
       router.events.off("routeChangeComplete", change_complete);
+      router.events.off("routeChangeError", change_error);
     };
     };
   }, [router]);
   }, [router]);
 
 

+ 1 - 0
reflex/__init__.py

@@ -264,6 +264,7 @@ _MAPPING: dict = {
     "experimental": ["_x"],
     "experimental": ["_x"],
     "admin": ["AdminDash"],
     "admin": ["AdminDash"],
     "app": ["App", "UploadFile"],
     "app": ["App", "UploadFile"],
+    "assets": ["asset"],
     "base": ["Base"],
     "base": ["Base"],
     "components.component": [
     "components.component": [
         "Component",
         "Component",

+ 1 - 0
reflex/__init__.pyi

@@ -19,6 +19,7 @@ from . import vars as vars
 from .admin import AdminDash as AdminDash
 from .admin import AdminDash as AdminDash
 from .app import App as App
 from .app import App as App
 from .app import UploadFile as UploadFile
 from .app import UploadFile as UploadFile
+from .assets import asset as asset
 from .base import Base as Base
 from .base import Base as Base
 from .components import el as el
 from .components import el as el
 from .components import lucide as lucide
 from .components import lucide as lucide

+ 95 - 0
reflex/assets.py

@@ -0,0 +1,95 @@
+"""Helper functions for adding assets to the app."""
+
+import inspect
+from pathlib import Path
+from typing import Optional
+
+from reflex import constants
+from reflex.utils.exec import is_backend_only
+
+
+def asset(
+    path: str,
+    shared: bool = False,
+    subfolder: Optional[str] = None,
+    _stack_level: int = 1,
+) -> str:
+    """Add an asset to the app, either shared as a symlink or local.
+
+    Shared/External/Library assets:
+        Place the file next to your including python file.
+        Links the file to the app's external assets directory.
+
+    Example:
+    ```python
+    # my_custom_javascript.js is a shared asset located next to the including python file.
+    rx.script(src=rx.asset(path="my_custom_javascript.js", shared=True))
+    rx.image(src=rx.asset(path="test_image.png", shared=True, subfolder="subfolder"))
+    ```
+
+    Local/Internal assets:
+        Place the file in the app's assets/ directory.
+
+    Example:
+    ```python
+    # local_image.png is an asset located in the app's assets/ directory. It cannot be shared when developing a library.
+    rx.image(src=rx.asset(path="local_image.png"))
+    ```
+
+    Args:
+        path: The relative path of the asset.
+        subfolder: The directory to place the shared asset in.
+        shared: Whether to expose the asset to other apps.
+        _stack_level: The stack level to determine the calling file, defaults to
+            the immediate caller 1. When using rx.asset via a helper function,
+            increase this number for each helper function in the stack.
+
+    Raises:
+        FileNotFoundError: If the file does not exist.
+        ValueError: If subfolder is provided for local assets.
+
+    Returns:
+        The relative URL to the asset.
+    """
+    assets = constants.Dirs.APP_ASSETS
+    backend_only = is_backend_only()
+
+    # Local asset handling
+    if not shared:
+        cwd = Path.cwd()
+        src_file_local = cwd / assets / path
+        if subfolder is not None:
+            raise ValueError("Subfolder is not supported for local assets.")
+        if not backend_only and not src_file_local.exists():
+            raise FileNotFoundError(f"File not found: {src_file_local}")
+        return f"/{path}"
+
+    # Shared asset handling
+    # Determine the file by which the asset is exposed.
+    frame = inspect.stack()[_stack_level]
+    calling_file = frame.filename
+    module = inspect.getmodule(frame[0])
+    assert module is not None
+
+    external = constants.Dirs.EXTERNAL_APP_ASSETS
+    src_file_shared = Path(calling_file).parent / path
+    if not src_file_shared.exists():
+        raise FileNotFoundError(f"File not found: {src_file_shared}")
+
+    caller_module_path = module.__name__.replace(".", "/")
+    subfolder = f"{caller_module_path}/{subfolder}" if subfolder else caller_module_path
+
+    # Symlink the asset to the app's external assets directory if running frontend.
+    if not backend_only:
+        # Create the asset folder in the currently compiling app.
+        asset_folder = Path.cwd() / assets / external / subfolder
+        asset_folder.mkdir(parents=True, exist_ok=True)
+
+        dst_file = asset_folder / path
+
+        if not dst_file.exists() and (
+            not dst_file.is_symlink() or dst_file.resolve() != src_file_shared.resolve()
+        ):
+            dst_file.symlink_to(src_file_shared)
+
+    return f"/{external}/{subfolder}/{path}"

+ 1 - 1
reflex/components/datadisplay/code.py

@@ -382,7 +382,7 @@ for theme_name in dir(Theme):
 class CodeBlock(Component, MarkdownComponentMap):
 class CodeBlock(Component, MarkdownComponentMap):
     """A code block."""
     """A code block."""
 
 
-    library = "react-syntax-highlighter@15.6.1"
+    library = "react-syntax-highlighter@15.6.0"
 
 
     tag = "PrismAsyncLight"
     tag = "PrismAsyncLight"
 
 

+ 5 - 23
reflex/components/radix/primitives/drawer.py

@@ -11,7 +11,6 @@ from reflex.components.radix.primitives.base import RadixPrimitiveComponent
 from reflex.components.radix.themes.base import Theme
 from reflex.components.radix.themes.base import Theme
 from reflex.components.radix.themes.layout.flex import Flex
 from reflex.components.radix.themes.layout.flex import Flex
 from reflex.event import EventHandler, no_args_event_spec, passthrough_event_spec
 from reflex.event import EventHandler, no_args_event_spec, passthrough_event_spec
-from reflex.utils import console
 from reflex.vars.base import Var
 from reflex.vars.base import Var
 
 
 
 
@@ -140,19 +139,19 @@ class DrawerContent(DrawerComponent):
         base_style.update(style)
         base_style.update(style)
         return {"css": base_style}
         return {"css": base_style}
 
 
-    # Fired when the drawer content is opened. Deprecated.
+    # Fired when the drawer content is opened.
     on_open_auto_focus: EventHandler[no_args_event_spec]
     on_open_auto_focus: EventHandler[no_args_event_spec]
 
 
-    # Fired when the drawer content is closed. Deprecated.
+    # Fired when the drawer content is closed.
     on_close_auto_focus: EventHandler[no_args_event_spec]
     on_close_auto_focus: EventHandler[no_args_event_spec]
 
 
-    # Fired when the escape key is pressed. Deprecated.
+    # Fired when the escape key is pressed.
     on_escape_key_down: EventHandler[no_args_event_spec]
     on_escape_key_down: EventHandler[no_args_event_spec]
 
 
-    # Fired when the pointer is down outside the drawer content. Deprecated.
+    # Fired when the pointer is down outside the drawer content.
     on_pointer_down_outside: EventHandler[no_args_event_spec]
     on_pointer_down_outside: EventHandler[no_args_event_spec]
 
 
-    # Fired when interacting outside the drawer content. Deprecated.
+    # Fired when interacting outside the drawer content.
     on_interact_outside: EventHandler[no_args_event_spec]
     on_interact_outside: EventHandler[no_args_event_spec]
 
 
     @classmethod
     @classmethod
@@ -170,23 +169,6 @@ class DrawerContent(DrawerComponent):
         Returns:
         Returns:
                  The drawer content.
                  The drawer content.
         """
         """
-        deprecated_properties = [
-            "on_open_auto_focus",
-            "on_close_auto_focus",
-            "on_escape_key_down",
-            "on_pointer_down_outside",
-            "on_interact_outside",
-        ]
-
-        for prop in deprecated_properties:
-            if prop in props:
-                console.deprecate(
-                    feature_name="drawer content events",
-                    reason=f"The `{prop}` event is deprecated and will be removed in 0.7.0.",
-                    deprecation_version="0.6.3",
-                    removal_version="0.7.0",
-                )
-
         comp = super().create(*children, **props)
         comp = super().create(*children, **props)
 
 
         return Theme.create(comp)
         return Theme.create(comp)

+ 3 - 1
reflex/components/radix/themes/components/segmented_control.py

@@ -12,7 +12,9 @@ from reflex.vars.base import Var
 from ..base import LiteralAccentColor, RadixThemesComponent
 from ..base import LiteralAccentColor, RadixThemesComponent
 
 
 
 
-def on_value_change(value: Var[str | List[str]]) -> Tuple[Var[str | List[str]]]:
+def on_value_change(
+    value: Var[Union[str, List[str]]],
+) -> Tuple[Var[Union[str, List[str]]]]:
     """Handle the on_value_change event.
     """Handle the on_value_change event.
 
 
     Args:
     Args:

+ 7 - 2
reflex/components/radix/themes/components/segmented_control.pyi

@@ -13,7 +13,9 @@ from reflex.vars.base import Var
 
 
 from ..base import RadixThemesComponent
 from ..base import RadixThemesComponent
 
 
-def on_value_change(value: Var[str | List[str]]) -> Tuple[Var[str | List[str]]]: ...
+def on_value_change(
+    value: Var[Union[str, List[str]]],
+) -> Tuple[Var[Union[str, List[str]]]]: ...
 
 
 class SegmentedControlRoot(RadixThemesComponent):
 class SegmentedControlRoot(RadixThemesComponent):
     @overload
     @overload
@@ -118,7 +120,10 @@ class SegmentedControlRoot(RadixThemesComponent):
         custom_attrs: Optional[Dict[str, Union[Var, Any]]] = None,
         custom_attrs: Optional[Dict[str, Union[Var, Any]]] = None,
         on_blur: Optional[EventType[[], BASE_STATE]] = None,
         on_blur: Optional[EventType[[], BASE_STATE]] = None,
         on_change: Optional[
         on_change: Optional[
-            Union[EventType[[], BASE_STATE], EventType[[str | List[str]], BASE_STATE]]
+            Union[
+                EventType[[], BASE_STATE],
+                EventType[[Union[str, List[str]]], BASE_STATE],
+            ]
         ] = None,
         ] = None,
         on_click: Optional[EventType[[], BASE_STATE]] = None,
         on_click: Optional[EventType[[], BASE_STATE]] = None,
         on_context_menu: Optional[EventType[[], BASE_STATE]] = None,
         on_context_menu: Optional[EventType[[], BASE_STATE]] = None,

+ 23 - 12
reflex/components/sonner/toast.py

@@ -15,6 +15,8 @@ from reflex.utils.imports import ImportVar
 from reflex.utils.serializers import serializer
 from reflex.utils.serializers import serializer
 from reflex.vars import VarData
 from reflex.vars import VarData
 from reflex.vars.base import LiteralVar, Var
 from reflex.vars.base import LiteralVar, Var
+from reflex.vars.function import FunctionVar
+from reflex.vars.object import ObjectVar
 
 
 LiteralPosition = Literal[
 LiteralPosition = Literal[
     "top-left",
     "top-left",
@@ -232,7 +234,9 @@ class Toaster(Component):
         return [hook]
         return [hook]
 
 
     @staticmethod
     @staticmethod
-    def send_toast(message: str = "", level: str | None = None, **props) -> EventSpec:
+    def send_toast(
+        message: str | Var = "", level: str | None = None, **props
+    ) -> EventSpec:
         """Send a toast message.
         """Send a toast message.
 
 
         Args:
         Args:
@@ -250,20 +254,27 @@ class Toaster(Component):
             raise ValueError(
             raise ValueError(
                 "Toaster component must be created before sending a toast. (use `rx.toast.provider()`)"
                 "Toaster component must be created before sending a toast. (use `rx.toast.provider()`)"
             )
             )
-        toast_command = f"{toast_ref}.{level}" if level is not None else toast_ref
-        if message == "" and ("title" not in props or "description" not in props):
+
+        toast_command = (
+            ObjectVar.__getattr__(toast_ref.to(dict), level) if level else toast_ref
+        ).to(FunctionVar)
+
+        if isinstance(message, Var):
+            props.setdefault("title", message)
+            message = ""
+        elif message == "" and "title" not in props and "description" not in props:
             raise ValueError("Toast message or title or description must be provided.")
             raise ValueError("Toast message or title or description must be provided.")
+
         if props:
         if props:
-            args = LiteralVar.create(ToastProps(component_name="rx.toast", **props))  # type: ignore
-            toast = f"{toast_command}(`{message}`, {str(args)})"
+            args = LiteralVar.create(ToastProps(component_name="rx.toast", **props))  # pyright: ignore [reportCallIssue, reportGeneralTypeIssues]
+            toast = toast_command.call(message, args)
         else:
         else:
-            toast = f"{toast_command}(`{message}`)"
+            toast = toast_command.call(message)
 
 
-        toast_action = Var(_js_expr=toast)
-        return run_script(toast_action)
+        return run_script(toast)
 
 
     @staticmethod
     @staticmethod
-    def toast_info(message: str = "", **kwargs):
+    def toast_info(message: str | Var = "", **kwargs):
         """Display an info toast message.
         """Display an info toast message.
 
 
         Args:
         Args:
@@ -276,7 +287,7 @@ class Toaster(Component):
         return Toaster.send_toast(message, level="info", **kwargs)
         return Toaster.send_toast(message, level="info", **kwargs)
 
 
     @staticmethod
     @staticmethod
-    def toast_warning(message: str = "", **kwargs):
+    def toast_warning(message: str | Var = "", **kwargs):
         """Display a warning toast message.
         """Display a warning toast message.
 
 
         Args:
         Args:
@@ -289,7 +300,7 @@ class Toaster(Component):
         return Toaster.send_toast(message, level="warning", **kwargs)
         return Toaster.send_toast(message, level="warning", **kwargs)
 
 
     @staticmethod
     @staticmethod
-    def toast_error(message: str = "", **kwargs):
+    def toast_error(message: str | Var = "", **kwargs):
         """Display an error toast message.
         """Display an error toast message.
 
 
         Args:
         Args:
@@ -302,7 +313,7 @@ class Toaster(Component):
         return Toaster.send_toast(message, level="error", **kwargs)
         return Toaster.send_toast(message, level="error", **kwargs)
 
 
     @staticmethod
     @staticmethod
-    def toast_success(message: str = "", **kwargs):
+    def toast_success(message: str | Var = "", **kwargs):
         """Display a success toast message.
         """Display a success toast message.
 
 
         Args:
         Args:

+ 6 - 6
reflex/components/sonner/toast.pyi

@@ -59,16 +59,16 @@ class Toaster(Component):
     def add_hooks(self) -> list[Var | str]: ...
     def add_hooks(self) -> list[Var | str]: ...
     @staticmethod
     @staticmethod
     def send_toast(
     def send_toast(
-        message: str = "", level: str | None = None, **props
+        message: str | Var = "", level: str | None = None, **props
     ) -> EventSpec: ...
     ) -> EventSpec: ...
     @staticmethod
     @staticmethod
-    def toast_info(message: str = "", **kwargs): ...
+    def toast_info(message: str | Var = "", **kwargs): ...
     @staticmethod
     @staticmethod
-    def toast_warning(message: str = "", **kwargs): ...
+    def toast_warning(message: str | Var = "", **kwargs): ...
     @staticmethod
     @staticmethod
-    def toast_error(message: str = "", **kwargs): ...
+    def toast_error(message: str | Var = "", **kwargs): ...
     @staticmethod
     @staticmethod
-    def toast_success(message: str = "", **kwargs): ...
+    def toast_success(message: str | Var = "", **kwargs): ...
     @staticmethod
     @staticmethod
     def toast_dismiss(id: Var | str | None = None): ...
     def toast_dismiss(id: Var | str | None = None): ...
     @overload
     @overload
@@ -176,7 +176,7 @@ class ToastNamespace(ComponentNamespace):
 
 
     @staticmethod
     @staticmethod
     def __call__(
     def __call__(
-        message: str = "", level: Optional[str] = None, **props
+        message: Union[str, Var] = "", level: Optional[str] = None, **props
     ) -> "Optional[EventSpec]":
     ) -> "Optional[EventSpec]":
         """Send a toast message.
         """Send a toast message.
 
 

+ 43 - 16
reflex/config.py

@@ -7,6 +7,7 @@ import importlib
 import inspect
 import inspect
 import os
 import os
 import sys
 import sys
+import threading
 import urllib.parse
 import urllib.parse
 from importlib.util import find_spec
 from importlib.util import find_spec
 from pathlib import Path
 from pathlib import Path
@@ -468,6 +469,14 @@ class PathExistsFlag:
 ExistingPath = Annotated[Path, PathExistsFlag]
 ExistingPath = Annotated[Path, PathExistsFlag]
 
 
 
 
+class PerformanceMode(enum.Enum):
+    """Performance mode for the app."""
+
+    WARN = "warn"
+    RAISE = "raise"
+    OFF = "off"
+
+
 class EnvironmentVariables:
 class EnvironmentVariables:
     """Environment variables class to instantiate environment variables."""
     """Environment variables class to instantiate environment variables."""
 
 
@@ -571,6 +580,15 @@ class EnvironmentVariables:
     # Where to save screenshots when tests fail.
     # Where to save screenshots when tests fail.
     SCREENSHOT_DIR: EnvVar[Optional[Path]] = env_var(None)
     SCREENSHOT_DIR: EnvVar[Optional[Path]] = env_var(None)
 
 
+    # Whether to check for outdated package versions.
+    REFLEX_CHECK_LATEST_VERSION: EnvVar[bool] = env_var(True)
+
+    # In which performance mode to run the app.
+    REFLEX_PERF_MODE: EnvVar[Optional[PerformanceMode]] = env_var(PerformanceMode.WARN)
+
+    # The maximum size of the reflex state in kilobytes.
+    REFLEX_STATE_SIZE_LIMIT: EnvVar[int] = env_var(1000)
+
     # Whether to minify state names. Default to true in prod mode and false otherwise.
     # Whether to minify state names. Default to true in prod mode and false otherwise.
     REFLEX_MINIFY_STATES: EnvVar[Optional[bool]] = env_var(
     REFLEX_MINIFY_STATES: EnvVar[Optional[bool]] = env_var(
         default_factory=lambda: EnvironmentVariables.REFLEX_ENV_MODE.get()
         default_factory=lambda: EnvironmentVariables.REFLEX_ENV_MODE.get()
@@ -844,6 +862,10 @@ def _get_config() -> Config:
     return rxconfig.config
     return rxconfig.config
 
 
 
 
+# Protect sys.path from concurrent modification
+_config_lock = threading.RLock()
+
+
 def get_config(reload: bool = False) -> Config:
 def get_config(reload: bool = False) -> Config:
     """Get the app config.
     """Get the app config.
 
 
@@ -853,21 +875,26 @@ def get_config(reload: bool = False) -> Config:
     Returns:
     Returns:
         The app config.
         The app config.
     """
     """
-    # Remove any cached module when `reload` is requested.
-    if reload and constants.Config.MODULE in sys.modules:
-        del sys.modules[constants.Config.MODULE]
+    cached_rxconfig = sys.modules.get(constants.Config.MODULE, None)
+    if cached_rxconfig is not None:
+        if reload:
+            # Remove any cached module when `reload` is requested.
+            del sys.modules[constants.Config.MODULE]
+        else:
+            return cached_rxconfig.config
 
 
-    sys_path = sys.path.copy()
-    sys.path.clear()
-    sys.path.append(os.getcwd())
-    try:
-        # Try to import the module with only the current directory in the path.
-        return _get_config()
-    except Exception:
-        # If the module import fails, try to import with the original sys.path.
-        sys.path.extend(sys_path)
-        return _get_config()
-    finally:
-        # Restore the original sys.path.
+    with _config_lock:
+        sys_path = sys.path.copy()
         sys.path.clear()
         sys.path.clear()
-        sys.path.extend(sys_path)
+        sys.path.append(os.getcwd())
+        try:
+            # Try to import the module with only the current directory in the path.
+            return _get_config()
+        except Exception:
+            # If the module import fails, try to import with the original sys.path.
+            sys.path.extend(sys_path)
+            return _get_config()
+        finally:
+            # Restore the original sys.path.
+            sys.path.clear()
+            sys.path.extend(sys_path)

+ 12 - 0
reflex/constants/base.py

@@ -97,6 +97,18 @@ class Templates(SimpleNamespace):
     # The default template
     # The default template
     DEFAULT = "blank"
     DEFAULT = "blank"
 
 
+    # The AI template
+    AI = "ai"
+
+    # The option for the user to choose a remote template.
+    CHOOSE_TEMPLATES = "choose-templates"
+
+    # The URL to find reflex templates.
+    REFLEX_TEMPLATES_URL = "https://reflex.dev/templates"
+
+    # Demo url for the default template.
+    DEFAULT_TEMPLATE_URL = "https://blank-template.reflex.run"
+
     # The reflex.build frontend host
     # The reflex.build frontend host
     REFLEX_BUILD_FRONTEND = "https://flexgen.reflex.run"
     REFLEX_BUILD_FRONTEND = "https://flexgen.reflex.run"
 
 

+ 16 - 0
reflex/event.py

@@ -181,6 +181,18 @@ class EventActionsMixin:
             event_actions={"debounce": delay_ms, **self.event_actions},
             event_actions={"debounce": delay_ms, **self.event_actions},
         )
         )
 
 
+    @property
+    def temporal(self):
+        """Do not queue the event if the backend is down.
+
+        Returns:
+            New EventHandler-like with temporal set to True.
+        """
+        return dataclasses.replace(
+            self,
+            event_actions={"temporal": True, **self.event_actions},
+        )
+
 
 
 @dataclasses.dataclass(
 @dataclasses.dataclass(
     init=True,
     init=True,
@@ -1346,6 +1358,10 @@ def check_fn_match_arg_spec(
         EventFnArgMismatch: Raised if the number of mandatory arguments do not match
         EventFnArgMismatch: Raised if the number of mandatory arguments do not match
     """
     """
     user_args = inspect.getfullargspec(user_func).args
     user_args = inspect.getfullargspec(user_func).args
+    # Drop the first argument if it's a bound method
+    if inspect.ismethod(user_func) and user_func.__self__ is not None:
+        user_args = user_args[1:]
+
     user_default_args = inspect.getfullargspec(user_func).defaults
     user_default_args = inspect.getfullargspec(user_func).defaults
     number_of_user_args = len(user_args) - number_of_bound_args
     number_of_user_args = len(user_args) - number_of_bound_args
     number_of_user_default_args = len(user_default_args) if user_default_args else 0
     number_of_user_default_args = len(user_default_args) if user_default_args else 0

+ 14 - 36
reflex/experimental/assets.py

@@ -1,14 +1,15 @@
 """Helper functions for adding assets to the app."""
 """Helper functions for adding assets to the app."""
 
 
-import inspect
-from pathlib import Path
 from typing import Optional
 from typing import Optional
 
 
-from reflex import constants
+from reflex import assets
+from reflex.utils import console
 
 
 
 
 def asset(relative_filename: str, subfolder: Optional[str] = None) -> str:
 def asset(relative_filename: str, subfolder: Optional[str] = None) -> str:
-    """Add an asset to the app.
+    """DEPRECATED: use `rx.asset` with `shared=True` instead.
+
+    Add an asset to the app.
     Place the file next to your including python file.
     Place the file next to your including python file.
     Copies the file to the app's external assets directory.
     Copies the file to the app's external assets directory.
 
 
@@ -22,38 +23,15 @@ def asset(relative_filename: str, subfolder: Optional[str] = None) -> str:
         relative_filename: The relative filename of the asset.
         relative_filename: The relative filename of the asset.
         subfolder: The directory to place the asset in.
         subfolder: The directory to place the asset in.
 
 
-    Raises:
-        FileNotFoundError: If the file does not exist.
-        ValueError: If the module is None.
-
     Returns:
     Returns:
         The relative URL to the copied asset.
         The relative URL to the copied asset.
     """
     """
-    # Determine the file by which the asset is exposed.
-    calling_file = inspect.stack()[1].filename
-    module = inspect.getmodule(inspect.stack()[1][0])
-    if module is None:
-        raise ValueError("Module is None")
-    caller_module_path = module.__name__.replace(".", "/")
-
-    subfolder = f"{caller_module_path}/{subfolder}" if subfolder else caller_module_path
-
-    src_file = Path(calling_file).parent / relative_filename
-
-    assets = constants.Dirs.APP_ASSETS
-    external = constants.Dirs.EXTERNAL_APP_ASSETS
-
-    if not src_file.exists():
-        raise FileNotFoundError(f"File not found: {src_file}")
-
-    # Create the asset folder in the currently compiling app.
-    asset_folder = Path.cwd() / assets / external / subfolder
-    asset_folder.mkdir(parents=True, exist_ok=True)
-
-    dst_file = asset_folder / relative_filename
-
-    if not dst_file.exists():
-        dst_file.symlink_to(src_file)
-
-    asset_url = f"/{external}/{subfolder}/{relative_filename}"
-    return asset_url
+    console.deprecate(
+        feature_name="rx._x.asset",
+        reason="Use `rx.asset` with `shared=True` instead of `rx._x.asset`.",
+        deprecation_version="0.6.6",
+        removal_version="0.7.0",
+    )
+    return assets.asset(
+        relative_filename, shared=True, subfolder=subfolder, _stack_level=2
+    )

+ 5 - 28
reflex/reflex.py

@@ -17,10 +17,10 @@ from reflex_cli.v2.deployments import check_version, hosting_cli
 from reflex import constants
 from reflex import constants
 from reflex.config import EnvironmentVariables, get_config
 from reflex.config import EnvironmentVariables, get_config
 from reflex.custom_components.custom_components import custom_components_cli
 from reflex.custom_components.custom_components import custom_components_cli
-from reflex.utils import console, redir, telemetry
+from reflex.utils import console, telemetry
 
 
 # Disable typer+rich integration for help panels
 # Disable typer+rich integration for help panels
-typer.core.rich = False  # type: ignore
+typer.core.rich = None  # type: ignore
 
 
 # Create the app.
 # Create the app.
 try:
 try:
@@ -89,30 +89,8 @@ def _init(
     # Set up the web project.
     # Set up the web project.
     prerequisites.initialize_frontend_dependencies()
     prerequisites.initialize_frontend_dependencies()
 
 
-    # Integrate with reflex.build.
-    generation_hash = None
-    if ai:
-        if template is None:
-            # If AI is requested and no template specified, redirect the user to reflex.build.
-            generation_hash = redir.reflex_build_redirect()
-        elif prerequisites.is_generation_hash(template):
-            # Otherwise treat the template as a generation hash.
-            generation_hash = template
-        else:
-            console.error(
-                "Cannot use `--template` option with `--ai` option. Please remove `--template` option."
-            )
-            raise typer.Exit(2)
-        template = constants.Templates.DEFAULT
-
     # Initialize the app.
     # Initialize the app.
-    template = prerequisites.initialize_app(app_name, template)
-
-    # If a reflex.build generation hash is available, download the code and apply it to the main module.
-    if generation_hash:
-        prerequisites.initialize_main_module_index_from_generation(
-            app_name, generation_hash=generation_hash
-        )
+    template = prerequisites.initialize_app(app_name, template, ai)
 
 
     # Initialize the .gitignore.
     # Initialize the .gitignore.
     prerequisites.initialize_gitignore()
     prerequisites.initialize_gitignore()
@@ -120,7 +98,7 @@ def _init(
     # Initialize the requirements.txt.
     # Initialize the requirements.txt.
     prerequisites.initialize_requirements_txt()
     prerequisites.initialize_requirements_txt()
 
 
-    template_msg = "" if not template else f" using the {template} template"
+    template_msg = f" using the {template} template" if template else ""
     # Finish initializing the app.
     # Finish initializing the app.
     console.success(f"Initialized {app_name}{template_msg}")
     console.success(f"Initialized {app_name}{template_msg}")
 
 
@@ -675,8 +653,7 @@ def deployv2(
     project: Optional[str] = typer.Option(
     project: Optional[str] = typer.Option(
         None,
         None,
         "--project",
         "--project",
-        help="project to deploy to",
-        hidden=True,
+        help="project id to deploy to",
     ),
     ),
     token: Optional[str] = typer.Option(
     token: Optional[str] = typer.Option(
         None,
         None,

+ 53 - 15
reflex/state.py

@@ -43,7 +43,7 @@ from sqlalchemy.orm import DeclarativeBase
 from typing_extensions import Self
 from typing_extensions import Self
 
 
 from reflex import event
 from reflex import event
-from reflex.config import get_config
+from reflex.config import PerformanceMode, get_config
 from reflex.istate.data import RouterData
 from reflex.istate.data import RouterData
 from reflex.istate.storage import ClientStorageBase
 from reflex.istate.storage import ClientStorageBase
 from reflex.model import Model
 from reflex.model import Model
@@ -62,6 +62,13 @@ try:
 except ModuleNotFoundError:
 except ModuleNotFoundError:
     import pydantic
     import pydantic
 
 
+from pydantic import BaseModel as BaseModelV2
+
+try:
+    from pydantic.v1 import BaseModel as BaseModelV1
+except ModuleNotFoundError:
+    BaseModelV1 = BaseModelV2
+
 import wrapt
 import wrapt
 from redis.asyncio import Redis
 from redis.asyncio import Redis
 from redis.exceptions import ResponseError
 from redis.exceptions import ResponseError
@@ -90,6 +97,7 @@ from reflex.utils.exceptions import (
     ReflexRuntimeError,
     ReflexRuntimeError,
     SetUndefinedStateVarError,
     SetUndefinedStateVarError,
     StateSchemaMismatchError,
     StateSchemaMismatchError,
+    StateTooLargeError,
 )
 )
 from reflex.utils.exec import is_testing_env
 from reflex.utils.exec import is_testing_env
 from reflex.utils.serializers import serializer
 from reflex.utils.serializers import serializer
@@ -110,10 +118,13 @@ Delta = Dict[str, Any]
 var = computed_var
 var = computed_var
 
 
 
 
-# If the state is this large, it's considered a performance issue.
-TOO_LARGE_SERIALIZED_STATE = 100 * 1024  # 100kb
-# Only warn about each state class size once.
-_WARNED_ABOUT_STATE_SIZE: Set[str] = set()
+if EnvironmentVariables.REFLEX_PERF_MODE.get() != PerformanceMode.OFF:
+    # If the state is this large, it's considered a performance issue.
+    TOO_LARGE_SERIALIZED_STATE = (
+        EnvironmentVariables.REFLEX_STATE_SIZE_LIMIT.get() * 1024
+    )
+    # Only warn about each state class size once.
+    _WARNED_ABOUT_STATE_SIZE: Set[str] = set()
 
 
 # Errors caught during pickling of state
 # Errors caught during pickling of state
 HANDLED_PICKLE_ERRORS = (
 HANDLED_PICKLE_ERRORS = (
@@ -1306,7 +1317,7 @@ class BaseState(Base, ABC, extra=pydantic.Extra.allow):
             if parent_state is not None:
             if parent_state is not None:
                 return getattr(parent_state, name)
                 return getattr(parent_state, name)
 
 
-        if isinstance(value, MutableProxy.__mutable_types__) and (
+        if MutableProxy._is_mutable_type(value) and (
             name in super().__getattribute__("base_vars") or name in backend_vars
             name in super().__getattribute__("base_vars") or name in backend_vars
         ):
         ):
             # track changes in mutable containers (list, dict, set, etc)
             # track changes in mutable containers (list, dict, set, etc)
@@ -2155,7 +2166,7 @@ class BaseState(Base, ABC, extra=pydantic.Extra.allow):
             state["__dict__"].pop(inherited_var_name, None)
             state["__dict__"].pop(inherited_var_name, None)
         return state
         return state
 
 
-    def _warn_if_too_large(
+    def _check_state_size(
         self,
         self,
         pickle_state_size: int,
         pickle_state_size: int,
     ):
     ):
@@ -2163,6 +2174,9 @@ class BaseState(Base, ABC, extra=pydantic.Extra.allow):
 
 
         Args:
         Args:
             pickle_state_size: The size of the pickled state.
             pickle_state_size: The size of the pickled state.
+
+        Raises:
+            StateTooLargeError: If the state is too large.
         """
         """
         state_full_name = self.get_full_name()
         state_full_name = self.get_full_name()
         if (
         if (
@@ -2170,10 +2184,14 @@ class BaseState(Base, ABC, extra=pydantic.Extra.allow):
             and pickle_state_size > TOO_LARGE_SERIALIZED_STATE
             and pickle_state_size > TOO_LARGE_SERIALIZED_STATE
             and self.substates
             and self.substates
         ):
         ):
-            console.warn(
+            msg = (
                 f"State {state_full_name} serializes to {pickle_state_size} bytes "
                 f"State {state_full_name} serializes to {pickle_state_size} bytes "
-                "which may present performance issues. Consider reducing the size of this state."
+                + "which may present performance issues. Consider reducing the size of this state."
             )
             )
+            if EnvironmentVariables.REFLEX_PERF_MODE.get() == PerformanceMode.WARN:
+                console.warn(msg)
+            elif EnvironmentVariables.REFLEX_PERF_MODE.get() == PerformanceMode.RAISE:
+                raise StateTooLargeError(msg)
             _WARNED_ABOUT_STATE_SIZE.add(state_full_name)
             _WARNED_ABOUT_STATE_SIZE.add(state_full_name)
 
 
     @classmethod
     @classmethod
@@ -2215,7 +2233,8 @@ class BaseState(Base, ABC, extra=pydantic.Extra.allow):
         """
         """
         try:
         try:
             pickle_state = pickle.dumps((self._to_schema(), self))
             pickle_state = pickle.dumps((self._to_schema(), self))
-            self._warn_if_too_large(len(pickle_state))
+            if EnvironmentVariables.REFLEX_PERF_MODE.get() != PerformanceMode.OFF:
+                self._check_state_size(len(pickle_state))
             return pickle_state
             return pickle_state
         except HANDLED_PICKLE_ERRORS as og_pickle_error:
         except HANDLED_PICKLE_ERRORS as og_pickle_error:
             error = (
             error = (
@@ -3606,7 +3625,16 @@ class MutableProxy(wrapt.ObjectProxy):
         pydantic.BaseModel.__dict__
         pydantic.BaseModel.__dict__
     )
     )
 
 
-    __mutable_types__ = (list, dict, set, Base, DeclarativeBase)
+    # These types will be wrapped in MutableProxy
+    __mutable_types__ = (
+        list,
+        dict,
+        set,
+        Base,
+        DeclarativeBase,
+        BaseModelV2,
+        BaseModelV1,
+    )
 
 
     def __init__(self, wrapped: Any, state: BaseState, field_name: str):
     def __init__(self, wrapped: Any, state: BaseState, field_name: str):
         """Create a proxy for a mutable object that tracks changes.
         """Create a proxy for a mutable object that tracks changes.
@@ -3646,6 +3674,18 @@ class MutableProxy(wrapt.ObjectProxy):
         if wrapped is not None:
         if wrapped is not None:
             return wrapped(*args, **(kwargs or {}))
             return wrapped(*args, **(kwargs or {}))
 
 
+    @classmethod
+    def _is_mutable_type(cls, value: Any) -> bool:
+        """Check if a value is of a mutable type and should be wrapped.
+
+        Args:
+            value: The value to check.
+
+        Returns:
+            Whether the value is of a mutable type.
+        """
+        return isinstance(value, cls.__mutable_types__)
+
     def _wrap_recursive(self, value: Any) -> Any:
     def _wrap_recursive(self, value: Any) -> Any:
         """Wrap a value recursively if it is mutable.
         """Wrap a value recursively if it is mutable.
 
 
@@ -3656,9 +3696,7 @@ class MutableProxy(wrapt.ObjectProxy):
             The wrapped value.
             The wrapped value.
         """
         """
         # Recursively wrap mutable types, but do not re-wrap MutableProxy instances.
         # Recursively wrap mutable types, but do not re-wrap MutableProxy instances.
-        if isinstance(value, self.__mutable_types__) and not isinstance(
-            value, MutableProxy
-        ):
+        if self._is_mutable_type(value) and not isinstance(value, MutableProxy):
             return type(self)(
             return type(self)(
                 wrapped=value,
                 wrapped=value,
                 state=self._self_state,
                 state=self._self_state,
@@ -3716,7 +3754,7 @@ class MutableProxy(wrapt.ObjectProxy):
                     self._wrap_recursive_decorator,
                     self._wrap_recursive_decorator,
                 )
                 )
 
 
-        if isinstance(value, self.__mutable_types__) and __name not in (
+        if self._is_mutable_type(value) and __name not in (
             "__wrapped__",
             "__wrapped__",
             "_self_state",
             "_self_state",
         ):
         ):

+ 4 - 0
reflex/utils/exceptions.py

@@ -151,6 +151,10 @@ class InvalidPropValueError(ReflexError):
     """Raised when a prop value is invalid."""
     """Raised when a prop value is invalid."""
 
 
 
 
+class StateTooLargeError(ReflexError):
+    """Raised when the state is too large to be serialized."""
+
+
 class SystemPackageMissingError(ReflexError):
 class SystemPackageMissingError(ReflexError):
     """Raised when a system package is missing."""
     """Raised when a system package is missing."""
 
 

+ 172 - 42
reflex/utils/prerequisites.py

@@ -34,7 +34,7 @@ from redis.asyncio import Redis
 from reflex import constants, model
 from reflex import constants, model
 from reflex.compiler import templates
 from reflex.compiler import templates
 from reflex.config import Config, EnvironmentVariables, get_config
 from reflex.config import Config, EnvironmentVariables, get_config
-from reflex.utils import console, net, path_ops, processes
+from reflex.utils import console, net, path_ops, processes, redir
 from reflex.utils.exceptions import (
 from reflex.utils.exceptions import (
     GeneratedCodeHasNoFunctionDefs,
     GeneratedCodeHasNoFunctionDefs,
     raise_system_package_missing_error,
     raise_system_package_missing_error,
@@ -93,6 +93,8 @@ def check_latest_package_version(package_name: str):
     Args:
     Args:
         package_name: The name of the package.
         package_name: The name of the package.
     """
     """
+    if EnvironmentVariables.REFLEX_CHECK_LATEST_VERSION.get() is False:
+        return
     try:
     try:
         # Get the latest version from PyPI
         # Get the latest version from PyPI
         current_version = importlib.metadata.version(package_name)
         current_version = importlib.metadata.version(package_name)
@@ -1212,7 +1214,7 @@ def check_schema_up_to_date():
                 )
                 )
 
 
 
 
-def prompt_for_template(templates: list[Template]) -> str:
+def prompt_for_template_options(templates: list[Template]) -> str:
     """Prompt the user to specify a template.
     """Prompt the user to specify a template.
 
 
     Args:
     Args:
@@ -1224,9 +1226,14 @@ def prompt_for_template(templates: list[Template]) -> str:
     # Show the user the URLs of each template to preview.
     # Show the user the URLs of each template to preview.
     console.print("\nGet started with a template:")
     console.print("\nGet started with a template:")
 
 
+    def format_demo_url_str(url: str) -> str:
+        return f" ({url})" if url else ""
+
     # Prompt the user to select a template.
     # Prompt the user to select a template.
     id_to_name = {
     id_to_name = {
-        str(idx): f"{template.name} ({template.demo_url}) - {template.description}"
+        str(
+            idx
+        ): f"{template.name.replace('_', ' ').replace('-', ' ')}{format_demo_url_str(template.demo_url)} - {template.description}"
         for idx, template in enumerate(templates)
         for idx, template in enumerate(templates)
     }
     }
     for id in range(len(id_to_name)):
     for id in range(len(id_to_name)):
@@ -1381,15 +1388,119 @@ def create_config_init_app_from_remote_template(app_name: str, template_url: str
     shutil.rmtree(unzip_dir)
     shutil.rmtree(unzip_dir)
 
 
 
 
-def initialize_app(app_name: str, template: str | None = None) -> str | None:
-    """Initialize the app either from a remote template or a blank app. If the config file exists, it is considered as reinit.
+def initialize_default_app(app_name: str):
+    """Initialize the default app.
 
 
     Args:
     Args:
         app_name: The name of the app.
         app_name: The name of the app.
-        template: The name of the template to use.
+    """
+    create_config(app_name)
+    initialize_app_directory(app_name)
+
+
+def validate_and_create_app_using_remote_template(app_name, template, templates):
+    """Validate and create an app using a remote template.
+
+    Args:
+        app_name: The name of the app.
+        template: The name of the template.
+        templates: The available templates.
+
+    Raises:
+        Exit: If the template is not found.
+    """
+    # If user selects a template, it needs to exist.
+    if template in templates:
+        template_url = templates[template].code_url
+    else:
+        # Check if the template is a github repo.
+        if template.startswith("https://github.com"):
+            template_url = f"{template.strip('/').replace('.git', '')}/archive/main.zip"
+        else:
+            console.error(f"Template `{template}` not found.")
+            raise typer.Exit(1)
+
+    if template_url is None:
+        return
+
+    create_config_init_app_from_remote_template(
+        app_name=app_name, template_url=template_url
+    )
+
+
+def generate_template_using_ai(template: str | None = None) -> str:
+    """Generate a template using AI(Flexgen).
+
+    Args:
+        template: The name of the template.
+
+    Returns:
+        The generation hash.
+
+    Raises:
+        Exit: If the template and ai flags are used.
+    """
+    if template is None:
+        # If AI is requested and no template specified, redirect the user to reflex.build.
+        return redir.reflex_build_redirect()
+    elif is_generation_hash(template):
+        # Otherwise treat the template as a generation hash.
+        return template
+    else:
+        console.error(
+            "Cannot use `--template` option with `--ai` option. Please remove `--template` option."
+        )
+        raise typer.Exit(2)
+
+
+def fetch_remote_templates(
+    template: Optional[str] = None,
+) -> tuple[str, dict[str, Template]]:
+    """Fetch the available remote templates.
+
+    Args:
+        template: The name of the template.
+
+    Returns:
+        The selected template and the available templates.
 
 
     Raises:
     Raises:
-        Exit: If template is directly provided in the command flag and is invalid.
+        Exit: If the template is not valid or if the template is not specified.
+    """
+    available_templates = {}
+
+    try:
+        # Get the available templates
+        available_templates = fetch_app_templates(constants.Reflex.VERSION)
+    except Exception as e:
+        console.warn("Failed to fetch templates. Falling back to default template.")
+        console.debug(f"Error while fetching templates: {e}")
+        template = constants.Templates.DEFAULT
+
+    if template == constants.Templates.DEFAULT:
+        return template, available_templates
+
+    if template in available_templates:
+        return template, available_templates
+
+    else:
+        if template is not None:
+            console.error(f"{template!r} is not a valid template name.")
+        console.print(
+            f"Go to the templates page ({constants.Templates.REFLEX_TEMPLATES_URL}) and copy the command to init with a template."
+        )
+        raise typer.Exit(0)
+
+
+def initialize_app(
+    app_name: str, template: str | None = None, ai: bool = False
+) -> str | None:
+    """Initialize the app either from a remote template or a blank app. If the config file exists, it is considered as reinit.
+
+    Args:
+        app_name: The name of the app.
+        template: The name of the template to use.
+        ai: Whether to use AI to generate the template.
 
 
     Returns:
     Returns:
         The name of the template.
         The name of the template.
@@ -1402,54 +1513,73 @@ def initialize_app(app_name: str, template: str | None = None) -> str | None:
         telemetry.send("reinit")
         telemetry.send("reinit")
         return
         return
 
 
+    generation_hash = None
+    if ai:
+        generation_hash = generate_template_using_ai(template)
+        template = constants.Templates.DEFAULT
+
     templates: dict[str, Template] = {}
     templates: dict[str, Template] = {}
 
 
     # Don't fetch app templates if the user directly asked for DEFAULT.
     # Don't fetch app templates if the user directly asked for DEFAULT.
-    if template is None or (template != constants.Templates.DEFAULT):
-        try:
-            # Get the available templates
-            templates = fetch_app_templates(constants.Reflex.VERSION)
-            if template is None and len(templates) > 0:
-                template = prompt_for_template(list(templates.values()))
-        except Exception as e:
-            console.warn("Failed to fetch templates. Falling back to default template.")
-            console.debug(f"Error while fetching templates: {e}")
-        finally:
-            template = template or constants.Templates.DEFAULT
+    if template is not None and (template not in (constants.Templates.DEFAULT,)):
+        template, templates = fetch_remote_templates(template)
+
+    if template is None:
+        template = prompt_for_template_options(get_init_cli_prompt_options())
+        if template == constants.Templates.AI:
+            generation_hash = generate_template_using_ai()
+            # change to the default to allow creation of default app
+            template = constants.Templates.DEFAULT
+        elif template == constants.Templates.CHOOSE_TEMPLATES:
+            template, templates = fetch_remote_templates()
 
 
     # If the blank template is selected, create a blank app.
     # If the blank template is selected, create a blank app.
-    if template == constants.Templates.DEFAULT:
+    if template in (constants.Templates.DEFAULT,):
         # Default app creation behavior: a blank app.
         # Default app creation behavior: a blank app.
-        create_config(app_name)
-        initialize_app_directory(app_name)
+        initialize_default_app(app_name)
     else:
     else:
-        # Fetch App templates from the backend server.
-        console.debug(f"Available templates: {templates}")
-
-        # If user selects a template, it needs to exist.
-        if template in templates:
-            template_url = templates[template].code_url
-        else:
-            # Check if the template is a github repo.
-            if template.startswith("https://github.com"):
-                template_url = (
-                    f"{template.strip('/').replace('.git', '')}/archive/main.zip"
-                )
-            else:
-                console.error(f"Template `{template}` not found.")
-                raise typer.Exit(1)
-
-        if template_url is None:
-            return
-
-        create_config_init_app_from_remote_template(
-            app_name=app_name, template_url=template_url
+        validate_and_create_app_using_remote_template(
+            app_name=app_name, template=template, templates=templates
         )
         )
 
 
+    # If a reflex.build generation hash is available, download the code and apply it to the main module.
+    if generation_hash:
+        initialize_main_module_index_from_generation(
+            app_name, generation_hash=generation_hash
+        )
     telemetry.send("init", template=template)
     telemetry.send("init", template=template)
+
     return template
     return template
 
 
 
 
+def get_init_cli_prompt_options() -> list[Template]:
+    """Get the CLI options for initializing a Reflex app.
+
+    Returns:
+        The CLI options.
+    """
+    return [
+        Template(
+            name=constants.Templates.DEFAULT,
+            description="A blank Reflex app.",
+            demo_url=constants.Templates.DEFAULT_TEMPLATE_URL,
+            code_url="",
+        ),
+        Template(
+            name=constants.Templates.AI,
+            description="Generate a template using AI [Experimental]",
+            demo_url="",
+            code_url="",
+        ),
+        Template(
+            name=constants.Templates.CHOOSE_TEMPLATES,
+            description="Choose an existing template.",
+            demo_url="",
+            code_url="",
+        ),
+    ]
+
+
 def initialize_main_module_index_from_generation(app_name: str, generation_hash: str):
 def initialize_main_module_index_from_generation(app_name: str, generation_hash: str):
     """Overwrite the `index` function in the main module with reflex.build generated code.
     """Overwrite the `index` function in the main module with reflex.build generated code.
 
 

+ 13 - 4
reflex/utils/redir.py

@@ -10,6 +10,18 @@ from .. import constants
 from . import console
 from . import console
 
 
 
 
+def open_browser(target_url: str) -> None:
+    """Open a browser window to target_url.
+
+    Args:
+        target_url: The URL to open in the browser.
+    """
+    if not webbrowser.open(target_url):
+        console.warn(
+            f"Unable to automatically open the browser. Please navigate to {target_url} in your browser."
+        )
+
+
 def open_browser_and_wait(
 def open_browser_and_wait(
     target_url: str, poll_url: str, interval: int = 2
     target_url: str, poll_url: str, interval: int = 2
 ) -> httpx.Response:
 ) -> httpx.Response:
@@ -23,10 +35,7 @@ def open_browser_and_wait(
     Returns:
     Returns:
         The response from the poll_url.
         The response from the poll_url.
     """
     """
-    if not webbrowser.open(target_url):
-        console.warn(
-            f"Unable to automatically open the browser. Please navigate to {target_url} in your browser."
-        )
+    open_browser(target_url)
     console.info("[b]Complete the workflow in the browser to continue.[/b]")
     console.info("[b]Complete the workflow in the browser to continue.[/b]")
     while True:
     while True:
         try:
         try:

+ 47 - 0
reflex/utils/serializers.py

@@ -270,6 +270,53 @@ def serialize_base(value: Base) -> dict:
     }
     }
 
 
 
 
+try:
+    from pydantic.v1 import BaseModel as BaseModelV1
+
+    @serializer(to=dict)
+    def serialize_base_model_v1(model: BaseModelV1) -> dict:
+        """Serialize a pydantic v1 BaseModel instance.
+
+        Args:
+            model: The BaseModel to serialize.
+
+        Returns:
+            The serialized BaseModel.
+        """
+        return model.dict()
+
+    from pydantic import BaseModel as BaseModelV2
+
+    if BaseModelV1 is not BaseModelV2:
+
+        @serializer(to=dict)
+        def serialize_base_model_v2(model: BaseModelV2) -> dict:
+            """Serialize a pydantic v2 BaseModel instance.
+
+            Args:
+                model: The BaseModel to serialize.
+
+            Returns:
+                The serialized BaseModel.
+            """
+            return model.model_dump()
+except ImportError:
+    # Older pydantic v1 import
+    from pydantic import BaseModel as BaseModelV1
+
+    @serializer(to=dict)
+    def serialize_base_model_v1(model: BaseModelV1) -> dict:
+        """Serialize a pydantic v1 BaseModel instance.
+
+        Args:
+            model: The BaseModel to serialize.
+
+        Returns:
+            The serialized BaseModel.
+        """
+        return model.dict()
+
+
 @serializer
 @serializer
 def serialize_set(value: Set) -> list:
 def serialize_set(value: Set) -> list:
     """Serialize a set to a JSON serializable list.
     """Serialize a set to a JSON serializable list.

+ 4 - 0
reflex/utils/types.py

@@ -576,6 +576,10 @@ def _isinstance(obj: Any, cls: GenericType, nested: bool = False) -> bool:
                 return does_obj_satisfy_typed_dict(obj, cls)
                 return does_obj_satisfy_typed_dict(obj, cls)
             return isinstance(obj, dict)
             return isinstance(obj, dict)
 
 
+        # cls is a float
+        if cls is float:
+            return isinstance(obj, (float, int))
+
         # cls is a simple class
         # cls is a simple class
         return isinstance(obj, cls)
         return isinstance(obj, cls)
 
 

+ 0 - 0
tests/units/experimental/custom_script.js → tests/units/assets/custom_script.js


+ 94 - 0
tests/units/assets/test_assets.py

@@ -0,0 +1,94 @@
+import shutil
+from pathlib import Path
+from typing import Generator
+
+import pytest
+
+import reflex as rx
+import reflex.constants as constants
+
+
+def test_shared_asset() -> None:
+    """Test shared assets."""
+    # The asset function copies a file to the app's external assets directory.
+    asset = rx.asset(path="custom_script.js", shared=True, subfolder="subfolder")
+    assert asset == "/external/test_assets/subfolder/custom_script.js"
+    result_file = Path(
+        Path.cwd(), "assets/external/test_assets/subfolder/custom_script.js"
+    )
+    assert result_file.exists()
+
+    # Running a second time should not raise an error.
+    asset = rx.asset(path="custom_script.js", shared=True, subfolder="subfolder")
+
+    # Test the asset function without a subfolder.
+    asset = rx.asset(path="custom_script.js", shared=True)
+    assert asset == "/external/test_assets/custom_script.js"
+    result_file = Path(Path.cwd(), "assets/external/test_assets/custom_script.js")
+    assert result_file.exists()
+
+    # clean up
+    shutil.rmtree(Path.cwd() / "assets/external")
+
+    with pytest.raises(FileNotFoundError):
+        asset = rx.asset("non_existent_file.js")
+
+    # Nothing is done to assets when file does not exist.
+    assert not Path(Path.cwd() / "assets/external").exists()
+
+
+def test_deprecated_x_asset(capsys) -> None:
+    """Test that the deprecated asset function raises a warning.
+
+    Args:
+        capsys: Pytest fixture that captures stdout and stderr.
+    """
+    assert rx.asset("custom_script.js", shared=True) == rx._x.asset("custom_script.js")
+    assert (
+        "DeprecationWarning: rx._x.asset has been deprecated in version 0.6.6"
+        in capsys.readouterr().out
+    )
+
+
+@pytest.mark.parametrize(
+    "path,shared",
+    [
+        pytest.param("non_existing_file", True),
+        pytest.param("non_existing_file", False),
+    ],
+)
+def test_invalid_assets(path: str, shared: bool) -> None:
+    """Test that asset raises an error when the file does not exist.
+
+    Args:
+        path: The path to the asset.
+        shared: Whether the asset should be shared.
+    """
+    with pytest.raises(FileNotFoundError):
+        _ = rx.asset(path, shared=shared)
+
+
+@pytest.fixture
+def custom_script_in_asset_dir() -> Generator[Path, None, None]:
+    """Create a custom_script.js file in the app's assets directory.
+
+    Yields:
+        The path to the custom_script.js file.
+    """
+    asset_dir = Path.cwd() / constants.Dirs.APP_ASSETS
+    asset_dir.mkdir(exist_ok=True)
+    path = asset_dir / "custom_script.js"
+    path.touch()
+    yield path
+    path.unlink()
+
+
+def test_local_asset(custom_script_in_asset_dir: Path) -> None:
+    """Test that no error is raised if shared is set and both files exist.
+
+    Args:
+        custom_script_in_asset_dir: Fixture that creates a custom_script.js file in the app's assets directory.
+
+    """
+    asset = rx.asset("custom_script.js", shared=False)
+    assert asset == "/custom_script.js"

+ 0 - 36
tests/units/experimental/test_assets.py

@@ -1,36 +0,0 @@
-import shutil
-from pathlib import Path
-
-import pytest
-
-import reflex as rx
-
-
-def test_asset():
-    # Test the asset function.
-
-    # The asset function copies a file to the app's external assets directory.
-    asset = rx._x.asset("custom_script.js", "subfolder")
-    assert asset == "/external/test_assets/subfolder/custom_script.js"
-    result_file = Path(
-        Path.cwd(), "assets/external/test_assets/subfolder/custom_script.js"
-    )
-    assert result_file.exists()
-
-    # Running a second time should not raise an error.
-    asset = rx._x.asset("custom_script.js", "subfolder")
-
-    # Test the asset function without a subfolder.
-    asset = rx._x.asset("custom_script.js")
-    assert asset == "/external/test_assets/custom_script.js"
-    result_file = Path(Path.cwd(), "assets/external/test_assets/custom_script.js")
-    assert result_file.exists()
-
-    # clean up
-    shutil.rmtree(Path.cwd() / "assets/external")
-
-    with pytest.raises(FileNotFoundError):
-        asset = rx._x.asset("non_existent_file.js")
-
-    # Nothing is done to assets when file does not exist.
-    assert not Path(Path.cwd() / "assets/external").exists()

+ 15 - 0
tests/units/test_event.py

@@ -2,6 +2,7 @@ from typing import Callable, List
 
 
 import pytest
 import pytest
 
 
+import reflex as rx
 from reflex.event import (
 from reflex.event import (
     Event,
     Event,
     EventChain,
     EventChain,
@@ -439,3 +440,17 @@ def test_event_var_data():
     # Ensure chain carries _var_data
     # Ensure chain carries _var_data
     chain_var = Var.create(EventChain(events=[S.s(S.x)], args_spec=_args_spec))
     chain_var = Var.create(EventChain(events=[S.s(S.x)], args_spec=_args_spec))
     assert chain_var._get_all_var_data() == S.x._get_all_var_data()
     assert chain_var._get_all_var_data() == S.x._get_all_var_data()
+
+
+def test_event_bound_method() -> None:
+    class S(BaseState):
+        @event
+        def e(self, arg: str):
+            print(arg)
+
+    class Wrapper:
+        def get_handler(self, arg: str):
+            return S.e(arg)
+
+    w = Wrapper()
+    _ = rx.input(on_change=w.get_handler)

+ 49 - 0
tests/units/test_state.py

@@ -16,6 +16,8 @@ from unittest.mock import AsyncMock, Mock
 import pytest
 import pytest
 import pytest_asyncio
 import pytest_asyncio
 from plotly.graph_objects import Figure
 from plotly.graph_objects import Figure
+from pydantic import BaseModel as BaseModelV2
+from pydantic.v1 import BaseModel as BaseModelV1
 
 
 import reflex as rx
 import reflex as rx
 import reflex.config
 import reflex.config
@@ -3414,6 +3416,53 @@ def test_typed_state() -> None:
     _ = TypedState(field="str")
     _ = TypedState(field="str")
 
 
 
 
+class ModelV1(BaseModelV1):
+    """A pydantic BaseModel v1."""
+
+    foo: str = "bar"
+
+
+class ModelV2(BaseModelV2):
+    """A pydantic BaseModel v2."""
+
+    foo: str = "bar"
+
+
+@dataclasses.dataclass
+class ModelDC:
+    """A dataclass."""
+
+    foo: str = "bar"
+
+
+class PydanticState(rx.State):
+    """A state with pydantic BaseModel vars."""
+
+    v1: ModelV1 = ModelV1()
+    v2: ModelV2 = ModelV2()
+    dc: ModelDC = ModelDC()
+
+
+def test_mutable_models():
+    """Test that dataclass and pydantic BaseModel v1 and v2 use dep tracking."""
+    state = PydanticState()
+    assert isinstance(state.v1, MutableProxy)
+    state.v1.foo = "baz"
+    assert state.dirty_vars == {"v1"}
+    state.dirty_vars.clear()
+
+    assert isinstance(state.v2, MutableProxy)
+    state.v2.foo = "baz"
+    assert state.dirty_vars == {"v2"}
+    state.dirty_vars.clear()
+
+    # Not yet supported ENG-4083
+    # assert isinstance(state.dc, MutableProxy)
+    # state.dc.foo = "baz"
+    # assert state.dirty_vars == {"dc"}
+    # state.dirty_vars.clear()
+
+
 def test_get_value():
 def test_get_value():
     class GetValueState(rx.State):
     class GetValueState(rx.State):
         foo: str = "FOO"
         foo: str = "FOO"