Skip to content

Commit

Permalink
perf(spec-parser): add type b conversation starter (#11329)
Browse files Browse the repository at this point in the history
* perf(spec-parser): add type b conversation starter

* perf: update test case to cover more code

* perf: add test case to make codecov happy

* perf: update

---------

Co-authored-by: turenlong <rentu@microsoft.com>
  • Loading branch information
SLdragon and SLdragon authored Apr 10, 2024
1 parent 5fc8cea commit ab62b2e
Show file tree
Hide file tree
Showing 6 changed files with 482 additions and 87 deletions.
5 changes: 5 additions & 0 deletions packages/spec-parser/src/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,11 @@ export interface ParseOptions {
*/
allowMethods?: string[];

/**
* If true, the parser will allow conversation starters in plugin file. Only take effect in Copilot project
*/
allowConversationStarters?: boolean;

/**
* The type of project that the parser is being used for.
* Project can be SME/Copilot/TeamsAi
Expand Down
17 changes: 17 additions & 0 deletions packages/spec-parser/src/manifestUpdater.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ export class ManifestUpdater {
): Promise<PluginManifestSchema> {
const functions: FunctionObject[] = [];
const functionNames: string[] = [];
const conversationStarters: string[] = [];

const paths = spec.paths;

Expand Down Expand Up @@ -184,6 +185,9 @@ export class ManifestUpdater {

functions.push(funcObj);
functionNames.push(operationId);
if (description) {
conversationStarters.push(description);
}
}
}
}
Expand Down Expand Up @@ -240,6 +244,19 @@ export class ManifestUpdater {
spec.info.description ?? "<Please add description of the plugin>";
}

if (options.allowConversationStarters && conversationStarters.length > 0) {
if (!apiPlugin.capabilities) {
apiPlugin.capabilities = {
localization: {},
};
}
if (!apiPlugin.capabilities.conversation_starters) {
apiPlugin.capabilities.conversation_starters = conversationStarters
.slice(0, 5)
.map((text) => ({ text }));
}
}

return apiPlugin;
}

Expand Down
7 changes: 1 addition & 6 deletions packages/spec-parser/src/specParser.browser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import {
ListAPIResult,
ProjectType,
APIMap,
WarningType,
ErrorResult,
WarningResult,
} from "./interfaces";
Expand All @@ -32,7 +31,6 @@ export class SpecParser {
public readonly parser: SwaggerParser;
public readonly options: Required<ParseOptions>;

private apiMap: APIMap | undefined;
private spec: OpenAPIV3.Document | undefined;
private validator: Validator | undefined;
private unResolveSpec: OpenAPIV3.Document | undefined;
Expand All @@ -46,6 +44,7 @@ export class SpecParser {
allowBearerTokenAuth: false,
allowOauth2: false,
allowMethods: ["get", "post"],
allowConversationStarters: false,
projectType: ProjectType.SME,
};

Expand Down Expand Up @@ -242,12 +241,8 @@ export class SpecParser {
}

private getAPIs(spec: OpenAPIV3.Document): APIMap {
if (this.apiMap !== undefined) {
return this.apiMap;
}
const validator = this.getValidator(spec);
const apiMap = validator.listAPIs();
this.apiMap = apiMap;
return apiMap;
}

Expand Down
3 changes: 1 addition & 2 deletions packages/spec-parser/src/specParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ export class SpecParser {
public readonly parser: SwaggerParser;
public readonly options: Required<ParseOptions>;

private apiMap: APIMap | undefined;
private validator: Validator | undefined;
private spec: OpenAPIV3.Document | undefined;
private unResolveSpec: OpenAPIV3.Document | undefined;
Expand All @@ -56,6 +55,7 @@ export class SpecParser {
allowMultipleParameters: false,
allowOauth2: false,
allowMethods: ["get", "post"],
allowConversationStarters: false,
projectType: ProjectType.SME,
};

Expand Down Expand Up @@ -437,7 +437,6 @@ export class SpecParser {
private getAPIs(spec: OpenAPIV3.Document): APIMap {
const validator = this.getValidator(spec);
const apiMap = validator.listAPIs();
this.apiMap = apiMap;
return apiMap;
}

Expand Down
79 changes: 0 additions & 79 deletions packages/spec-parser/test/browser/specParser.browser.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -192,85 +192,6 @@ describe("SpecParser in Browser", () => {
]);
});

it("should reuse apiMap if listSupportedAPIInfo is called multiple times", async () => {
const specPath = "valid-spec.yaml";
const specParser = new SpecParser(specPath, { allowMissingId: false });
const spec = {
servers: [
{
url: "https://example.com",
},
],
paths: {
"/user/{userId}": {
get: {
operationId: "getUserById",
description: "Get user by user id, balabala",
summary: "Get user by user id",
parameters: [
{
name: "userId",
in: "path",
description: "User Id",
schema: {
type: "string",
},
},
],
responses: {
200: {
content: {
"application/json": {
schema: {
type: "object",
properties: {
name: {
type: "string",
},
},
},
},
},
},
},
},
post: {
operationId: "createUser",
security: [{ api_key: [] }],
},
},
"/store/order": {
post: {
operationId: "placeOrder",
},
},
},
};

const parseStub = sinon.stub(specParser.parser, "parse").resolves(spec as any);
const dereferenceStub = sinon.stub(specParser.parser, "dereference").resolves(spec as any);
const listAPIsSyp = sinon.spy(SMEValidator.prototype, "listAPIs");
let result = await specParser.listSupportedAPIInfo();
result = await specParser.listSupportedAPIInfo();
expect(result).to.deep.equal([
{
method: "GET",
path: "/user/{userId}",
title: "Get user by user id",
id: "getUserById",
parameters: [
{
name: "userId",
title: "UserId",
description: "User Id",
},
],
description: "Get user by user id, balabala",
},
]);
expect(listAPIsSyp.callCount).to.equal(1);
});

it("should not list api without operationId with allowMissingId is true", async () => {
const specPath = "valid-spec.yaml";
const specParser = new SpecParser(specPath, { allowMissingId: true });
Expand Down
Loading

0 comments on commit ab62b2e

Please sign in to comment.