From be7db5f4da47015184cb4952e543dd1f1d75d74d Mon Sep 17 00:00:00 2001 From: rentu <5545529+SLdragon@users.noreply.github.com> Date: Mon, 30 Sep 2024 10:21:42 +0800 Subject: [PATCH] perf(ai-generator): generate api action for csharp (#12481) Co-authored-by: rentu --- .../src/component/generator/apiSpec/helper.ts | 40 +++++++++++++++++++ .../generator/apiSpecGenerator.test.ts | 15 ++++++- .../OpenAPIClient/OpenAPIClient.cs | 1 - 3 files changed, 53 insertions(+), 3 deletions(-) diff --git a/packages/fx-core/src/component/generator/apiSpec/helper.ts b/packages/fx-core/src/component/generator/apiSpec/helper.ts index 8b64c444a3..6cae3c6821 100644 --- a/packages/fx-core/src/component/generator/apiSpec/helper.ts +++ b/packages/fx-core/src/component/generator/apiSpec/helper.ts @@ -1243,6 +1243,28 @@ async def {{operationId}}( await context.send_activity(message) return "success" `, + cs: ` + [Action("{{actionName}}")] + public async Task {{actionName}}Async([ActionTurnContext] ITurnContext turnContext, [ActionTurnState] TurnState turnState, [ActionParameters] Dictionary args) + { + try + { + RequestParams requestParam = ParseRequestParams(args); + + var response = await Client.CallAsync("{{apiPath}}", Method.{{apiMethod}}, requestParam); + var data = response.Content; + + var cardTemplatePath = "./adaptiveCards/{{operationId}}.json"; + var message = RenderCardToMessage(cardTemplatePath, data); + + await turnContext.SendActivityAsync(message); + } + catch (Exception ex) { + await turnContext.SendActivityAsync("Failed to call API with error: " + ex.Message); + } + + return "complete"; + }`, }; const AuthCode = { @@ -1309,6 +1331,24 @@ async function updateCodeForCustomApi( .replace("{{OPENAPI_SPEC_PATH}}", openapiSpecFileName) .replace("# Replace with action code", actionsCode.join("\n")); await fs.writeFile(botFilePath, updateBotFileContent); + } else if (language === ProgrammingLanguage.CSharp) { + const actionsCode = []; + const codeTemplate = ActionCode["cs"]; + for (const item of specItems) { + const code = codeTemplate + .replace(/{{operationId}}/g, item.item.operationId!) + .replace(/{{apiPath}}/g, item.pathUrl) + .replace(/{{apiMethod}}/g, Utils.updateFirstLetter(item.method)) + .replace(/{{actionName}}/g, Utils.updateFirstLetter(item.item.operationId!)); + actionsCode.push(code); + } + + const apiActionCsFilePath = path.join(destinationPath, "APIActions.cs"); + const apiActionCsFileContent = (await fs.readFile(apiActionCsFilePath)).toString(); + const updateApiActionCsFileContent = apiActionCsFileContent + .replace("{{OPENAPI_SPEC_PATH}}", openapiSpecFileName) + .replace("// Replace with action code", actionsCode.join("\n")); + await fs.writeFile(apiActionCsFilePath, updateApiActionCsFileContent); } } diff --git a/packages/fx-core/tests/component/generator/apiSpecGenerator.test.ts b/packages/fx-core/tests/component/generator/apiSpecGenerator.test.ts index 5c8f1e54f1..bf9a5467a7 100644 --- a/packages/fx-core/tests/component/generator/apiSpecGenerator.test.ts +++ b/packages/fx-core/tests/component/generator/apiSpecGenerator.test.ts @@ -818,9 +818,20 @@ describe("updateForCustomApi", async () => { it("happy path: csharp", async () => { sandbox.stub(fs, "ensureDir").resolves(); - const mockWriteFile = sandbox.stub(fs, "writeFile").resolves(); + sandbox.stub(fs, "writeFile").callsFake((file, data) => { + if (file == path.join("path", "APIActions.cs")) { + expect(data).to.contains(`[Action("GetHello")]`); + expect(data).to.contains(`public async Task GetHelloAsync`); + expect(data).to.contains("openapi.yaml"); + expect(data).not.to.contains("{{"); + expect(data).not.to.contains("# Replace with action code"); + } + }); + + sandbox + .stub(fs, "readFile") + .resolves(Buffer.from("test code // Replace with action code {{OPENAPI_SPEC_PATH}}")); await CopilotPluginHelper.updateForCustomApi(spec, "csharp", "path", "openapi.yaml"); - expect(mockWriteFile.notCalled).to.be.true; }); it("happy path with spec without path", async () => { diff --git a/templates/csharp/custom-copilot-rag-custom-api/OpenAPIClient/OpenAPIClient.cs b/templates/csharp/custom-copilot-rag-custom-api/OpenAPIClient/OpenAPIClient.cs index 039341df1f..bf35d72f21 100644 --- a/templates/csharp/custom-copilot-rag-custom-api/OpenAPIClient/OpenAPIClient.cs +++ b/templates/csharp/custom-copilot-rag-custom-api/OpenAPIClient/OpenAPIClient.cs @@ -2,7 +2,6 @@ using System.Text.Json; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Readers; -using rentu_vs_ai_bot_test; using RestSharp.Authenticators; namespace OpenAPIClient