arize-phoenix 9.6.1__tar.gz → 10.0.0__tar.gz

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

Potentially problematic release.


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

Files changed (406) hide show
  1. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/PKG-INFO +1 -1
  2. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/auth.py +6 -4
  3. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/config.py +150 -25
  4. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/db/enums.py +1 -2
  5. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/db/facilitator.py +20 -11
  6. arize_phoenix-10.0.0/src/phoenix/db/migrations/versions/6a88424799fe_update_users_with_auth_method.py +179 -0
  7. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/db/models.py +66 -37
  8. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/context.py +5 -4
  9. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/mutations/user_mutations.py +58 -26
  10. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/routers/auth.py +16 -4
  11. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/routers/oauth2.py +196 -15
  12. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/app.py +36 -10
  13. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/bearer_auth.py +5 -7
  14. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/jwt_store.py +5 -4
  15. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/main.py +11 -4
  16. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/oauth2.py +47 -3
  17. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/static/.vite/manifest.json +9 -9
  18. arize_phoenix-9.6.1/src/phoenix/server/static/assets/components-CDvTuTqd.js → arize_phoenix-10.0.0/src/phoenix/server/static/assets/components-CjGpmneV.js +192 -184
  19. arize_phoenix-9.6.1/src/phoenix/server/static/assets/index-DpcxdHu4.js → arize_phoenix-10.0.0/src/phoenix/server/static/assets/index-C57g4e_o.js +11 -11
  20. arize_phoenix-9.6.1/src/phoenix/server/static/assets/pages-Bcs41-Zv.js → arize_phoenix-10.0.0/src/phoenix/server/static/assets/pages-fQ2s7TFY.js +343 -337
  21. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/templates/index.html +1 -0
  22. arize_phoenix-10.0.0/src/phoenix/version.py +1 -0
  23. arize_phoenix-9.6.1/src/phoenix/version.py +0 -1
  24. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/.gitignore +0 -0
  25. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/IP_NOTICE +0 -0
  26. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/LICENSE +0 -0
  27. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/README.md +0 -0
  28. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/pyproject.toml +0 -0
  29. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/__init__.py +0 -0
  30. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/core/__init__.py +0 -0
  31. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/core/embedding_dimension.py +0 -0
  32. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/core/model.py +0 -0
  33. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/core/model_schema.py +0 -0
  34. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/core/model_schema_adapter.py +0 -0
  35. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/datetime_utils.py +0 -0
  36. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/db/README.md +0 -0
  37. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/db/__init__.py +0 -0
  38. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/db/alembic.ini +0 -0
  39. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/db/bulk_inserter.py +0 -0
  40. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/db/constants.py +0 -0
  41. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/db/engines.py +0 -0
  42. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/db/helpers.py +0 -0
  43. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/db/insertion/__init__.py +0 -0
  44. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/db/insertion/constants.py +0 -0
  45. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/db/insertion/dataset.py +0 -0
  46. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/db/insertion/document_annotation.py +0 -0
  47. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/db/insertion/evaluation.py +0 -0
  48. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/db/insertion/helpers.py +0 -0
  49. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/db/insertion/span.py +0 -0
  50. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/db/insertion/span_annotation.py +0 -0
  51. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/db/insertion/trace_annotation.py +0 -0
  52. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/db/insertion/types.py +0 -0
  53. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/db/migrate.py +0 -0
  54. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/db/migrations/__init__.py +0 -0
  55. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/db/migrations/data_migration_scripts/__init__.py +0 -0
  56. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/db/migrations/data_migration_scripts/populate_project_sessions.py +0 -0
  57. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/db/migrations/env.py +0 -0
  58. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/db/migrations/script.py.mako +0 -0
  59. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/db/migrations/versions/10460e46d750_datasets.py +0 -0
  60. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/db/migrations/versions/2f9d1a65945f_annotation_config_migration.py +0 -0
  61. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/db/migrations/versions/3be8647b87d8_add_token_columns_to_spans_table.py +0 -0
  62. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/db/migrations/versions/4ded9e43755f_create_project_sessions_table.py +0 -0
  63. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/db/migrations/versions/8a3764fe7f1a_change_jsonb_to_json_for_prompts.py +0 -0
  64. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/db/migrations/versions/bb8139330879_create_project_trace_retention_policies_table.py +0 -0
  65. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/db/migrations/versions/bc8fea3c2bc8_add_prompt_tables.py +0 -0
  66. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/db/migrations/versions/cd164e83824f_users_and_tokens.py +0 -0
  67. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/db/migrations/versions/cf03bd6bae1d_init.py +0 -0
  68. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/db/pg_config.py +0 -0
  69. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/db/types/__init__.py +0 -0
  70. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/db/types/annotation_configs.py +0 -0
  71. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/db/types/db_models.py +0 -0
  72. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/db/types/identifier.py +0 -0
  73. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/db/types/model_provider.py +0 -0
  74. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/db/types/trace_retention.py +0 -0
  75. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/exceptions.py +0 -0
  76. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/experiments/__init__.py +0 -0
  77. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/experiments/evaluators/__init__.py +0 -0
  78. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/experiments/evaluators/base.py +0 -0
  79. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/experiments/evaluators/code_evaluators.py +0 -0
  80. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/experiments/evaluators/llm_evaluators.py +0 -0
  81. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/experiments/evaluators/utils.py +0 -0
  82. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/experiments/functions.py +0 -0
  83. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/experiments/tracing.py +0 -0
  84. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/experiments/types.py +0 -0
  85. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/experiments/utils.py +0 -0
  86. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/inferences/__init__.py +0 -0
  87. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/inferences/errors.py +0 -0
  88. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/inferences/fixtures.py +0 -0
  89. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/inferences/inferences.py +0 -0
  90. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/inferences/schema.py +0 -0
  91. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/inferences/validation.py +0 -0
  92. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/logging/__init__.py +0 -0
  93. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/logging/_config.py +0 -0
  94. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/logging/_filter.py +0 -0
  95. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/logging/_formatter.py +0 -0
  96. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/metrics/README.md +0 -0
  97. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/metrics/__init__.py +0 -0
  98. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/metrics/binning.py +0 -0
  99. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/metrics/metrics.py +0 -0
  100. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/metrics/mixins.py +0 -0
  101. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/metrics/retrieval_metrics.py +0 -0
  102. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/metrics/timeseries.py +0 -0
  103. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/metrics/wrappers.py +0 -0
  104. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/pointcloud/__init__.py +0 -0
  105. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/pointcloud/clustering.py +0 -0
  106. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/pointcloud/pointcloud.py +0 -0
  107. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/pointcloud/projectors.py +0 -0
  108. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/pointcloud/umap_parameters.py +0 -0
  109. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/py.typed +0 -0
  110. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/__init__.py +0 -0
  111. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/README.md +0 -0
  112. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/__init__.py +0 -0
  113. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/auth.py +0 -0
  114. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/dataloaders/__init__.py +0 -0
  115. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/dataloaders/annotation_summaries.py +0 -0
  116. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/dataloaders/average_experiment_run_latency.py +0 -0
  117. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/dataloaders/cache/__init__.py +0 -0
  118. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/dataloaders/cache/two_tier_cache.py +0 -0
  119. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/dataloaders/dataset_example_revisions.py +0 -0
  120. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/dataloaders/dataset_example_spans.py +0 -0
  121. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/dataloaders/document_evaluation_summaries.py +0 -0
  122. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/dataloaders/document_evaluations.py +0 -0
  123. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/dataloaders/document_retrieval_metrics.py +0 -0
  124. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/dataloaders/experiment_annotation_summaries.py +0 -0
  125. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/dataloaders/experiment_error_rates.py +0 -0
  126. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/dataloaders/experiment_run_annotations.py +0 -0
  127. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/dataloaders/experiment_run_counts.py +0 -0
  128. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/dataloaders/experiment_sequence_number.py +0 -0
  129. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/dataloaders/latency_ms_quantile.py +0 -0
  130. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/dataloaders/min_start_or_max_end_times.py +0 -0
  131. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/dataloaders/num_child_spans.py +0 -0
  132. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/dataloaders/num_spans_per_trace.py +0 -0
  133. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/dataloaders/project_by_name.py +0 -0
  134. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/dataloaders/project_ids_by_trace_retention_policy_id.py +0 -0
  135. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/dataloaders/prompt_version_sequence_number.py +0 -0
  136. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/dataloaders/record_counts.py +0 -0
  137. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/dataloaders/session_io.py +0 -0
  138. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/dataloaders/session_num_traces.py +0 -0
  139. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/dataloaders/session_num_traces_with_error.py +0 -0
  140. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/dataloaders/session_token_usages.py +0 -0
  141. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/dataloaders/session_trace_latency_ms_quantile.py +0 -0
  142. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/dataloaders/span_annotations.py +0 -0
  143. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/dataloaders/span_by_id.py +0 -0
  144. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/dataloaders/span_dataset_examples.py +0 -0
  145. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/dataloaders/span_descendants.py +0 -0
  146. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/dataloaders/span_projects.py +0 -0
  147. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/dataloaders/table_fields.py +0 -0
  148. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/dataloaders/token_counts.py +0 -0
  149. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/dataloaders/trace_by_trace_ids.py +0 -0
  150. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/dataloaders/trace_retention_policy_id_by_project_id.py +0 -0
  151. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/dataloaders/trace_root_spans.py +0 -0
  152. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/dataloaders/user_roles.py +0 -0
  153. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/dataloaders/users.py +0 -0
  154. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/exceptions.py +0 -0
  155. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/helpers/__init__.py +0 -0
  156. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/helpers/annotations.py +0 -0
  157. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/helpers/dataset_helpers.py +0 -0
  158. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/helpers/experiment_run_filters.py +0 -0
  159. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/helpers/playground_clients.py +0 -0
  160. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/helpers/playground_registry.py +0 -0
  161. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/helpers/playground_spans.py +0 -0
  162. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/helpers/prompts/__init__.py +0 -0
  163. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/helpers/prompts/conversions/__init__.py +0 -0
  164. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/helpers/prompts/conversions/anthropic.py +0 -0
  165. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/helpers/prompts/conversions/openai.py +0 -0
  166. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/helpers/prompts/models.py +0 -0
  167. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/input_types/AddExamplesToDatasetInput.py +0 -0
  168. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/input_types/AddSpansToDatasetInput.py +0 -0
  169. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/input_types/ChatCompletionInput.py +0 -0
  170. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/input_types/ChatCompletionMessageInput.py +0 -0
  171. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/input_types/ClearProjectInput.py +0 -0
  172. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/input_types/ClusterInput.py +0 -0
  173. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/input_types/Coordinates.py +0 -0
  174. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/input_types/CreateDatasetInput.py +0 -0
  175. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/input_types/CreateSpanAnnotationInput.py +0 -0
  176. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/input_types/CreateTraceAnnotationInput.py +0 -0
  177. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/input_types/DataQualityMetricInput.py +0 -0
  178. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/input_types/DatasetExampleInput.py +0 -0
  179. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/input_types/DatasetSort.py +0 -0
  180. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/input_types/DatasetVersionSort.py +0 -0
  181. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/input_types/DeleteAnnotationsInput.py +0 -0
  182. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/input_types/DeleteDatasetExamplesInput.py +0 -0
  183. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/input_types/DeleteDatasetInput.py +0 -0
  184. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/input_types/DeleteExperimentsInput.py +0 -0
  185. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/input_types/DimensionFilter.py +0 -0
  186. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/input_types/DimensionInput.py +0 -0
  187. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/input_types/GenerativeModelInput.py +0 -0
  188. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/input_types/Granularity.py +0 -0
  189. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/input_types/InvocationParameters.py +0 -0
  190. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/input_types/PatchAnnotationInput.py +0 -0
  191. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/input_types/PatchDatasetExamplesInput.py +0 -0
  192. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/input_types/PatchDatasetInput.py +0 -0
  193. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/input_types/PerformanceMetricInput.py +0 -0
  194. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/input_types/ProjectFilter.py +0 -0
  195. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/input_types/ProjectSessionSort.py +0 -0
  196. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/input_types/ProjectSort.py +0 -0
  197. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/input_types/PromptTemplateOptions.py +0 -0
  198. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/input_types/PromptVersionInput.py +0 -0
  199. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/input_types/SpanAnnotationFilter.py +0 -0
  200. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/input_types/SpanAnnotationSort.py +0 -0
  201. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/input_types/SpanSort.py +0 -0
  202. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/input_types/TimeRange.py +0 -0
  203. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/input_types/TraceAnnotationSort.py +0 -0
  204. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/input_types/UserRoleInput.py +0 -0
  205. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/input_types/__init__.py +0 -0
  206. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/interceptor.py +0 -0
  207. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/mutations/__init__.py +0 -0
  208. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/mutations/annotation_config_mutations.py +0 -0
  209. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/mutations/api_key_mutations.py +0 -0
  210. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/mutations/chat_mutations.py +0 -0
  211. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/mutations/dataset_mutations.py +0 -0
  212. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/mutations/experiment_mutations.py +0 -0
  213. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/mutations/export_events_mutations.py +0 -0
  214. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/mutations/project_mutations.py +0 -0
  215. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/mutations/project_trace_retention_policy_mutations.py +0 -0
  216. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/mutations/prompt_label_mutations.py +0 -0
  217. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/mutations/prompt_mutations.py +0 -0
  218. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/mutations/prompt_version_tag_mutations.py +0 -0
  219. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/mutations/span_annotations_mutations.py +0 -0
  220. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/mutations/trace_annotations_mutations.py +0 -0
  221. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/mutations/trace_mutations.py +0 -0
  222. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/openapi/__init__.py +0 -0
  223. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/openapi/main.py +0 -0
  224. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/openapi/schema.py +0 -0
  225. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/queries.py +0 -0
  226. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/routers/__init__.py +0 -0
  227. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/routers/embeddings.py +0 -0
  228. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/routers/utils.py +0 -0
  229. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/routers/v1/__init__.py +0 -0
  230. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/routers/v1/annotation_configs.py +0 -0
  231. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/routers/v1/annotations.py +0 -0
  232. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/routers/v1/datasets.py +0 -0
  233. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/routers/v1/evaluations.py +0 -0
  234. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/routers/v1/experiment_evaluations.py +0 -0
  235. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/routers/v1/experiment_runs.py +0 -0
  236. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/routers/v1/experiments.py +0 -0
  237. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/routers/v1/models.py +0 -0
  238. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/routers/v1/projects.py +0 -0
  239. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/routers/v1/prompts.py +0 -0
  240. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/routers/v1/spans.py +0 -0
  241. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/routers/v1/traces.py +0 -0
  242. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/routers/v1/utils.py +0 -0
  243. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/schema.py +0 -0
  244. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/subscriptions.py +0 -0
  245. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/types/Annotation.py +0 -0
  246. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/types/AnnotationConfig.py +0 -0
  247. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/types/AnnotationSource.py +0 -0
  248. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/types/AnnotationSummary.py +0 -0
  249. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/types/AnnotatorKind.py +0 -0
  250. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/types/ApiKey.py +0 -0
  251. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/types/AuthMethod.py +0 -0
  252. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/types/ChatCompletionMessageRole.py +0 -0
  253. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/types/ChatCompletionSubscriptionPayload.py +0 -0
  254. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/types/Cluster.py +0 -0
  255. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/types/CreateDatasetPayload.py +0 -0
  256. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/types/CronExpression.py +0 -0
  257. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/types/DataQualityMetric.py +0 -0
  258. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/types/Dataset.py +0 -0
  259. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/types/DatasetExample.py +0 -0
  260. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/types/DatasetExampleRevision.py +0 -0
  261. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/types/DatasetValues.py +0 -0
  262. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/types/DatasetVersion.py +0 -0
  263. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/types/Dimension.py +0 -0
  264. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/types/DimensionDataType.py +0 -0
  265. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/types/DimensionShape.py +0 -0
  266. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/types/DimensionType.py +0 -0
  267. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/types/DimensionWithValue.py +0 -0
  268. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/types/DocumentEvaluationSummary.py +0 -0
  269. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/types/DocumentRetrievalMetrics.py +0 -0
  270. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/types/EmbeddingDimension.py +0 -0
  271. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/types/EmbeddingMetadata.py +0 -0
  272. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/types/Evaluation.py +0 -0
  273. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/types/EvaluationSummary.py +0 -0
  274. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/types/Event.py +0 -0
  275. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/types/EventMetadata.py +0 -0
  276. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/types/ExampleRevisionInterface.py +0 -0
  277. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/types/Experiment.py +0 -0
  278. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/types/ExperimentAnnotationSummary.py +0 -0
  279. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/types/ExperimentComparison.py +0 -0
  280. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/types/ExperimentRun.py +0 -0
  281. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/types/ExperimentRunAnnotation.py +0 -0
  282. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/types/ExportedFile.py +0 -0
  283. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/types/Functionality.py +0 -0
  284. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/types/GenerativeModel.py +0 -0
  285. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/types/GenerativeProvider.py +0 -0
  286. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/types/Identifier.py +0 -0
  287. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/types/Inferences.py +0 -0
  288. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/types/InferencesRole.py +0 -0
  289. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/types/LabelFraction.py +0 -0
  290. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/types/MimeType.py +0 -0
  291. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/types/Model.py +0 -0
  292. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/types/NumericRange.py +0 -0
  293. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/types/PerformanceMetric.py +0 -0
  294. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/types/Project.py +0 -0
  295. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/types/ProjectSession.py +0 -0
  296. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/types/ProjectTraceRetentionPolicy.py +0 -0
  297. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/types/Prompt.py +0 -0
  298. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/types/PromptLabel.py +0 -0
  299. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/types/PromptResponse.py +0 -0
  300. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/types/PromptVersion.py +0 -0
  301. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/types/PromptVersionTag.py +0 -0
  302. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/types/PromptVersionTemplate.py +0 -0
  303. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/types/ResponseFormat.py +0 -0
  304. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/types/Retrieval.py +0 -0
  305. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/types/ScalarDriftMetricEnum.py +0 -0
  306. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/types/Segments.py +0 -0
  307. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/types/SortDir.py +0 -0
  308. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/types/Span.py +0 -0
  309. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/types/SpanAnnotation.py +0 -0
  310. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/types/SpanIOValue.py +0 -0
  311. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/types/SystemApiKey.py +0 -0
  312. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/types/TimeSeries.py +0 -0
  313. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/types/TokenCountPromptDetails.py +0 -0
  314. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/types/TokenUsage.py +0 -0
  315. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/types/ToolDefinition.py +0 -0
  316. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/types/Trace.py +0 -0
  317. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/types/TraceAnnotation.py +0 -0
  318. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/types/UMAPPoints.py +0 -0
  319. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/types/User.py +0 -0
  320. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/types/UserApiKey.py +0 -0
  321. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/types/UserRole.py +0 -0
  322. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/types/ValidationResult.py +0 -0
  323. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/types/VectorDriftMetricEnum.py +0 -0
  324. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/types/__init__.py +0 -0
  325. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/types/node.py +0 -0
  326. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/types/pagination.py +0 -0
  327. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/api/utils.py +0 -0
  328. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/authorization.py +0 -0
  329. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/cost_tracking/__init__.py +0 -0
  330. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/cost_tracking/cost_lookup.py +0 -0
  331. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/cost_tracking/model_cost_manifest.json +0 -0
  332. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/dml_event.py +0 -0
  333. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/dml_event_handler.py +0 -0
  334. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/email/__init__.py +0 -0
  335. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/email/sender.py +0 -0
  336. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/email/templates/__init__.py +0 -0
  337. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/email/templates/password_reset.html +0 -0
  338. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/email/templates/welcome.html +0 -0
  339. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/email/types.py +0 -0
  340. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/grpc_server.py +0 -0
  341. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/middleware/__init__.py +0 -0
  342. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/middleware/gzip.py +0 -0
  343. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/openapi/__init__.py +0 -0
  344. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/prometheus.py +0 -0
  345. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/rate_limiters.py +0 -0
  346. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/retention.py +0 -0
  347. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/static/apple-touch-icon-114x114.png +0 -0
  348. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/static/apple-touch-icon-120x120.png +0 -0
  349. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/static/apple-touch-icon-144x144.png +0 -0
  350. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/static/apple-touch-icon-152x152.png +0 -0
  351. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/static/apple-touch-icon-180x180.png +0 -0
  352. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/static/apple-touch-icon-72x72.png +0 -0
  353. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/static/apple-touch-icon-76x76.png +0 -0
  354. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/static/apple-touch-icon.png +0 -0
  355. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/static/assets/vendor-CToBXdDM.js +0 -0
  356. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/static/assets/vendor-WIZid84E.css +0 -0
  357. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/static/assets/vendor-arizeai-BhbMHqQs.js +0 -0
  358. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/static/assets/vendor-codemirror-CeLHFooz.js +0 -0
  359. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/static/assets/vendor-recharts-PlWJHgM9.js +0 -0
  360. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/static/assets/vendor-shiki-CPwL2jwA.js +0 -0
  361. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/static/assets/vendor-three-C5WAXd5r.js +0 -0
  362. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/static/favicon.ico +0 -0
  363. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/static/modernizr.js +0 -0
  364. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/telemetry.py +0 -0
  365. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/templates/__init__.py +0 -0
  366. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/thread_server.py +0 -0
  367. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/server/types.py +0 -0
  368. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/services.py +0 -0
  369. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/session/__init__.py +0 -0
  370. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/session/client.py +0 -0
  371. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/session/data_extractor.py +0 -0
  372. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/session/evaluation.py +0 -0
  373. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/session/session.py +0 -0
  374. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/settings.py +0 -0
  375. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/trace/__init__.py +0 -0
  376. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/trace/attributes.py +0 -0
  377. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/trace/dsl/README.md +0 -0
  378. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/trace/dsl/__init__.py +0 -0
  379. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/trace/dsl/filter.py +0 -0
  380. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/trace/dsl/helpers.py +0 -0
  381. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/trace/dsl/query.py +0 -0
  382. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/trace/errors.py +0 -0
  383. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/trace/evaluation_conventions.py +0 -0
  384. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/trace/exporter.py +0 -0
  385. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/trace/fixtures.py +0 -0
  386. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/trace/otel.py +0 -0
  387. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/trace/projects.py +0 -0
  388. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/trace/schemas.py +0 -0
  389. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/trace/span_evaluations.py +0 -0
  390. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/trace/span_json_decoder.py +0 -0
  391. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/trace/span_json_encoder.py +0 -0
  392. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/trace/trace_dataset.py +0 -0
  393. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/trace/utils.py +0 -0
  394. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/trace/v1/__init__.py +0 -0
  395. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/trace/v1/evaluation_pb2.py +0 -0
  396. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/trace/v1/evaluation_pb2.pyi +0 -0
  397. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/utilities/__init__.py +0 -0
  398. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/utilities/client.py +0 -0
  399. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/utilities/deprecation.py +0 -0
  400. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/utilities/error_handling.py +0 -0
  401. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/utilities/json.py +0 -0
  402. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/utilities/logging.py +0 -0
  403. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/utilities/project.py +0 -0
  404. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/utilities/re.py +0 -0
  405. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/utilities/span_store.py +0 -0
  406. {arize_phoenix-9.6.1 → arize_phoenix-10.0.0}/src/phoenix/utilities/template_formatters.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: arize-phoenix
3
- Version: 9.6.1
3
+ Version: 10.0.0
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
@@ -7,15 +7,16 @@ from enum import Enum, auto
7
7
  from hashlib import pbkdf2_hmac
8
8
  from typing import Any, Literal, Optional, Protocol
9
9
 
10
+ from starlette.datastructures import Secret
10
11
  from starlette.responses import Response
11
12
  from typing_extensions import TypeVar
12
13
 
13
- from phoenix.config import get_env_phoenix_use_secure_cookies
14
+ from phoenix.config import get_env_cookies_path, get_env_phoenix_use_secure_cookies
14
15
 
15
16
  ResponseType = TypeVar("ResponseType", bound=Response)
16
17
 
17
18
 
18
- def compute_password_hash(*, password: str, salt: bytes) -> bytes:
19
+ def compute_password_hash(*, password: Secret, salt: bytes) -> bytes:
19
20
  """
20
21
  Salts and hashes a password using PBKDF2, HMAC and SHA256.
21
22
 
@@ -26,11 +27,11 @@ def compute_password_hash(*, password: str, salt: bytes) -> bytes:
26
27
  bytes: the hashed password
27
28
  """
28
29
  assert salt
29
- password_bytes = password.encode("utf-8")
30
+ password_bytes = str(password).encode("utf-8")
30
31
  return pbkdf2_hmac("sha256", password_bytes, salt, NUM_ITERATIONS)
31
32
 
32
33
 
33
- def is_valid_password(*, password: str, salt: bytes, password_hash: bytes) -> bool:
34
+ def is_valid_password(*, password: Secret, salt: bytes, password_hash: bytes) -> bool:
34
35
  """
35
36
  Determines whether the password is valid by salting and hashing the password
36
37
  and comparing against the existing hash value.
@@ -131,6 +132,7 @@ def _set_cookie(
131
132
  httponly=True,
132
133
  samesite=samesite,
133
134
  max_age=int(cookie_max_age.total_seconds()),
135
+ path=get_env_cookies_path(),
134
136
  )
135
137
  return response
136
138
 
@@ -1,3 +1,5 @@
1
+ from __future__ import annotations
2
+
1
3
  import logging
2
4
  import os
3
5
  import re
@@ -7,16 +9,18 @@ from datetime import timedelta
7
9
  from enum import Enum
8
10
  from importlib.metadata import version
9
11
  from pathlib import Path
10
- from typing import Any, Optional, Union, cast, overload
12
+ from typing import TYPE_CHECKING, Any, NamedTuple, Optional, Union, cast, overload
11
13
  from urllib.parse import quote_plus, urljoin, urlparse
12
14
 
13
15
  import wrapt
14
16
  from email_validator import EmailNotValidError, validate_email
15
- from starlette.datastructures import URL
17
+ from starlette.datastructures import URL, Secret
16
18
 
17
19
  from phoenix.utilities.logging import log_a_list
20
+ from phoenix.utilities.re import parse_env_headers
18
21
 
19
- from .utilities.re import parse_env_headers
22
+ if TYPE_CHECKING:
23
+ from phoenix.server.oauth2 import OAuth2Clients
20
24
 
21
25
  logger = logging.getLogger(__name__)
22
26
 
@@ -138,6 +142,11 @@ ENV_PHOENIX_SERVER_INSTRUMENTATION_OTLP_TRACE_COLLECTOR_GRPC_ENDPOINT = (
138
142
 
139
143
  # Authentication settings
140
144
  ENV_PHOENIX_ENABLE_AUTH = "PHOENIX_ENABLE_AUTH"
145
+ ENV_PHOENIX_DISABLE_BASIC_AUTH = "PHOENIX_DISABLE_BASIC_AUTH"
146
+ """
147
+ Forbid login via password and disable the creation of local users, which log in via passwords.
148
+ This can be helpful in setups where authentication is handled entirely through OAUTH2.
149
+ """
141
150
  ENV_PHOENIX_DISABLE_RATE_LIMIT = "PHOENIX_DISABLE_RATE_LIMIT"
142
151
  ENV_PHOENIX_SECRET = "PHOENIX_SECRET"
143
152
  """
@@ -160,6 +169,7 @@ be updated manually in the application.
160
169
  """
161
170
  ENV_PHOENIX_API_KEY = "PHOENIX_API_KEY"
162
171
  ENV_PHOENIX_USE_SECURE_COOKIES = "PHOENIX_USE_SECURE_COOKIES"
172
+ ENV_PHOENIX_COOKIES_PATH = "PHOENIX_COOKIES_PATH"
163
173
  ENV_PHOENIX_ACCESS_TOKEN_EXPIRY_MINUTES = "PHOENIX_ACCESS_TOKEN_EXPIRY_MINUTES"
164
174
  """
165
175
  The duration, in minutes, before access tokens expire.
@@ -555,7 +565,7 @@ def _bool_val(env_var: str, default: Optional[bool] = None) -> Optional[bool]:
555
565
  assert (lower := value.lower()) in (
556
566
  "true",
557
567
  "false",
558
- ), f"{env_var} must be set to TRUE or FALSE (case-insensitive)"
568
+ ), f"{env_var} must be set to TRUE or FALSE (case-insensitive). Got: {value}"
559
569
  return lower == "true"
560
570
 
561
571
 
@@ -573,8 +583,7 @@ def _float_val(env_var: str, default: Optional[float] = None) -> Optional[float]
573
583
  return float(value)
574
584
  except ValueError:
575
585
  raise ValueError(
576
- f"Invalid value for environment variable {env_var}: {value}. "
577
- f"Value must be a number."
586
+ f"Invalid value for environment variable {env_var}: {value}. Value must be a number."
578
587
  )
579
588
 
580
589
 
@@ -592,8 +601,7 @@ def _int_val(env_var: str, default: Optional[int] = None) -> Optional[int]:
592
601
  return int(value)
593
602
  except ValueError:
594
603
  raise ValueError(
595
- f"Invalid value for environment variable {env_var}: {value}. "
596
- f"Value must be an integer."
604
+ f"Invalid value for environment variable {env_var}: {value}. Value must be an integer."
597
605
  )
598
606
 
599
607
 
@@ -631,6 +639,13 @@ def get_env_enable_auth() -> bool:
631
639
  return _bool_val(ENV_PHOENIX_ENABLE_AUTH, False)
632
640
 
633
641
 
642
+ def get_env_disable_basic_auth() -> bool:
643
+ """
644
+ Gets the value of the ENV_PHOENIX_DISABLE_BASIC_AUTH environment variable.
645
+ """
646
+ return _bool_val(ENV_PHOENIX_DISABLE_BASIC_AUTH, False)
647
+
648
+
634
649
  def get_env_disable_rate_limit() -> bool:
635
650
  """
636
651
  Gets the value of the PHOENIX_DISABLE_RATE_LIMIT environment variable.
@@ -638,29 +653,29 @@ def get_env_disable_rate_limit() -> bool:
638
653
  return _bool_val(ENV_PHOENIX_DISABLE_RATE_LIMIT, False)
639
654
 
640
655
 
641
- def get_env_phoenix_secret() -> Optional[str]:
656
+ def get_env_phoenix_secret() -> Secret:
642
657
  """
643
658
  Gets the value of the PHOENIX_SECRET environment variable
644
659
  and performs validation.
645
660
  """
646
661
  phoenix_secret = getenv(ENV_PHOENIX_SECRET)
647
662
  if phoenix_secret is None:
648
- return None
663
+ return Secret("")
649
664
  from phoenix.auth import REQUIREMENTS_FOR_PHOENIX_SECRET
650
665
 
651
666
  REQUIREMENTS_FOR_PHOENIX_SECRET.validate(phoenix_secret, "Phoenix secret")
652
- return phoenix_secret
667
+ return Secret(phoenix_secret)
653
668
 
654
669
 
655
- def get_env_phoenix_admin_secret() -> Optional[str]:
670
+ def get_env_phoenix_admin_secret() -> Secret:
656
671
  """
657
672
  Gets the value of the PHOENIX_ADMIN_SECRET environment variable
658
673
  and performs validation.
659
674
  """
660
675
  phoenix_admin_secret = getenv(ENV_PHOENIX_ADMIN_SECRET)
661
676
  if phoenix_admin_secret is None:
662
- return None
663
- if (phoenix_secret := get_env_phoenix_secret()) is None:
677
+ return Secret("")
678
+ if not (phoenix_secret := get_env_phoenix_secret()):
664
679
  raise ValueError(
665
680
  f"`{ENV_PHOENIX_ADMIN_SECRET}` must be not be set without "
666
681
  f"setting `{ENV_PHOENIX_SECRET}`."
@@ -668,17 +683,24 @@ def get_env_phoenix_admin_secret() -> Optional[str]:
668
683
  from phoenix.auth import REQUIREMENTS_FOR_PHOENIX_SECRET
669
684
 
670
685
  REQUIREMENTS_FOR_PHOENIX_SECRET.validate(phoenix_admin_secret, "Phoenix secret")
671
- if phoenix_admin_secret == phoenix_secret:
686
+ if phoenix_admin_secret == str(phoenix_secret):
672
687
  raise ValueError(
673
688
  f"`{ENV_PHOENIX_ADMIN_SECRET}` must be different from `{ENV_PHOENIX_SECRET}`"
674
689
  )
675
- return phoenix_admin_secret
690
+ return Secret(phoenix_admin_secret)
676
691
 
677
692
 
678
- def get_env_default_admin_initial_password() -> str:
693
+ def get_env_default_admin_initial_password() -> Secret:
679
694
  from phoenix.auth import DEFAULT_ADMIN_PASSWORD
680
695
 
681
- return getenv(ENV_PHOENIX_DEFAULT_ADMIN_INITIAL_PASSWORD) or DEFAULT_ADMIN_PASSWORD
696
+ return Secret(getenv(ENV_PHOENIX_DEFAULT_ADMIN_INITIAL_PASSWORD) or DEFAULT_ADMIN_PASSWORD)
697
+
698
+
699
+ def get_env_cookies_path() -> str:
700
+ """
701
+ Gets the value of the PHOENIX_COOKIE_PATH environment variable.
702
+ """
703
+ return getenv(ENV_PHOENIX_COOKIES_PATH, "/")
682
704
 
683
705
 
684
706
  def get_env_phoenix_use_secure_cookies() -> bool:
@@ -689,7 +711,15 @@ def get_env_phoenix_api_key() -> Optional[str]:
689
711
  return getenv(ENV_PHOENIX_API_KEY)
690
712
 
691
713
 
692
- def get_env_auth_settings() -> tuple[bool, Optional[str]]:
714
+ class AuthSettings(NamedTuple):
715
+ enable_auth: bool
716
+ disable_basic_auth: bool
717
+ phoenix_secret: Secret
718
+ phoenix_admin_secret: Secret
719
+ oauth2_clients: OAuth2Clients
720
+
721
+
722
+ def get_env_auth_settings() -> AuthSettings:
693
723
  """
694
724
  Gets auth settings and performs validation.
695
725
  """
@@ -700,7 +730,22 @@ def get_env_auth_settings() -> tuple[bool, Optional[str]]:
700
730
  f"`{ENV_PHOENIX_SECRET}` must be set when "
701
731
  f"auth is enabled with `{ENV_PHOENIX_ENABLE_AUTH}`"
702
732
  )
703
- return enable_auth, phoenix_secret
733
+ phoenix_admin_secret = get_env_phoenix_admin_secret()
734
+ disable_basic_auth = get_env_disable_basic_auth()
735
+ from phoenix.server.oauth2 import OAuth2Clients
736
+
737
+ oauth2_clients = OAuth2Clients.from_configs(get_env_oauth2_settings())
738
+ if enable_auth and disable_basic_auth and not oauth2_clients:
739
+ raise ValueError(
740
+ "OAuth2 is the only supported auth method but no OAuth2 client configs are provided."
741
+ )
742
+ return AuthSettings(
743
+ enable_auth=enable_auth,
744
+ disable_basic_auth=disable_basic_auth,
745
+ phoenix_secret=phoenix_secret,
746
+ phoenix_admin_secret=phoenix_admin_secret,
747
+ oauth2_clients=oauth2_clients,
748
+ )
704
749
 
705
750
 
706
751
  def get_env_password_reset_token_expiry() -> timedelta:
@@ -839,6 +884,8 @@ class OAuth2ClientConfig:
839
884
  client_id: str
840
885
  client_secret: str
841
886
  oidc_config_url: str
887
+ allow_sign_up: bool
888
+ auto_login: bool
842
889
 
843
890
  @classmethod
844
891
  def from_env(cls, idp_name: str) -> "OAuth2ClientConfig":
@@ -870,6 +917,8 @@ class OAuth2ClientConfig:
870
917
  f"An OpenID Connect configuration URL must be set for the {idp_name} OAuth2 IDP "
871
918
  f"via the {oidc_config_url_env_var} environment variable"
872
919
  )
920
+ allow_sign_up = get_env_oauth2_allow_sign_up(idp_name)
921
+ auto_login = get_env_oauth2_auto_login(idp_name)
873
922
  parsed_oidc_config_url = urlparse(oidc_config_url)
874
923
  is_local_oidc_config_url = parsed_oidc_config_url.hostname in ("localhost", "127.0.0.1")
875
924
  if parsed_oidc_config_url.scheme != "https" and not is_local_oidc_config_url:
@@ -886,17 +935,52 @@ class OAuth2ClientConfig:
886
935
  client_id=client_id,
887
936
  client_secret=client_secret,
888
937
  oidc_config_url=oidc_config_url,
938
+ allow_sign_up=allow_sign_up,
939
+ auto_login=auto_login,
889
940
  )
890
941
 
891
942
 
892
943
  def get_env_oauth2_settings() -> list[OAuth2ClientConfig]:
893
944
  """
894
- Get OAuth2 settings from environment variables.
895
- """
945
+ Retrieves and validates OAuth2/OpenID Connect (OIDC) identity provider configurations from environment variables.
946
+
947
+ This function scans the environment for OAuth2 configuration variables and returns a list of
948
+ configured identity providers. It supports multiple identity providers simultaneously.
949
+
950
+ Environment Variable Pattern:
951
+ PHOENIX_OAUTH2_{IDP_NAME}_{CONFIG_TYPE}
896
952
 
953
+ Required Environment Variables for each IDP:
954
+ - PHOENIX_OAUTH2_{IDP_NAME}_CLIENT_ID: The OAuth2 client ID issued by the identity provider
955
+ - PHOENIX_OAUTH2_{IDP_NAME}_CLIENT_SECRET: The OAuth2 client secret issued by the identity provider
956
+ - PHOENIX_OAUTH2_{IDP_NAME}_OIDC_CONFIG_URL: The OpenID Connect configuration URL (must be HTTPS)
957
+
958
+ Optional Environment Variables:
959
+ - PHOENIX_OAUTH2_{IDP_NAME}_DISPLAY_NAME: A user-friendly name for the identity provider
960
+ - PHOENIX_OAUTH2_{IDP_NAME}_ALLOW_SIGN_UP: Whether to allow new user registration (defaults to True)
961
+ When set to False, the system will check if the user exists in the database by their email address.
962
+ If the user does not exist or has a password set, they will be redirected to the login page with
963
+ an error message.
964
+
965
+ Returns:
966
+ list[OAuth2ClientConfig]: A list of configured OAuth2 identity providers, sorted alphabetically by IDP name.
967
+ Each OAuth2ClientConfig contains the validated configuration for one identity provider.
968
+
969
+ Raises:
970
+ ValueError: If required environment variables are missing or invalid.
971
+ Specifically, if the OIDC configuration URL is not HTTPS (except for localhost).
972
+
973
+ Example:
974
+ To configure Google as an identity provider, set these environment variables:
975
+ PHOENIX_OAUTH2_GOOGLE_CLIENT_ID=your_client_id
976
+ PHOENIX_OAUTH2_GOOGLE_CLIENT_SECRET=your_client_secret
977
+ PHOENIX_OAUTH2_GOOGLE_OIDC_CONFIG_URL=https://accounts.google.com/.well-known/openid-configuration
978
+ PHOENIX_OAUTH2_GOOGLE_DISPLAY_NAME=Google (optional)
979
+ PHOENIX_OAUTH2_GOOGLE_ALLOW_SIGN_UP=true (optional, defaults to true)
980
+ """ # noqa: E501
897
981
  idp_names = set()
898
982
  pattern = re.compile(
899
- r"^PHOENIX_OAUTH2_(\w+)_(DISPLAY_NAME|CLIENT_ID|CLIENT_SECRET|OIDC_CONFIG_URL)$"
983
+ r"^PHOENIX_OAUTH2_(\w+)_(DISPLAY_NAME|CLIENT_ID|CLIENT_SECRET|OIDC_CONFIG_URL|ALLOW_SIGN_UP|AUTO_LOGIN)$" # noqa: E501
900
984
  )
901
985
  for env_var in os.environ:
902
986
  if (match := pattern.match(env_var)) is not None and (idp_name := match.group(1).lower()):
@@ -904,6 +988,47 @@ def get_env_oauth2_settings() -> list[OAuth2ClientConfig]:
904
988
  return [OAuth2ClientConfig.from_env(idp_name) for idp_name in sorted(idp_names)]
905
989
 
906
990
 
991
+ def get_env_oauth2_allow_sign_up(idp_name: str) -> bool:
992
+ """Retrieves the allow_sign_up setting for a specific OAuth2 identity provider.
993
+
994
+ This function determines whether new user registration is allowed for the specified identity provider.
995
+ When set to False, the system will check if the user exists in the database by their email address.
996
+ If the user does not exist or has a password set, they will be redirected to the login page with
997
+ an error message.
998
+
999
+ Parameters:
1000
+ idp_name (str): The name of the identity provider (e.g., 'google', 'aws_cognito', 'microsoft_entra_id')
1001
+
1002
+ Returns:
1003
+ bool: True if new user registration is allowed (default), False otherwise
1004
+
1005
+ Environment Variable:
1006
+ PHOENIX_OAUTH2_{IDP_NAME}_ALLOW_SIGN_UP: Controls whether new user registration is allowed (defaults to True if not set)
1007
+ """ # noqa: E501
1008
+ env_var = f"PHOENIX_OAUTH2_{idp_name}_ALLOW_SIGN_UP".upper()
1009
+ return _bool_val(env_var, True)
1010
+
1011
+
1012
+ def get_env_oauth2_auto_login(idp_name: str) -> bool:
1013
+ """Retrieves the auto_login setting for a specific OAuth2 identity provider.
1014
+
1015
+ This function determines whether users should be automatically logged in when accessing the OAuth2
1016
+ identity provider's login page. When set to True, users will be redirected to the identity provider's
1017
+ login page without first seeing the application's login page.
1018
+
1019
+ Parameters:
1020
+ idp_name (str): The name of the identity provider (e.g., 'google', 'aws_cognito', 'microsoft_entra_id')
1021
+
1022
+ Returns:
1023
+ bool: True if auto-login is enabled, False otherwise (defaults to False if not set)
1024
+
1025
+ Environment Variable:
1026
+ PHOENIX_OAUTH2_{IDP_NAME}_AUTO_LOGIN: Controls whether auto-login is enabled (defaults to False if not set)
1027
+ """ # noqa: E501
1028
+ env_var = f"PHOENIX_OAUTH2_{idp_name}_AUTO_LOGIN".upper()
1029
+ return _bool_val(env_var, False)
1030
+
1031
+
907
1032
  PHOENIX_DIR = Path(__file__).resolve().parent
908
1033
  # Server config
909
1034
  SERVER_DIR = PHOENIX_DIR / "server"
@@ -1258,7 +1383,7 @@ def get_env_logging_mode() -> LoggingMode:
1258
1383
  except ValueError:
1259
1384
  raise ValueError(
1260
1385
  f"Invalid value `{logging_mode}` for env var `{ENV_LOGGING_MODE}`. "
1261
- f"Valid values are: {log_a_list([mode.value for mode in LoggingMode],'and')} "
1386
+ f"Valid values are: {log_a_list([mode.value for mode in LoggingMode], 'and')} "
1262
1387
  "(case-insensitive)."
1263
1388
  )
1264
1389
 
@@ -1337,7 +1462,7 @@ def _get_logging_level(env_var: str, default_level: int) -> int:
1337
1462
  if logging_level.upper() not in valid_values:
1338
1463
  raise ValueError(
1339
1464
  f"Invalid value `{logging_level}` for env var `{env_var}`. "
1340
- f"Valid values are: {log_a_list(valid_values,'and')} (case-insensitive)."
1465
+ f"Valid values are: {log_a_list(valid_values, 'and')} (case-insensitive)."
1341
1466
  )
1342
1467
  return levelNamesMapping[logging_level.upper()]
1343
1468
 
@@ -4,9 +4,8 @@ from enum import Enum
4
4
  from sqlalchemy.orm import InstrumentedAttribute
5
5
 
6
6
  from phoenix.db import models
7
- from phoenix.db.models import AuthMethod
8
7
 
9
- __all__ = ["AuthMethod", "UserRole", "COLUMN_ENUMS"]
8
+ __all__ = ["UserRole", "COLUMN_ENUMS"]
10
9
 
11
10
 
12
11
  class UserRole(Enum):
@@ -26,6 +26,7 @@ from phoenix.auth import (
26
26
  from phoenix.config import (
27
27
  get_env_admins,
28
28
  get_env_default_admin_initial_password,
29
+ get_env_disable_basic_auth,
29
30
  )
30
31
  from phoenix.db import models
31
32
  from phoenix.db.constants import DEFAULT_PROJECT_TRACE_RETENTION_POLICY_ID
@@ -111,7 +112,7 @@ async def _ensure_user_roles(db: DbSessionFactory) -> None:
111
112
  if (system_role := UserRole.SYSTEM.value) not in existing_roles and (
112
113
  system_role_id := role_ids.get(system_role)
113
114
  ) is not None:
114
- system_user = models.User(
115
+ system_user = models.LocalUser(
115
116
  user_role_id=system_role_id,
116
117
  username=DEFAULT_SYSTEM_USERNAME,
117
118
  email=DEFAULT_SYSTEM_EMAIL,
@@ -128,7 +129,7 @@ async def _ensure_user_roles(db: DbSessionFactory) -> None:
128
129
  compute = partial(compute_password_hash, password=password, salt=salt)
129
130
  loop = asyncio.get_running_loop()
130
131
  hash_ = await loop.run_in_executor(None, compute)
131
- admin_user = models.User(
132
+ admin_user = models.LocalUser(
132
133
  user_role_id=admin_role_id,
133
134
  username=DEFAULT_ADMIN_USERNAME,
134
135
  email=DEFAULT_ADMIN_EMAIL,
@@ -168,6 +169,7 @@ async def _ensure_admins(
168
169
  """
169
170
  if not (admins := get_env_admins()):
170
171
  return
172
+ disable_basic_auth = get_env_disable_basic_auth()
171
173
  async with db() as session:
172
174
  existing_emails = set(
173
175
  await session.scalars(
@@ -195,16 +197,23 @@ async def _ensure_admins(
195
197
  select(models.UserRole.id).filter_by(name=UserRole.ADMIN.value)
196
198
  )
197
199
  assert admin_role_id is not None, "Admin role not found in database"
200
+ user: models.User
198
201
  for email, username in admins.items():
199
- values = dict(
200
- user_role_id=admin_role_id,
201
- username=username,
202
- email=email,
203
- password_salt=secrets.token_bytes(DEFAULT_SECRET_LENGTH),
204
- password_hash=secrets.token_bytes(DEFAULT_SECRET_LENGTH),
205
- reset_password=True,
206
- )
207
- await session.execute(insert(models.User).values(values))
202
+ if not disable_basic_auth:
203
+ user = models.LocalUser(
204
+ email=email,
205
+ username=username,
206
+ password_salt=secrets.token_bytes(DEFAULT_SECRET_LENGTH),
207
+ password_hash=secrets.token_bytes(DEFAULT_SECRET_LENGTH),
208
+ )
209
+ else:
210
+ user = models.OAuth2User(
211
+ email=email,
212
+ username=username,
213
+ )
214
+ user.user_role_id = admin_role_id
215
+ session.add(user)
216
+ await session.flush()
208
217
  if email_sender is None:
209
218
  return
210
219
  for exc in await gather(
@@ -0,0 +1,179 @@
1
+ """Add auth_method column to users table and migrate existing authentication data.
2
+
3
+ This migration:
4
+ 1. Adds a new 'auth_method' column to the users table that indicates whether a user
5
+ authenticates via local password ('LOCAL') or external OAuth2 ('OAUTH2')
6
+ 2. Migrates existing authentication data to populate the new column:
7
+ - Sets 'LOCAL' for users with password_hash
8
+ - Sets 'OAUTH2' for users with OAuth2 credentials
9
+ 3. Adds appropriate constraints to ensure data integrity:
10
+ - NOT NULL constraint on auth_method
11
+ - 'valid_auth_method': ensures only 'LOCAL' or 'OAUTH2' values
12
+ - 'local_auth_has_password_no_oauth': ensures LOCAL users have password credentials and
13
+ do not have OAuth2 credentials
14
+ - 'non_local_auth_has_no_password': ensures OAUTH2 users do not have password credentials
15
+ 4. Removes legacy constraints that are replaced by the new column:
16
+ - 'password_hash_and_salt': ensures password_hash and password_salt are consistent
17
+ - 'exactly_one_auth_method': replaced by auth_method column and its constraints
18
+ - 'oauth2_client_id_and_user_id': replaced by auth_method column and its constraints
19
+ 5. Drops redundant single column indices:
20
+ - 'ix_users_oauth2_client_id' and 'ix_users_oauth2_user_id' are removed as they are
21
+ redundant with the unique constraint 'uq_users_oauth2_client_id_oauth2_user_id',
22
+ which already provides the necessary composite index for lookups
23
+
24
+ The migration uses batch_alter_table to ensure compatibility with both SQLite and PostgreSQL.
25
+ This approach allows us to:
26
+ - Add the column as nullable initially
27
+ - Update the values based on existing authentication data
28
+ - Make the column NOT NULL after populating
29
+ - Add appropriate constraints
30
+ - Remove legacy constraints
31
+ - Drop redundant indices
32
+
33
+ The downgrade path:
34
+ 1. Recreates the legacy constraints:
35
+ - 'password_hash_and_salt': ensures password_hash and password_salt are consistent
36
+ - 'exactly_one_auth_method': ensures exactly one auth method is set
37
+ - 'oauth2_client_id_and_user_id': ensures OAuth2 credentials are consistent
38
+ 2. Removes the auth_method column and its associated constraints
39
+ 3. Recreates the single column indices to maintain backward compatibility:
40
+ - 'ix_users_oauth2_client_id'
41
+ - 'ix_users_oauth2_user_id'
42
+
43
+ Revision ID: 6a88424799fe
44
+ Revises: 8a3764fe7f1a
45
+ Create Date: 2025-05-01 08:08:22.700715
46
+
47
+ """ # noqa: E501
48
+
49
+ from typing import Sequence, Union
50
+
51
+ import sqlalchemy as sa
52
+ from alembic import op
53
+
54
+ # revision identifiers, used by Alembic.
55
+ revision: str = "6a88424799fe"
56
+ down_revision: Union[str, None] = "8a3764fe7f1a"
57
+ branch_labels: Union[str, Sequence[str], None] = None
58
+ depends_on: Union[str, Sequence[str], None] = None
59
+
60
+
61
+ def upgrade() -> None:
62
+ """Upgrade the database schema to include the auth_method column.
63
+
64
+ This function:
65
+ 1. Adds the auth_method column as nullable
66
+ 2. Populates the column based on existing authentication data:
67
+ - 'LOCAL' for users with password_hash
68
+ - 'OAUTH2' for users with OAuth2 credentials
69
+ 3. Makes the column NOT NULL after populating
70
+ 4. Adds CHECK constraints to ensure data integrity:
71
+ - 'valid_auth_method': ensures only 'LOCAL' or 'OAUTH2' values
72
+ - 'local_auth_has_password_no_oauth': ensures LOCAL users have password credentials and
73
+ do not have OAuth2 credentials
74
+ - 'non_local_auth_has_no_password': ensures OAUTH2 users do not have password credentials
75
+ 5. Removes legacy constraints that are replaced by the new column:
76
+ - 'password_hash_and_salt'
77
+ - 'exactly_one_auth_method'
78
+ - 'oauth2_client_id_and_user_id'
79
+ 6. Drops redundant single column indices:
80
+ - 'ix_users_oauth2_client_id' and 'ix_users_oauth2_user_id' are removed as they are
81
+ redundant with the unique constraint 'uq_users_oauth2_client_id_oauth2_user_id',
82
+ which already provides the necessary composite index for lookups
83
+
84
+ The implementation uses batch_alter_table for compatibility with both
85
+ SQLite and PostgreSQL databases.
86
+
87
+ Raises:
88
+ sqlalchemy.exc.SQLAlchemyError: If database operations fail
89
+ """ # noqa: E501
90
+ with op.batch_alter_table("users") as batch_op:
91
+ # For SQLite, first add the column as nullable
92
+ batch_op.add_column(sa.Column("auth_method", sa.String, nullable=True))
93
+
94
+ with op.batch_alter_table("users") as batch_op:
95
+ batch_op.execute("""
96
+ UPDATE users
97
+ SET auth_method = CASE
98
+ WHEN password_hash IS NOT NULL THEN 'LOCAL' ELSE 'OAUTH2' END
99
+ """)
100
+ # Make the column non-nullable
101
+ batch_op.alter_column("auth_method", nullable=False, existing_nullable=True)
102
+
103
+ # Drop both old constraints as they're now redundant
104
+ batch_op.drop_constraint("password_hash_and_salt", type_="check")
105
+ batch_op.drop_constraint("exactly_one_auth_method", type_="check")
106
+ batch_op.drop_constraint("oauth2_client_id_and_user_id", type_="check")
107
+
108
+ # Drop redundant single column indices, because a composite index already
109
+ # exists in the uniqueness constraint for (client_id, user_id)
110
+ batch_op.drop_index("ix_users_oauth2_client_id")
111
+ batch_op.drop_index("ix_users_oauth2_user_id")
112
+
113
+ # Add CHECK constraint to ensure only valid values are allowed
114
+ batch_op.create_check_constraint(
115
+ "valid_auth_method",
116
+ "auth_method IN ('LOCAL', 'OAUTH2')",
117
+ )
118
+ batch_op.create_check_constraint(
119
+ "local_auth_has_password_no_oauth",
120
+ "auth_method != 'LOCAL' "
121
+ "OR (password_hash IS NOT NULL AND password_salt IS NOT NULL "
122
+ "AND oauth2_client_id IS NULL AND oauth2_user_id IS NULL)",
123
+ )
124
+ batch_op.create_check_constraint(
125
+ "non_local_auth_has_no_password",
126
+ "auth_method = 'LOCAL' OR (password_hash IS NULL AND password_salt IS NULL)",
127
+ )
128
+
129
+
130
+ def downgrade() -> None:
131
+ """Downgrade the database schema by removing the auth_method column.
132
+
133
+ This function:
134
+ 1. Recreates the legacy constraints that were removed in the upgrade:
135
+ - 'password_hash_and_salt': ensures password_hash and password_salt are consistent
136
+ - 'exactly_one_auth_method': ensures exactly one auth method is set
137
+ - 'oauth2_client_id_and_user_id': ensures OAuth2 credentials are consistent
138
+ 2. Removes the auth_method column and its associated CHECK constraints:
139
+ - 'non_local_auth_has_no_password'
140
+ - 'local_auth_has_password_no_oauth'
141
+ - 'valid_auth_method'
142
+ 3. Recreates the single column indices to maintain backward compatibility:
143
+ - 'ix_users_oauth2_client_id'
144
+ - 'ix_users_oauth2_user_id'
145
+
146
+ The implementation uses batch_alter_table to ensure compatibility with both
147
+ SQLite and PostgreSQL databases.
148
+
149
+ Raises:
150
+ sqlalchemy.exc.SQLAlchemyError: If database operations fail
151
+ """ # noqa: E501
152
+ # Use batch_alter_table for SQLite compatibility
153
+ # This ensures the downgrade works on both SQLite and PostgreSQL
154
+ with op.batch_alter_table("users") as batch_op:
155
+ # Drop the CHECK constraint and column
156
+ batch_op.drop_constraint("non_local_auth_has_no_password", type_="check")
157
+ batch_op.drop_constraint("local_auth_has_password_no_oauth", type_="check")
158
+ batch_op.drop_constraint("valid_auth_method", type_="check")
159
+
160
+ # Recreate single column indices
161
+ batch_op.create_index("ix_users_oauth2_user_id", ["oauth2_user_id"])
162
+ batch_op.create_index("ix_users_oauth2_client_id", ["oauth2_client_id"])
163
+
164
+ # Recreate both old constraints that were dropped in upgrade
165
+ batch_op.create_check_constraint(
166
+ "oauth2_client_id_and_user_id",
167
+ "(oauth2_client_id IS NULL) = (oauth2_user_id IS NULL)",
168
+ )
169
+ batch_op.create_check_constraint(
170
+ "exactly_one_auth_method",
171
+ "(password_hash IS NULL) != (oauth2_client_id IS NULL)",
172
+ )
173
+ batch_op.create_check_constraint(
174
+ "password_hash_and_salt",
175
+ "(password_hash IS NULL) = (password_salt IS NULL)",
176
+ )
177
+
178
+ # Remove added column
179
+ batch_op.drop_column("auth_method")