arize-phoenix 8.26.0__py3-none-any.whl → 8.26.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of arize-phoenix might be problematic. Click here for more details.

Files changed (24) hide show
  1. {arize_phoenix-8.26.0.dist-info → arize_phoenix-8.26.2.dist-info}/METADATA +1 -2
  2. {arize_phoenix-8.26.0.dist-info → arize_phoenix-8.26.2.dist-info}/RECORD +24 -22
  3. phoenix/config.py +7 -8
  4. phoenix/server/api/mutations/user_mutations.py +2 -0
  5. phoenix/server/app.py +3 -32
  6. phoenix/server/main.py +0 -10
  7. phoenix/server/middleware/__init__.py +0 -0
  8. phoenix/server/middleware/gzip.py +33 -0
  9. phoenix/server/static/.vite/manifest.json +40 -40
  10. phoenix/server/static/assets/{components-B5CAbHpr.js → components-BpgLJxZt.js} +192 -192
  11. phoenix/server/static/assets/{index-DIP5WhNE.js → index-DHuvzpC2.js} +2 -2
  12. phoenix/server/static/assets/{pages-cfOsoZi6.js → pages-CNkfmPS4.js} +209 -209
  13. phoenix/server/static/assets/{vendor-DCvpCpca.js → vendor-C77BEnnR.js} +175 -170
  14. phoenix/server/static/assets/{vendor-arizeai-Ce3Kd6MM.js → vendor-arizeai-CMLBpPBs.js} +1 -1
  15. phoenix/server/static/assets/{vendor-codemirror-CoZ2wzq8.js → vendor-codemirror-DT1ReytN.js} +1 -1
  16. phoenix/server/static/assets/{vendor-recharts-Bv0CPtHC.js → vendor-recharts-ByEcbiML.js} +1 -1
  17. phoenix/server/static/assets/{vendor-shiki-CkOPKXne.js → vendor-shiki-DEgpVt4G.js} +1 -1
  18. phoenix/services.py +0 -4
  19. phoenix/session/session.py +0 -15
  20. phoenix/version.py +1 -1
  21. {arize_phoenix-8.26.0.dist-info → arize_phoenix-8.26.2.dist-info}/WHEEL +0 -0
  22. {arize_phoenix-8.26.0.dist-info → arize_phoenix-8.26.2.dist-info}/entry_points.txt +0 -0
  23. {arize_phoenix-8.26.0.dist-info → arize_phoenix-8.26.2.dist-info}/licenses/IP_NOTICE +0 -0
  24. {arize_phoenix-8.26.0.dist-info → arize_phoenix-8.26.2.dist-info}/licenses/LICENSE +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: arize-phoenix
3
- Version: 8.26.0
3
+ Version: 8.26.2
4
4
  Summary: AI Observability and Evaluation
5
5
  Project-URL: Documentation, https://docs.arize.com/phoenix/
6
6
  Project-URL: Issues, https://github.com/Arize-ai/phoenix/issues
@@ -53,7 +53,6 @@ Requires-Dist: strawberry-graphql>=0.262.0
53
53
  Requires-Dist: tqdm
54
54
  Requires-Dist: typing-extensions>=4.6
55
55
  Requires-Dist: uvicorn
56
- Requires-Dist: websockets
57
56
  Requires-Dist: wrapt>=1.17.2
58
57
  Provides-Extra: container
59
58
  Requires-Dist: aiohttp; extra == 'container'
@@ -1,12 +1,12 @@
1
1
  phoenix/__init__.py,sha256=X3eUEwd2rG8KKWWYVNNDJoqo08ihfjgHhlP29dcdNJE,5481
2
2
  phoenix/auth.py,sha256=VVMHrWN31tln3Zo4z6ofecrV4daiqJjLd8r85mqlxek,10939
3
- phoenix/config.py,sha256=GQUQ5l5IplbseE86-eVutD5pgU4uwxz3qCclb8tfmjg,39965
3
+ phoenix/config.py,sha256=NrZKYKtUFyQetptVpcgtiQwky8fx3ZOBTUz3--ln0p4,40049
4
4
  phoenix/datetime_utils.py,sha256=iJzNG6YJ6V7_u8B2iA7P2Z26FyxYbOPtx0dhJ7kNDHA,3398
5
5
  phoenix/exceptions.py,sha256=n2L2KKuecrdflB9MsCdAYCiSEvGJptIsfRkXMoJle7A,169
6
6
  phoenix/py.typed,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
7
- phoenix/services.py,sha256=kpW1WL0kiB8XJsO6XycvZVJ-lBkNoenhQ7atCvBoSe8,5365
7
+ phoenix/services.py,sha256=ngkyKGVatX3cO2WJdo2hKdaVKP-xJCMvqthvga6kJss,5196
8
8
  phoenix/settings.py,sha256=x87BX7hWGQQZbrW_vrYqFR_izCGfO9gFc--JXUG4Tdk,754
9
- phoenix/version.py,sha256=BXfuOm4YfpVYO9mbewzWBZMWjGUwIkmqobIy44BKJiw,23
9
+ phoenix/version.py,sha256=pB5g-Q3J7KRvul9go4Dd1MGegwWPs_1QfuHBfOycTXA,23
10
10
  phoenix/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
11
  phoenix/core/embedding_dimension.py,sha256=zKGbcvwOXgLf-yrJBpQyKtd-LEOPRKHnUToyAU8Owis,87
12
12
  phoenix/core/model.py,sha256=qBFraOtmwCCnWJltKNP18DDG0mULXigytlFsa6YOz6k,4837
@@ -80,13 +80,13 @@ phoenix/pointcloud/pointcloud.py,sha256=SN_1wXZcwKrtSnHGZLDZGx71orqE1WyVF7E-D58d
80
80
  phoenix/pointcloud/projectors.py,sha256=TQgwc9cJDjJkin1WZyZzgl3HsYrLLiyWD7Czy4jNW3U,1088
81
81
  phoenix/pointcloud/umap_parameters.py,sha256=db_WEPoamuWtopZx7tQfAXPnoE0MS8FkAV0_ThjEx_Q,1735
82
82
  phoenix/server/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
83
- phoenix/server/app.py,sha256=f9H8ekaGiMwCMbSf2kbQIUFKywY2VmaIuJgPlrC7obU,40221
83
+ phoenix/server/app.py,sha256=e62PuFqJLd_JJuBaLWB4EistfaUYo3NMG8CLQIt-YGQ,38658
84
84
  phoenix/server/bearer_auth.py,sha256=9AY0-aOSHm-B7OYB-20jFA7bETAA6S1_W1za42A8Yt8,6804
85
85
  phoenix/server/dml_event.py,sha256=MjJmVEKytq75chBOSyvYDusUnEbg1pHpIjR3pZkUaJA,2838
86
86
  phoenix/server/dml_event_handler.py,sha256=EZLXmCvx4pJrCkz29gxwKwmvmUkTtPCHw6klR-XM8qE,8258
87
87
  phoenix/server/grpc_server.py,sha256=SknR-iLIUqU9swiAyLhbCUREA1obOM6w49xgdK1AQDs,3839
88
88
  phoenix/server/jwt_store.py,sha256=asxzY4_ZBM2FWAMstHvhvnKUP_0AA3v3xPTL2IOgNqY,16831
89
- phoenix/server/main.py,sha256=qJcqXudiY65UeOWOaxP1-dqzrV-BBnbZu_IDd-qMKMk,16720
89
+ phoenix/server/main.py,sha256=3b8YF1uTHGiwQAn42sIbWC_fzcKjiAyTfZPNdjL-erg,16287
90
90
  phoenix/server/oauth2.py,sha256=EV4wcCwG0N7cJRcfGNURdP5rZgRVCeRDvXyle19A27Y,2064
91
91
  phoenix/server/prometheus.py,sha256=1KjvSfjSa2-BPjDybVMM_Kag316CsN-Zwt64YNr_snc,7825
92
92
  phoenix/server/rate_limiters.py,sha256=cFc73D2NaxqNZZDbwfIDw4So-fRVOJPBtqxOZ8Qky_s,7155
@@ -201,7 +201,7 @@ phoenix/server/api/mutations/prompt_version_tag_mutations.py,sha256=t77osYb5he2A
201
201
  phoenix/server/api/mutations/span_annotations_mutations.py,sha256=sumBLUqRKlgMASWdWwYItmIJ2l7AyAp_PlIYeXYfguc,5970
202
202
  phoenix/server/api/mutations/trace_annotations_mutations.py,sha256=sEcEt8hbMt8YMiRX5o3xcJ5rWWZbDeBPMNz2teZoi3U,5945
203
203
  phoenix/server/api/mutations/trace_mutations.py,sha256=D5h2HYdlTo6yYZNq-O-PjaS9GeiZHxxVaOxDdh7fwjw,2957
204
- phoenix/server/api/mutations/user_mutations.py,sha256=5pgtNKZwOnP1pbuegnNMwPn5u4teeWJ6vZSIcjDSCUg,14055
204
+ phoenix/server/api/mutations/user_mutations.py,sha256=7CSTuUENIfKkdFhwLguqPG28h3zO5KrhMhfQqSCjNIg,14164
205
205
  phoenix/server/api/openapi/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
206
206
  phoenix/server/api/openapi/main.py,sha256=yKdzJYI4cxy_1mFcK4_7YObIcuRviBIfwNjB23RG14k,461
207
207
  phoenix/server/api/openapi/schema.py,sha256=WGmHWSIyJhtc5EIh_M3vlXU-EgHkFuTlyVofgS0kj1I,529
@@ -305,6 +305,8 @@ phoenix/server/email/types.py,sha256=IO2bTtCh-1cve-xiM4MWnunCCVNOQ3Z2cqTqF7vH-do
305
305
  phoenix/server/email/templates/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
306
306
  phoenix/server/email/templates/password_reset.html,sha256=jv0Pe-06JloPZcubRWxPdAFHYEn9eDj_4SjmuoIwshI,441
307
307
  phoenix/server/email/templates/welcome.html,sha256=AyVsIOtpmyYwWmmkXjuEgXwkbsag4YHHKfkmOTiNo-M,316
308
+ phoenix/server/middleware/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
309
+ phoenix/server/middleware/gzip.py,sha256=N-igp8kO6QoATEa2w9n0BdxkwkB3ZLqwgnjcA-7qua0,1396
308
310
  phoenix/server/openapi/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
309
311
  phoenix/server/static/apple-touch-icon-114x114.png,sha256=xtFVXAYQnJkpUApg2D1hltSTuyO4Is4sD4A0ZkikiVU,9486
310
312
  phoenix/server/static/apple-touch-icon-120x120.png,sha256=iqZVAk634BbjJMozA8aHYyw15JjhIlIrG41FA2DFFaE,9957
@@ -316,16 +318,16 @@ phoenix/server/static/apple-touch-icon-76x76.png,sha256=CT_xT12I0u2i0WU8JzBZBuOQ
316
318
  phoenix/server/static/apple-touch-icon.png,sha256=fOfpjqGpWYbJ0eAurKsyoZP1EAs6ZVooBJ_SGk2ZkDs,3801
317
319
  phoenix/server/static/favicon.ico,sha256=bY0vvCKRftemZfPShwZtE93DiiQdaYaozkPGwNFr6H8,34494
318
320
  phoenix/server/static/modernizr.js,sha256=mvK-XtkNqjOral-QvzoqsyOMECXIMu5BQwSVN_wcU9c,2564
319
- phoenix/server/static/.vite/manifest.json,sha256=sE9Qo2ZhJ-1E7Hq5qRAUh6RJ5-gsaKgfSw0on-FTxKk,2165
320
- phoenix/server/static/assets/components-B5CAbHpr.js,sha256=6HSyPEbZMgpSX6AS-_5GeHljISBieEpf_pQWO9iZD-o,456228
321
- phoenix/server/static/assets/index-DIP5WhNE.js,sha256=abTUAQ-m29l7y5iitSlPD-rlP_BWAkbWl2ZlasrYcuQ,60460
322
- phoenix/server/static/assets/pages-cfOsoZi6.js,sha256=d5WiYECyTU9hfDyLnFhM5_SfXF7Tb5q-dUPLscrBuuw,864853
321
+ phoenix/server/static/.vite/manifest.json,sha256=3tdR6HqSOYUbt4gNa32x15VC8Xe1gLSUH4j8mAwwM3s,2165
322
+ phoenix/server/static/assets/components-BpgLJxZt.js,sha256=RpCwrVhoEisHa-Ow4Y61aaFluNF57mZ7vk6ndwcyvjQ,455968
323
+ phoenix/server/static/assets/index-DHuvzpC2.js,sha256=hoz3wcgcd8OYHpTlEObulqm25WvZUl-jGsBMVcQIFxA,60460
324
+ phoenix/server/static/assets/pages-CNkfmPS4.js,sha256=C9xC6ue9HPa7SKrhFR0ixZG4UlAAlvb9ysba3TJ58Y0,864773
325
+ phoenix/server/static/assets/vendor-C77BEnnR.js,sha256=HXts0jM6W95ukwujVDLkd-PH0j15JChjVdQ2XcVEdJs,2510650
323
326
  phoenix/server/static/assets/vendor-Cg6lcjUC.css,sha256=nZrkr0u6NNElFGvpWHk9GTHeGoibCXCli1bE7mXZGZg,1816
324
- phoenix/server/static/assets/vendor-DCvpCpca.js,sha256=8Snf_3RF5d8AxOBi-kGMeDNPf8prJ8VWOhd4oU0nGBo,2509995
325
- phoenix/server/static/assets/vendor-arizeai-Ce3Kd6MM.js,sha256=WzCM-aYW4CaJeIyMBIklvRMUmK2Q7s0uPEuREvDjv10,193248
326
- phoenix/server/static/assets/vendor-codemirror-CoZ2wzq8.js,sha256=hq3lk1J62vpLjaHAL3XRZTbkFcX3AxUgpXDo9nVYe3M,781264
327
- phoenix/server/static/assets/vendor-recharts-Bv0CPtHC.js,sha256=F4Ydc5zEhNsvutA3zczt0Um0BD8R6hqePl_BY3qlRbw,282109
328
- phoenix/server/static/assets/vendor-shiki-CkOPKXne.js,sha256=ExRd8OKRnvIMlflZge41ha5B9bKa_K3SOc8-Uj2Eb90,8980312
327
+ phoenix/server/static/assets/vendor-arizeai-CMLBpPBs.js,sha256=u15ZUksgnu0bjS7O26zLvas3Er8vu9n0JQWlR9TRQJk,193248
328
+ phoenix/server/static/assets/vendor-codemirror-DT1ReytN.js,sha256=T-wL0C0T_hNpcxVs5bTASnvDwGlOLUYDhyEAYu8bnoE,781264
329
+ phoenix/server/static/assets/vendor-recharts-ByEcbiML.js,sha256=MAqybYIhy5fjWkbWluUC_QxW94Sge_lPn2HHYJUpGQI,282109
330
+ phoenix/server/static/assets/vendor-shiki-DEgpVt4G.js,sha256=n-4TW0jBUV1izQqrnpY2XVohK4zrtGRuSIQJX9jEi10,8980312
329
331
  phoenix/server/static/assets/vendor-three-C5WAXd5r.js,sha256=ELkg06u70N7h8oFmvqdoHyPuUf9VgGEWeT4LKFx4VWo,620975
330
332
  phoenix/server/templates/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
331
333
  phoenix/server/templates/index.html,sha256=e8_jdi7Eo19SK7DI_gglkTW094D17E0VAegoMmmmvIc,4330
@@ -333,7 +335,7 @@ phoenix/session/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
333
335
  phoenix/session/client.py,sha256=nXSn2Zmf9wTxgSe11Y9kKSLClkG8pNEAJgfEmy4mPm8,35234
334
336
  phoenix/session/data_extractor.py,sha256=Y0RzYFaNy9fQj8PEIeQ76TBZ90_E1FW7bXu3K5x0EZY,2782
335
337
  phoenix/session/evaluation.py,sha256=Q3fOMNELvqkk-b6a6PKc8pDJdsNQ0ZbTpseUSA2NKqs,5300
336
- phoenix/session/session.py,sha256=paP01LC8g3_ABbiQRbqSaIcXaUa7I0WpbcLf-IeR3-k,28199
338
+ phoenix/session/session.py,sha256=twE8tld8knShmTpZp6R80CUt2jau3RmfdfZAQCLSTKU,27621
337
339
  phoenix/trace/__init__.py,sha256=ujk_uYjM8gmm-YqnyXxF-kekfwid0bcaPMTtNNcaw6U,407
338
340
  phoenix/trace/attributes.py,sha256=hyEKYZWPCP4NRmW7VmiC2voa3TH7FYKUBR9DYiVfXlw,12627
339
341
  phoenix/trace/errors.py,sha256=wB1z8qdPckngdfU-TORToekvg3344oNFAA83_hC2yFY,180
@@ -366,9 +368,9 @@ phoenix/utilities/project.py,sha256=auVpARXkDb-JgeX5f2aStyFIkeKvGwN9l7qrFeJMVxI,
366
368
  phoenix/utilities/re.py,sha256=6YyUWIkv0zc2SigsxfOWIHzdpjKA_TZo2iqKq7zJKvw,2081
367
369
  phoenix/utilities/span_store.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
368
370
  phoenix/utilities/template_formatters.py,sha256=gh9PJD6WEGw7TEYXfSst1UR4pWWwmjxMLrDVQ_CkpkQ,2779
369
- arize_phoenix-8.26.0.dist-info/METADATA,sha256=gZ8LxB1KtJL2NK_NslQ8Y48U_Gl84BDQxKBX46Is0uU,24495
370
- arize_phoenix-8.26.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
371
- arize_phoenix-8.26.0.dist-info/entry_points.txt,sha256=Pgpn8Upxx9P8z8joPXZWl2LlnAlGc3gcQoVchb06X1Q,94
372
- arize_phoenix-8.26.0.dist-info/licenses/IP_NOTICE,sha256=JBqyyCYYxGDfzQ0TtsQgjts41IJoa-hiwDrBjCb9gHM,469
373
- arize_phoenix-8.26.0.dist-info/licenses/LICENSE,sha256=HFkW9REuMOkvKRACuwLPT0hRydHb3zNg-fdFt94td18,3794
374
- arize_phoenix-8.26.0.dist-info/RECORD,,
371
+ arize_phoenix-8.26.2.dist-info/METADATA,sha256=bVxxsuDo1dMIq6m3Sevhc6YbKfCS4NYcqDWEDtTose0,24469
372
+ arize_phoenix-8.26.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
373
+ arize_phoenix-8.26.2.dist-info/entry_points.txt,sha256=Pgpn8Upxx9P8z8joPXZWl2LlnAlGc3gcQoVchb06X1Q,94
374
+ arize_phoenix-8.26.2.dist-info/licenses/IP_NOTICE,sha256=JBqyyCYYxGDfzQ0TtsQgjts41IJoa-hiwDrBjCb9gHM,469
375
+ arize_phoenix-8.26.2.dist-info/licenses/LICENSE,sha256=HFkW9REuMOkvKRACuwLPT0hRydHb3zNg-fdFt94td18,3794
376
+ arize_phoenix-8.26.2.dist-info/RECORD,,
phoenix/config.py CHANGED
@@ -119,10 +119,6 @@ ENV_LOG_MIGRATIONS = "PHOENIX_LOG_MIGRATIONS"
119
119
  """
120
120
  Whether or not to log migrations. Defaults to true.
121
121
  """
122
- ENV_PHOENIX_ENABLE_WEBSOCKETS = "PHOENIX_ENABLE_WEBSOCKETS"
123
- """
124
- Whether or not to enable websockets. Defaults to None.
125
- """
126
122
 
127
123
  ENV_PHOENIX_DANGEROUSLY_DISABLE_MIGRATIONS = "PHOENIX_DANGEROUSLY_DISABLE_MIGRATIONS"
128
124
  """
@@ -574,10 +570,6 @@ def get_env_smtp_validate_certs() -> bool:
574
570
  return _bool_val(ENV_PHOENIX_SMTP_VALIDATE_CERTS, True)
575
571
 
576
572
 
577
- def get_env_enable_websockets() -> Optional[bool]:
578
- return _bool_val(ENV_PHOENIX_ENABLE_WEBSOCKETS)
579
-
580
-
581
573
  @dataclass(frozen=True)
582
574
  class OAuth2ClientConfig:
583
575
  idp_name: str
@@ -1145,6 +1137,13 @@ def verify_server_environment_variables() -> None:
1145
1137
  get_env_phoenix_secret()
1146
1138
  get_env_phoenix_admin_secret()
1147
1139
 
1140
+ # Notify users about deprecated environment variables if they are being used.
1141
+ if os.getenv("PHOENIX_ENABLE_WEBSOCKETS") is not None:
1142
+ logger.warning(
1143
+ "The environment variable PHOENIX_ENABLE_WEBSOCKETS is deprecated "
1144
+ "because WebSocket is no longer necessary."
1145
+ )
1146
+
1148
1147
 
1149
1148
  SKLEARN_VERSION = cast(tuple[int, int], tuple(map(int, version("scikit-learn").split(".", 2)[:2])))
1150
1149
  PLAYGROUND_PROJECT_NAME = "playground"
@@ -143,6 +143,8 @@ class UserMutationMixin:
143
143
  if input.new_role:
144
144
  if user.email == DEFAULT_ADMIN_EMAIL:
145
145
  raise Unauthorized("Cannot modify role for the default admin user")
146
+ if user_id == requester_id:
147
+ raise Unauthorized("Cannot modify own role")
146
148
  user_role_id = await session.scalar(_select_role_id_by_name(input.new_role.value))
147
149
  if user_role_id is None:
148
150
  raise NotFound(f"Role {input.new_role.value} not found")
phoenix/server/app.py CHANGED
@@ -25,23 +25,21 @@ from urllib.parse import urlparse
25
25
  import strawberry
26
26
  from fastapi import APIRouter, Depends, FastAPI
27
27
  from fastapi.middleware.cors import CORSMiddleware
28
- from fastapi.middleware.gzip import GZipMiddleware
29
28
  from fastapi.utils import is_body_allowed_for_status_code
30
29
  from grpc.aio import ServerInterceptor
31
30
  from sqlalchemy import select
32
31
  from sqlalchemy.ext.asyncio import AsyncEngine, AsyncSession, async_sessionmaker
33
32
  from starlette.datastructures import State as StarletteState
34
- from starlette.exceptions import HTTPException, WebSocketException
33
+ from starlette.exceptions import HTTPException
35
34
  from starlette.middleware import Middleware
36
35
  from starlette.middleware.authentication import AuthenticationMiddleware
37
36
  from starlette.middleware.base import BaseHTTPMiddleware, RequestResponseEndpoint
38
37
  from starlette.requests import Request
39
- from starlette.responses import JSONResponse, PlainTextResponse, Response
38
+ from starlette.responses import PlainTextResponse, Response
40
39
  from starlette.staticfiles import StaticFiles
41
40
  from starlette.status import HTTP_401_UNAUTHORIZED
42
41
  from starlette.templating import Jinja2Templates
43
42
  from starlette.types import Scope, StatefulLifespan
44
- from starlette.websockets import WebSocket
45
43
  from strawberry.extensions import SchemaExtension
46
44
  from strawberry.fastapi import GraphQLRouter
47
45
  from strawberry.subscriptions import GRAPHQL_TRANSPORT_WS_PROTOCOL
@@ -123,6 +121,7 @@ from phoenix.server.dml_event_handler import DmlEventHandler
123
121
  from phoenix.server.email.types import EmailSender
124
122
  from phoenix.server.grpc_server import GrpcServer
125
123
  from phoenix.server.jwt_store import JwtStore
124
+ from phoenix.server.middleware.gzip import GZipMiddleware
126
125
  from phoenix.server.oauth2 import OAuth2Clients
127
126
  from phoenix.server.telemetry import initialize_opentelemetry_tracer_provider
128
127
  from phoenix.server.types import (
@@ -207,7 +206,6 @@ class AppConfig(NamedTuple):
207
206
  web_manifest_path: Path
208
207
  authentication_enabled: bool
209
208
  """ Whether authentication is enabled """
210
- websockets_enabled: bool
211
209
  oauth2_idps: Sequence[OAuth2Idp]
212
210
 
213
211
 
@@ -258,7 +256,6 @@ class Static(StaticFiles):
258
256
  "manifest": self._web_manifest,
259
257
  "authentication_enabled": self._app_config.authentication_enabled,
260
258
  "oauth2_idps": self._app_config.oauth2_idps,
261
- "websockets_enabled": self._app_config.websockets_enabled,
262
259
  },
263
260
  )
264
261
  except Exception as e:
@@ -723,36 +720,12 @@ async def plain_text_http_exception_handler(request: Request, exc: HTTPException
723
720
  return PlainTextResponse(str(exc.detail), status_code=exc.status_code, headers=headers)
724
721
 
725
722
 
726
- async def websocket_denial_response_handler(websocket: WebSocket, exc: WebSocketException) -> None:
727
- """
728
- Overrides the default exception handler for WebSocketException to ensure
729
- that the HTTP response returned when a WebSocket connection is denied has
730
- the same status code as the raised exception. This is in keeping with the
731
- WebSocket Denial Response Extension of the ASGI specificiation described
732
- below.
733
-
734
- "Websocket connections start with the client sending a HTTP request
735
- containing the appropriate upgrade headers. On receipt of this request a
736
- server can choose to either upgrade the connection or respond with an HTTP
737
- response (denying the upgrade). The core ASGI specification does not allow
738
- for any control over the denial response, instead specifying that the HTTP
739
- status code 403 should be returned, whereas this extension allows an ASGI
740
- framework to control the denial response."
741
-
742
- For details, see:
743
- - https://asgi.readthedocs.io/en/latest/extensions.html#websocket-denial-response
744
- """
745
- assert isinstance(exc, WebSocketException)
746
- await websocket.send_denial_response(JSONResponse(status_code=exc.code, content=exc.reason))
747
-
748
-
749
723
  def create_app(
750
724
  db: DbSessionFactory,
751
725
  export_path: Path,
752
726
  model: Model,
753
727
  authentication_enabled: bool,
754
728
  umap_params: UMAPParameters,
755
- enable_websockets: bool,
756
729
  corpus: Optional[Model] = None,
757
730
  debug: bool = False,
758
731
  dev: bool = False,
@@ -900,7 +873,6 @@ def create_app(
900
873
  middleware=middlewares,
901
874
  exception_handlers={
902
875
  HTTPException: plain_text_http_exception_handler,
903
- WebSocketException: websocket_denial_response_handler, # type: ignore[dict-item]
904
876
  },
905
877
  debug=debug,
906
878
  swagger_ui_parameters={
@@ -935,7 +907,6 @@ def create_app(
935
907
  authentication_enabled=authentication_enabled,
936
908
  web_manifest_path=web_manifest_path,
937
909
  oauth2_idps=oauth2_idps,
938
- websockets_enabled=enable_websockets,
939
910
  ),
940
911
  ),
941
912
  name="static",
phoenix/server/main.py CHANGED
@@ -23,7 +23,6 @@ from phoenix.config import (
23
23
  get_env_db_logging_level,
24
24
  get_env_disable_migrations,
25
25
  get_env_enable_prometheus,
26
- get_env_enable_websockets,
27
26
  get_env_grpc_port,
28
27
  get_env_host,
29
28
  get_env_host_root_path,
@@ -355,13 +354,6 @@ def main() -> None:
355
354
  None if corpus_inferences is None else create_model_from_inferences(corpus_inferences)
356
355
  )
357
356
 
358
- # Get enable_websockets from environment variable or command line argument
359
- enable_websockets = get_env_enable_websockets()
360
- if args.enable_websockets is not None:
361
- enable_websockets = args.enable_websockets.lower() == "true"
362
- if enable_websockets is None:
363
- enable_websockets = True
364
-
365
357
  allowed_origins = get_env_allowed_origins()
366
358
 
367
359
  # Print information about the server
@@ -374,7 +366,6 @@ def main() -> None:
374
366
  storage=get_printable_db_url(db_connection_str),
375
367
  schema=get_env_database_schema(),
376
368
  auth_enabled=authentication_enabled,
377
- websockets_enabled=enable_websockets,
378
369
  allowed_origins=allowed_origins,
379
370
  )
380
371
  if sys.platform.startswith("win"):
@@ -405,7 +396,6 @@ def main() -> None:
405
396
  db=factory,
406
397
  export_path=export_path,
407
398
  model=model,
408
- enable_websockets=enable_websockets,
409
399
  authentication_enabled=authentication_enabled,
410
400
  umap_params=umap_params,
411
401
  corpus=corpus_model,
File without changes
@@ -0,0 +1,33 @@
1
+ from starlette.datastructures import Headers
2
+ from starlette.middleware.gzip import GZipMiddleware as _GZipMiddleware
3
+ from starlette.middleware.gzip import GZipResponder, IdentityResponder
4
+ from starlette.types import ASGIApp, Receive, Scope, Send
5
+
6
+
7
+ class GZipMiddleware(_GZipMiddleware):
8
+ """
9
+ Subclass of Starlette's GZipMiddleware that excludes multipart/mixed responses from compression.
10
+
11
+ This middleware adds a check to exclude multipart/mixed content types from compression,
12
+ which is important for streaming responses where compression could interfere with delivery.
13
+
14
+ The middleware will use the IdentityResponder (no compression) when:
15
+ 1. The client doesn't support gzip compression, or
16
+ 2. The response is a multipart/mixed content type
17
+ """
18
+
19
+ async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:
20
+ if scope["type"] != "http":
21
+ await self.app(scope, receive, send)
22
+ return
23
+
24
+ headers = Headers(scope=scope)
25
+ responder: ASGIApp
26
+ if "gzip" not in headers.get("Accept-Encoding", "") or "multipart/mixed" in headers.get(
27
+ "Accept", ""
28
+ ):
29
+ responder = IdentityResponder(self.app, self.minimum_size)
30
+ else:
31
+ responder = GZipResponder(self.app, self.minimum_size, compresslevel=self.compresslevel)
32
+
33
+ await responder(scope, receive, send)
@@ -1,32 +1,28 @@
1
1
  {
2
- "_components-B5CAbHpr.js": {
3
- "file": "assets/components-B5CAbHpr.js",
2
+ "_components-BpgLJxZt.js": {
3
+ "file": "assets/components-BpgLJxZt.js",
4
4
  "name": "components",
5
5
  "imports": [
6
- "_vendor-DCvpCpca.js",
7
- "_pages-cfOsoZi6.js",
8
- "_vendor-arizeai-Ce3Kd6MM.js",
9
- "_vendor-codemirror-CoZ2wzq8.js",
6
+ "_vendor-C77BEnnR.js",
7
+ "_pages-CNkfmPS4.js",
8
+ "_vendor-arizeai-CMLBpPBs.js",
9
+ "_vendor-codemirror-DT1ReytN.js",
10
10
  "_vendor-three-C5WAXd5r.js"
11
11
  ]
12
12
  },
13
- "_pages-cfOsoZi6.js": {
14
- "file": "assets/pages-cfOsoZi6.js",
13
+ "_pages-CNkfmPS4.js": {
14
+ "file": "assets/pages-CNkfmPS4.js",
15
15
  "name": "pages",
16
16
  "imports": [
17
- "_vendor-DCvpCpca.js",
18
- "_vendor-arizeai-Ce3Kd6MM.js",
19
- "_components-B5CAbHpr.js",
20
- "_vendor-codemirror-CoZ2wzq8.js",
21
- "_vendor-recharts-Bv0CPtHC.js"
17
+ "_vendor-C77BEnnR.js",
18
+ "_vendor-arizeai-CMLBpPBs.js",
19
+ "_components-BpgLJxZt.js",
20
+ "_vendor-codemirror-DT1ReytN.js",
21
+ "_vendor-recharts-ByEcbiML.js"
22
22
  ]
23
23
  },
24
- "_vendor-Cg6lcjUC.css": {
25
- "file": "assets/vendor-Cg6lcjUC.css",
26
- "src": "_vendor-Cg6lcjUC.css"
27
- },
28
- "_vendor-DCvpCpca.js": {
29
- "file": "assets/vendor-DCvpCpca.js",
24
+ "_vendor-C77BEnnR.js": {
25
+ "file": "assets/vendor-C77BEnnR.js",
30
26
  "name": "vendor",
31
27
  "imports": [
32
28
  "_vendor-three-C5WAXd5r.js"
@@ -35,33 +31,37 @@
35
31
  "assets/vendor-Cg6lcjUC.css"
36
32
  ]
37
33
  },
38
- "_vendor-arizeai-Ce3Kd6MM.js": {
39
- "file": "assets/vendor-arizeai-Ce3Kd6MM.js",
34
+ "_vendor-Cg6lcjUC.css": {
35
+ "file": "assets/vendor-Cg6lcjUC.css",
36
+ "src": "_vendor-Cg6lcjUC.css"
37
+ },
38
+ "_vendor-arizeai-CMLBpPBs.js": {
39
+ "file": "assets/vendor-arizeai-CMLBpPBs.js",
40
40
  "name": "vendor-arizeai",
41
41
  "imports": [
42
- "_vendor-DCvpCpca.js"
42
+ "_vendor-C77BEnnR.js"
43
43
  ]
44
44
  },
45
- "_vendor-codemirror-CoZ2wzq8.js": {
46
- "file": "assets/vendor-codemirror-CoZ2wzq8.js",
45
+ "_vendor-codemirror-DT1ReytN.js": {
46
+ "file": "assets/vendor-codemirror-DT1ReytN.js",
47
47
  "name": "vendor-codemirror",
48
48
  "imports": [
49
- "_vendor-DCvpCpca.js",
50
- "_vendor-shiki-CkOPKXne.js"
49
+ "_vendor-C77BEnnR.js",
50
+ "_vendor-shiki-DEgpVt4G.js"
51
51
  ]
52
52
  },
53
- "_vendor-recharts-Bv0CPtHC.js": {
54
- "file": "assets/vendor-recharts-Bv0CPtHC.js",
53
+ "_vendor-recharts-ByEcbiML.js": {
54
+ "file": "assets/vendor-recharts-ByEcbiML.js",
55
55
  "name": "vendor-recharts",
56
56
  "imports": [
57
- "_vendor-DCvpCpca.js"
57
+ "_vendor-C77BEnnR.js"
58
58
  ]
59
59
  },
60
- "_vendor-shiki-CkOPKXne.js": {
61
- "file": "assets/vendor-shiki-CkOPKXne.js",
60
+ "_vendor-shiki-DEgpVt4G.js": {
61
+ "file": "assets/vendor-shiki-DEgpVt4G.js",
62
62
  "name": "vendor-shiki",
63
63
  "imports": [
64
- "_vendor-DCvpCpca.js"
64
+ "_vendor-C77BEnnR.js"
65
65
  ]
66
66
  },
67
67
  "_vendor-three-C5WAXd5r.js": {
@@ -69,19 +69,19 @@
69
69
  "name": "vendor-three"
70
70
  },
71
71
  "index.tsx": {
72
- "file": "assets/index-DIP5WhNE.js",
72
+ "file": "assets/index-DHuvzpC2.js",
73
73
  "name": "index",
74
74
  "src": "index.tsx",
75
75
  "isEntry": true,
76
76
  "imports": [
77
- "_vendor-DCvpCpca.js",
78
- "_vendor-arizeai-Ce3Kd6MM.js",
79
- "_pages-cfOsoZi6.js",
80
- "_components-B5CAbHpr.js",
77
+ "_vendor-C77BEnnR.js",
78
+ "_vendor-arizeai-CMLBpPBs.js",
79
+ "_pages-CNkfmPS4.js",
80
+ "_components-BpgLJxZt.js",
81
81
  "_vendor-three-C5WAXd5r.js",
82
- "_vendor-codemirror-CoZ2wzq8.js",
83
- "_vendor-shiki-CkOPKXne.js",
84
- "_vendor-recharts-Bv0CPtHC.js"
82
+ "_vendor-codemirror-DT1ReytN.js",
83
+ "_vendor-shiki-DEgpVt4G.js",
84
+ "_vendor-recharts-ByEcbiML.js"
85
85
  ]
86
86
  }
87
87
  }