diff --git a/app/src/utils/errorUtils.ts b/app/src/utils/errorUtils.ts index d8259a9db9..89976cc8af 100644 --- a/app/src/utils/errorUtils.ts +++ b/app/src/utils/errorUtils.ts @@ -72,6 +72,18 @@ const isErrorWithSource = (error: unknown): error is ErrorWithSource => { ); }; +const isErrorsArray = (errors: unknown): errors is { message: string }[] => { + return ( + Array.isArray(errors) && + errors.every( + (error) => + typeof error === "object" && + error !== null && + typeof error.message === "string" + ) + ); +}; + /** * Extracts the error messages from a Relay subscription error. * A relay subscription error contains a source property with an errors array. @@ -96,5 +108,8 @@ export const getErrorMessagesFromRelaySubscriptionError = ( if (isErrorWithSource(error)) { return error.source.errors.map((error) => error.message); } + if (isErrorsArray(error)) { + return error.map((error) => error.message); + } return null; }; diff --git a/src/phoenix/server/api/mutations/chat_mutations.py b/src/phoenix/server/api/mutations/chat_mutations.py index b041ceff98..59baeb0210 100644 --- a/src/phoenix/server/api/mutations/chat_mutations.py +++ b/src/phoenix/server/api/mutations/chat_mutations.py @@ -25,6 +25,7 @@ from phoenix.datetime_utils import local_now, normalize_datetime from phoenix.db import models from phoenix.db.helpers import get_dataset_example_revisions +from phoenix.server.api.auth import IsNotReadOnly from phoenix.server.api.context import Context from phoenix.server.api.exceptions import BadRequest, CustomGraphQLError, NotFound from phoenix.server.api.helpers.playground_clients import ( @@ -118,7 +119,7 @@ class ChatCompletionOverDatasetMutationPayload: @strawberry.type class ChatCompletionMutationMixin: - @strawberry.mutation + @strawberry.mutation(permission_classes=[IsNotReadOnly]) # type: ignore @classmethod async def chat_completion_over_dataset( cls, @@ -273,7 +274,7 @@ async def chat_completion_over_dataset( payload.examples.append(example_payload) return payload - @strawberry.mutation + @strawberry.mutation(permission_classes=[IsNotReadOnly]) # type: ignore @classmethod async def chat_completion( cls, info: Info[Context, None], input: ChatCompletionInput diff --git a/src/phoenix/server/api/subscriptions.py b/src/phoenix/server/api/subscriptions.py index 72b6a3a1fc..47e9cee52d 100644 --- a/src/phoenix/server/api/subscriptions.py +++ b/src/phoenix/server/api/subscriptions.py @@ -24,6 +24,7 @@ from phoenix.datetime_utils import local_now, normalize_datetime from phoenix.db import models +from phoenix.server.api.auth import IsNotReadOnly from phoenix.server.api.context import Context from phoenix.server.api.exceptions import BadRequest, CustomGraphQLError, NotFound from phoenix.server.api.helpers.playground_clients import ( @@ -87,7 +88,7 @@ @strawberry.type class Subscription: - @strawberry.subscription + @strawberry.subscription(permission_classes=[IsNotReadOnly]) # type: ignore async def chat_completion( self, info: Info[Context, None], input: ChatCompletionInput ) -> AsyncIterator[ChatCompletionSubscriptionPayload]: @@ -162,7 +163,7 @@ async def chat_completion( info.context.event_queue.put(SpanInsertEvent(ids=(playground_project_id,))) yield ChatCompletionSubscriptionResult(span=to_gql_span(db_span)) - @strawberry.subscription + @strawberry.subscription(permission_classes=[IsNotReadOnly]) # type: ignore async def chat_completion_over_dataset( self, info: Info[Context, None], input: ChatCompletionOverDatasetInput ) -> AsyncIterator[ChatCompletionSubscriptionPayload]: