diff --git a/src/Common/Constants.ts b/src/Common/Constants.ts index 884209fed..51df6e94f 100644 --- a/src/Common/Constants.ts +++ b/src/Common/Constants.ts @@ -430,6 +430,12 @@ export class JunoEndpoints { public static readonly Stage = "https://tools-staging.cosmos.azure.com"; } +export class PriorityLevel { + public static readonly High = "high"; + public static readonly Low = "low"; + public static readonly Default = "low"; +} + export const QueryCopilotSampleDatabaseId = "CopilotSampleDb"; export const QueryCopilotSampleContainerId = "SampleContainer"; @@ -601,8 +607,68 @@ export const QueryCopilotSampleContainerSchema = { }, }; -export class PriorityLevel { - public static readonly High = "high"; - public static readonly Low = "low"; - public static readonly Default = "low"; -} +export const ShortenedQueryCopilotSampleContainerSchema = { + containerSchema: { + product: { + sampleData: { + categoryName: "Components, Saddles", + + name: "LL Road Seat/Saddle", + + price: 27.12, + + tags: [ + { + id: "0573D684-9140-4DEE-89AF-4E4A90E65666", + + name: "Tag-113", + }, + + { + id: "6C2F05C8-1E61-4912-BE1A-C67A378429BB", + + name: "Tag-5", + }, + ], + }, + + schema: { + properties: { + categoryName: { + type: "string", + }, + + name: { + type: "string", + }, + + price: { + type: "number", + }, + + tags: { + items: { + properties: { + id: { + type: "string", + }, + + name: { + type: "string", + }, + }, + + type: "object", + }, + + type: "array", + }, + }, + + type: "object", + }, + }, + }, + + userPrompt: "find all products", +}; diff --git a/src/Explorer/QueryCopilot/QueryCopilotTab.tsx b/src/Explorer/QueryCopilot/QueryCopilotTab.tsx index 1c32596b4..1f6888237 100644 --- a/src/Explorer/QueryCopilot/QueryCopilotTab.tsx +++ b/src/Explorer/QueryCopilot/QueryCopilotTab.tsx @@ -17,7 +17,11 @@ import { TextField, } from "@fluentui/react"; import { useBoolean } from "@fluentui/react-hooks"; -import { QueryCopilotSampleContainerId, QueryCopilotSampleContainerSchema } from "Common/Constants"; +import { + QueryCopilotSampleContainerId, + QueryCopilotSampleContainerSchema, + ShortenedQueryCopilotSampleContainerSchema, +} from "Common/Constants"; import { getErrorMessage, handleError } from "Common/ErrorHandlingUtils"; import { shouldEnableCrossPartitionKey } from "Common/HeadersUtility"; import { MinimalQueryIterator } from "Common/IteratorUtilities"; @@ -186,7 +190,7 @@ export const QueryCopilotTab: React.FC = ({ explorer }: Qu const generateSQLQuery = async (): Promise => { try { - if (shouldAllocateContainer) { + if (shouldAllocateContainer && userContext.features.enableCopilotPhoenixGateaway) { await explorer.allocateContainer(); setShouldAllocateContainer(false); } @@ -195,13 +199,17 @@ export const QueryCopilotTab: React.FC = ({ explorer }: Qu useTabs.getState().setIsTabExecuting(true); useTabs.getState().setIsQueryErrorThrown(false); const payload = { - containerSchema: QueryCopilotSampleContainerSchema, + containerSchema: userContext.features.enableCopilotFullSchema + ? QueryCopilotSampleContainerSchema + : ShortenedQueryCopilotSampleContainerSchema, userPrompt: userPrompt, }; setShowDeletePopup(false); useQueryCopilot.getState().refreshCorrelationId(); const serverInfo = useNotebook.getState().notebookServerInfo; - const queryUri = createUri(serverInfo.notebookServerEndpoint, "generateSQLQuery"); + const queryUri = userContext.features.enableCopilotPhoenixGateaway + ? createUri(serverInfo.notebookServerEndpoint, "generateSQLQuery") + : createUri("https://copilotorchestrater.azurewebsites.net/", "generateSQLQuery"); const response = await fetch(queryUri, { method: "POST", headers: { diff --git a/src/Explorer/QueryCopilot/QueryCopilotUtilities.test.tsx b/src/Explorer/QueryCopilot/QueryCopilotUtilities.test.tsx index 1be2873cb..e4b399fd8 100644 --- a/src/Explorer/QueryCopilot/QueryCopilotUtilities.test.tsx +++ b/src/Explorer/QueryCopilot/QueryCopilotUtilities.test.tsx @@ -1,11 +1,13 @@ import { FeedOptions } from "@azure/cosmos"; -import { QueryCopilotSampleContainerSchema } from "Common/Constants"; +import { QueryCopilotSampleContainerSchema, ShortenedQueryCopilotSampleContainerSchema } from "Common/Constants"; import { handleError } from "Common/ErrorHandlingUtils"; import { sampleDataClient } from "Common/SampleDataClient"; +import { createUri } from "Common/UrlUtility"; import * as commonUtils from "Common/dataAccess/queryDocuments"; import Explorer from "Explorer/Explorer"; import { useNotebook } from "Explorer/Notebook/useNotebook"; import DocumentId from "Explorer/Tree/DocumentId"; +import { userContext } from "UserContext"; import { querySampleDocuments, readSampleDocument, submitFeedback } from "./QueryCopilotUtilities"; jest.mock("Explorer/Tree/DocumentId", () => { @@ -70,7 +72,9 @@ describe("QueryCopilotUtilities", () => { userPrompt: "UserPrompt", description: "Description", contact: "Contact", - containerSchema: QueryCopilotSampleContainerSchema, + containerSchema: userContext.features.enableCopilotFullSchema + ? QueryCopilotSampleContainerSchema + : ShortenedQueryCopilotSampleContainerSchema, }; const mockStore = useNotebook.getState(); @@ -82,11 +86,14 @@ describe("QueryCopilotUtilities", () => { }; }); + const feedbackUri = userContext.features.enableCopilotPhoenixGateaway + ? createUri(useNotebook.getState().notebookServerInfo.notebookServerEndpoint, "feedback") + : createUri("https://copilotorchestrater.azurewebsites.net/", "feedback"); + it("should call fetch with the payload with like", async () => { const mockFetch = jest.fn().mockResolvedValueOnce({}); globalThis.fetch = mockFetch; - await submitFeedback({ params: { likeQuery: true, @@ -99,7 +106,7 @@ describe("QueryCopilotUtilities", () => { }); expect(mockFetch).toHaveBeenCalledWith( - "mocked-endpoint/feedback", + feedbackUri, expect.objectContaining({ headers: expect.objectContaining({ "x-ms-correlationid": "mocked-correlation-id", @@ -131,7 +138,7 @@ describe("QueryCopilotUtilities", () => { }); expect(mockFetch).toHaveBeenCalledWith( - "mocked-endpoint/feedback", + feedbackUri, expect.objectContaining({ method: "POST", headers: { diff --git a/src/Explorer/QueryCopilot/QueryCopilotUtilities.ts b/src/Explorer/QueryCopilot/QueryCopilotUtilities.ts index 9a3c5a33d..598aa937b 100644 --- a/src/Explorer/QueryCopilot/QueryCopilotUtilities.ts +++ b/src/Explorer/QueryCopilot/QueryCopilotUtilities.ts @@ -3,6 +3,7 @@ import { QueryCopilotSampleContainerId, QueryCopilotSampleContainerSchema, QueryCopilotSampleDatabaseId, + ShortenedQueryCopilotSampleContainerSchema, } from "Common/Constants"; import { handleError } from "Common/ErrorHandlingUtils"; import { sampleDataClient } from "Common/SampleDataClient"; @@ -12,6 +13,7 @@ import { getCommonQueryOptions } from "Common/dataAccess/queryDocuments"; import Explorer from "Explorer/Explorer"; import { useNotebook } from "Explorer/Notebook/useNotebook"; import DocumentId from "Explorer/Tree/DocumentId"; +import { userContext } from "UserContext"; import { logConsoleProgress } from "Utils/NotificationConsoleUtils"; import { useQueryCopilot } from "hooks/useQueryCopilot"; @@ -34,19 +36,23 @@ export const submitFeedback = async ({ const { likeQuery, generatedQuery, userPrompt, description, contact } = params; const { correlationId, shouldAllocateContainer, setShouldAllocateContainer } = useQueryCopilot(); const payload = { - containerSchema: QueryCopilotSampleContainerSchema, + containerSchema: userContext.features.enableCopilotFullSchema + ? QueryCopilotSampleContainerSchema + : ShortenedQueryCopilotSampleContainerSchema, like: likeQuery ? "like" : "dislike", generatedSql: generatedQuery, userPrompt, description: description || "", contact: contact || "", }; - if (shouldAllocateContainer) { + if (shouldAllocateContainer && userContext.features.enableCopilotPhoenixGateaway) { await explorer.allocateContainer(); setShouldAllocateContainer(false); } const serverInfo = useNotebook.getState().notebookServerInfo; - const feedbackUri = createUri(serverInfo.notebookServerEndpoint, "feedback"); + const feedbackUri = userContext.features.enableCopilotPhoenixGateaway + ? createUri(serverInfo.notebookServerEndpoint, "feedback") + : createUri("https://copilotorchestrater.azurewebsites.net/", "feedback"); const response = await fetch(feedbackUri, { method: "POST", headers: { diff --git a/src/Platform/Hosted/extractFeatures.ts b/src/Platform/Hosted/extractFeatures.ts index 9d90e7c5e..881465e9c 100644 --- a/src/Platform/Hosted/extractFeatures.ts +++ b/src/Platform/Hosted/extractFeatures.ts @@ -39,6 +39,8 @@ export type Features = { readonly enablePriorityBasedThrottling: boolean; readonly enableNPSSurvey: boolean; readonly copilotVersion?: string; + readonly enableCopilotPhoenixGateaway: boolean; + readonly enableCopilotFullSchema: boolean; // can be set via both flight and feature flag autoscaleDefault: boolean; @@ -110,6 +112,8 @@ export function extractFeatures(given = new URLSearchParams(window.location.sear enableNPSSurvey: "true" === get("enablenpssurvey"), enableCopilot: "true" === get("enablecopilot"), copilotVersion: get("copilotVersion") ? get("copilotVersion") : "v1.0", + enableCopilotPhoenixGateaway: "true" === get("enablecopilotphoenixgateaway"), + enableCopilotFullSchema: "true" === get("enablecopilotfullschema"), }; }