Skip to content

Commit

Permalink
refactor: update scaffolding declarative Copilot (#11491)
Browse files Browse the repository at this point in the history
* refactor: first

* refactor: more

* test: ut

* test: ut

* test: ut

* refactor: pr comment
  • Loading branch information
yuqizhou77 authored Apr 26, 2024
1 parent c59795a commit f2bd731
Show file tree
Hide file tree
Showing 12 changed files with 20 additions and 286 deletions.
8 changes: 1 addition & 7 deletions packages/cli/src/commands/models/create.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,7 @@ function adjustOptions(options: CLICommandOption[]) {
break;
}
}
if (!featureFlagManager.getBooleanValue(FeatureFlags.CustomizeGpt)) {
//skip customize GPT questions if customize GPT is not enabled.
const customizeGptQuestionNames = [QuestionNames.CustomizeGptWithPluginStart];
options = options.filter(
(option) => !customizeGptQuestionNames.includes(option.name as QuestionNames)
);
}

return options;
}

Expand Down
25 changes: 0 additions & 25 deletions packages/cli/tests/unit/commands.tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,31 +106,6 @@ describe("CLI commands", () => {
assert.isTrue(res.isOk());
});

it("createProjectOptions - need to adjust options when feature flag is enabled", async () => {
mockedEnvRestore = mockedEnv({
DEVELOP_COPILOT_PLUGIN: "true",
API_COPILOT_PLUGIN: "false",
[FeatureFlags.CustomizeGpt.name]: "true",
});
sandbox.stub(activate, "getFxCore").returns(new FxCore({} as any));
sandbox.stub(FxCore.prototype, "createProject").resolves(ok({ projectPath: "..." }));

const ctx: CLIContext = {
command: { ...getCreateCommand(), fullName: "new" },
optionValues: {},
globalOptionValues: {},
argumentValues: [],
telemetryProperties: {},
};

const filteredQuestionNames = [QuestionNames.CustomizeGptWithPluginStart.toString()];
assert.isTrue(
ctx.command.options?.filter((o) => filteredQuestionNames.includes(o.name)).length === 1
);
const res = await getCreateCommand().handler!(ctx);
assert.isTrue(res.isOk());
});

it("core return error", async () => {
sandbox.stub(activate, "getFxCore").returns(new FxCore({} as any));
sandbox.stub(FxCore.prototype, "createProject").resolves(err(new UserCancelError()));
Expand Down
2 changes: 1 addition & 1 deletion packages/fx-core/src/common/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,5 +52,5 @@ export class FeatureFlagName {
static readonly ChatParticipant = "TEAMSFX_CHAT_PARTICIPANT";
static readonly NewGenerator = "TEAMSFX_NEW_GENERATOR";
static readonly CopilotAuth = "TEAMSFX_COPILOT_AUTH";
static readonly CustomizeGpt = "TEAMSFX_CUSTOMIZE_GPT";
static readonly CustomizeGpt = "TEAMSFX_DECLARATIVE_COPILOT";
}
6 changes: 1 addition & 5 deletions packages/fx-core/src/component/coordinator/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -201,11 +201,7 @@ class Coordinator {
const res = await OfficeAddinGenerator.generate(context, inputs, projectPath);
if (res.isErr()) return err(res.error);
}
} else if (
capability === CapabilityOptions.copilotPluginApiSpec().id ||
inputs[QuestionNames.CustomizeGptWithPluginStart] ===
CapabilityOptions.copilotPluginApiSpec().id
) {
} else if (capability === CapabilityOptions.copilotPluginApiSpec().id) {
const res = await CopilotPluginGenerator.generatePluginFromApiSpec(
context,
inputs,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import {
ResponseTemplatesFolderName,
AppPackageFolderName,
Warning,
ApiOperation,
AuthInfo,
SystemError,
} from "@microsoft/teamsfx-api";
Expand All @@ -44,7 +43,7 @@ import {
} from "./helper";
import { getLocalizedString } from "../../../common/localizeUtils";
import { manifestUtils } from "../../driver/teamsApp/utils/ManifestUtils";
import { CapabilityOptions, ProgrammingLanguage } from "../../../question/create";
import { ProgrammingLanguage } from "../../../question/create";
import * as fs from "fs-extra";
import { assembleError } from "../../../error";
import {
Expand All @@ -53,14 +52,10 @@ import {
ValidationStatus,
WarningType,
ProjectType,
Utils,
ParseOptions,
} from "@microsoft/m365-spec-parser";
import * as util from "util";
import { isValidHttpUrl } from "../../../question/util";
import { merge } from "lodash";
import { TemplateNames } from "../templates/templateNames";
import { copilotGptManifestUtils } from "../../driver/teamsApp/utils/CopilotGptManifestUtils";
import { isCopilotAuthEnabled } from "../../../common/featureFlags";

const fromApiSpecComponentName = "copilot-plugin-existing-api";
Expand All @@ -74,7 +69,6 @@ const apiSpecFolderName = "apiSpecificationFile";
const apiSpecYamlFileName = "openapi.yaml";
const apiSpecJsonFileName = "openapi.json";
const pluginManifestFileName = "ai-plugin.json";
const defaultPluginId = "plugin_1";

const copilotPluginExistingApiSpecUrlTelemetryEvent = "copilot-plugin-existing-api-spec-url";

Expand Down Expand Up @@ -142,11 +136,7 @@ export class CopilotPluginGenerator {
destinationPath: string,
actionContext?: ActionContext
): Promise<Result<CopilotPluginGeneratorResult, FxError>> {
const templateName =
inputs[QuestionNames.CustomizeGptWithPluginStart] ===
CapabilityOptions.copilotPluginApiSpec().id
? TemplateNames.BasicGpt
: apiPluginFromApiSpecTemplateName;
const templateName = apiPluginFromApiSpecTemplateName;
const componentName = fromApiSpecComponentName;

merge(actionContext?.telemetryProps, { [telemetryProperties.templateName]: templateName });
Expand Down Expand Up @@ -294,14 +284,10 @@ export class CopilotPluginGenerator {
});

// validate API spec
const isGptPlugin = templateName === TemplateNames.BasicGpt;
const specParser = new SpecParser(
url,
isPlugin
? {
...copilotPluginParserOptions,
isGptPlugin,
}
? copilotPluginParserOptions
: {
allowBearerTokenAuth: true, // Currently, API key auth support is actually bearer token auth
allowMultipleParameters: true,
Expand Down Expand Up @@ -414,25 +400,6 @@ export class CopilotPluginGenerator {
if (updateManifestRes.isErr()) return err(updateManifestRes.error);
}

// update gpt.json including plugins
if (isGptPlugin && teamsManifest.copilotGpts && teamsManifest.copilotGpts.length > 0) {
const copilotGptPath = path.join(
destinationPath,
AppPackageFolderName,
teamsManifest.copilotGpts[0].file
);
await fs.ensureFile(copilotGptPath);
const addPluginRes = await copilotGptManifestUtils.addPlugin(
copilotGptPath,
defaultPluginId,
pluginManifestFileName
);

if (addPluginRes.isErr()) {
return err(addPluginRes.error);
}
}

if (componentName === forCustomCopilotRagCustomApi) {
const specs = await specParser.getFilteredSpecs(filters);
const spec = specs[1];
Expand Down
41 changes: 8 additions & 33 deletions packages/fx-core/src/question/create.ts
Original file line number Diff line number Diff line change
Expand Up @@ -864,17 +864,18 @@ export class CapabilityOptions {
// customize GPT
static customizeGptBasic(): OptionItem {
return {
id: "customize-gpt-basic",
label: "Basic GPT",
detail: "A simple GPT skeleton you can author without any plugin",
id: "basic-declarative-copilot",
label: "Basic Declarative Copilot",
detail: "A declarative Copilot skeleton you can author without any plugin",
};
}

static customizeGptWithPlugin(): OptionItem {
return {
id: "customize-gpt-with-plugin",
label: "GPT with a plugin",
detail: "A GPT containing a Copilot plugin",
id: "declarative-copilot-with-plugin-from-scratch",
label: "Declarative Copilot with a plugin using Azure Functions",
detail:
"A declarative Copilot containing a Copilot plugin with a new API from Azure Functions",
};
}
}
Expand Down Expand Up @@ -921,7 +922,7 @@ export function capabilityQuestion(): SingleSelectQuestion {
case ProjectTypeOptions.customCopilot().id:
return getLocalizedString("core.createProjectQuestion.projectType.customCopilot.title");
case ProjectTypeOptions.customizeGpt().id:
return "Choose the GPT type";
return "Choose Declarative Copilot type";
default:
return getLocalizedString("core.createCapabilityQuestion.titleNew");
}
Expand Down Expand Up @@ -1416,23 +1417,6 @@ export function SPFxImportFolderQuestion(hasDefaultFunc = false): FolderQuestion
};
}

function CustomizeGptWithPluginStartQuestion(): SingleSelectQuestion {
return {
name: QuestionNames.CustomizeGptWithPluginStart,
title: getLocalizedString("core.createProjectQuestion.projectType.copilotPlugin.title"),
type: "singleSelect",
staticOptions: GptWithPluginStartOptions(),
cliDescription: "Copilot Plugin.",
placeholder: getLocalizedString(
"core.createProjectQuestion.projectType.copilotPlugin.placeholder"
),
};
}

function GptWithPluginStartOptions(): OptionItem[] {
return [CapabilityOptions.copilotPluginNewApi(), CapabilityOptions.copilotPluginApiSpec()];
}

export function officeAddinHostingQuestion(): SingleSelectQuestion {
return {
name: QuestionNames.OfficeAddinHost,
Expand Down Expand Up @@ -2505,11 +2489,6 @@ export function capabilitySubTree(): IQTreeNode {
},
],
},
// Customize GPT with plugin
{
condition: { equals: CapabilityOptions.customizeGptWithPlugin().id },
data: CustomizeGptWithPluginStartQuestion(),
},
{
// Search ME sub-tree
condition: { equals: CapabilityOptions.m365SearchMe().id },
Expand All @@ -2520,8 +2499,6 @@ export function capabilitySubTree(): IQTreeNode {
condition: (inputs: Inputs) => {
return (
inputs[QuestionNames.Capabilities] === CapabilityOptions.copilotPluginApiSpec().id ||
inputs[QuestionNames.CustomizeGptWithPluginStart] ===
CapabilityOptions.copilotPluginApiSpec().id ||
inputs[QuestionNames.Capabilities] ===
CapabilityOptions.copilotPluginOpenAIPlugin().id ||
inputs[QuestionNames.MeArchitectureType] === MeArchitectureOptions.apiSpec().id
Expand Down Expand Up @@ -2589,8 +2566,6 @@ export function capabilitySubTree(): IQTreeNode {
inputs[QuestionNames.Capabilities] !==
CapabilityOptions.copilotPluginOpenAIPlugin().id &&
inputs[QuestionNames.Capabilities] !== CapabilityOptions.customizeGptBasic().id &&
inputs[QuestionNames.CustomizeGptWithPluginStart] !==
CapabilityOptions.copilotPluginApiSpec().id &&
inputs[QuestionNames.MeArchitectureType] !== MeArchitectureOptions.apiSpec().id &&
inputs[QuestionNames.Capabilities] !== CapabilityOptions.officeAddinImport().id &&
inputs[QuestionNames.Capabilities] !== CapabilityOptions.outlookAddinImport().id
Expand Down
6 changes: 2 additions & 4 deletions packages/fx-core/src/question/inputs/CreateProjectInputs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ export interface CreateProjectInputs extends Inputs {
| "message-extension"
| "BotAndMessageExtension"
| "TabNonSsoAndBot"
| "customize-gpt-basic"
| "customize-gpt-with-plugin"
| "basic-declarative-copilot"
| "declarative-copilot-with-plugin-from-scratch"
| "json-taskpane"
| "office-content-addin"
| "word-taskpane"
Expand Down Expand Up @@ -80,8 +80,6 @@ export interface CreateProjectInputs extends Inputs {
"spfx-webpart-name"?: string;
/** @description SPFx solution folder */
"spfx-folder"?: string;
/** @description Copilot Plugin */
"customize-gpt-with-plugin-start"?: "copilot-plugin-new-api" | "copilot-plugin-existing-api";
/** @description Architecture of Search Based Message Extension */
"me-architecture"?: "new-api" | "api-spec" | "bot-plugin" | "bot";
/** @description OpenAPI Description Document */
Expand Down
10 changes: 2 additions & 8 deletions packages/fx-core/src/question/options/CreateProjectOptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,8 @@ export const CreateProjectOptions: CLICommandOption[] = [
"message-extension",
"BotAndMessageExtension",
"TabNonSsoAndBot",
"customize-gpt-basic",
"customize-gpt-with-plugin",
"basic-declarative-copilot",
"declarative-copilot-with-plugin-from-scratch",
"json-taskpane",
"office-content-addin",
"word-taskpane",
Expand Down Expand Up @@ -122,12 +122,6 @@ export const CreateProjectOptions: CLICommandOption[] = [
type: "string",
description: "Directory or Path that contains the existing SharePoint Framework solution.",
},
{
name: "customize-gpt-with-plugin-start",
type: "string",
description: "Copilot Plugin.",
choices: ["copilot-plugin-new-api", "copilot-plugin-existing-api"],
},
{
name: "me-architecture",
type: "string",
Expand Down
1 change: 0 additions & 1 deletion packages/fx-core/src/question/questionNames.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,6 @@ export enum QuestionNames {

collaborationAppType = "collaborationType",
DestinationApiSpecFilePath = "destination-api-spec-location",
CustomizeGptWithPluginStart = "customize-gpt-with-plugin-start",
}

export enum CliQuestionName {
Expand Down
Loading

0 comments on commit f2bd731

Please sign in to comment.