diff --git a/Elsa.SemanticKernel/Config/KernelConfigExtensions.cs b/Elsa.SemanticKernel/Config/KernelConfigExtensions.cs
deleted file mode 100644
index 92b8392ef..000000000
--- a/Elsa.SemanticKernel/Config/KernelConfigExtensions.cs
+++ /dev/null
@@ -1,27 +0,0 @@
-using Microsoft.SemanticKernel;
-
-internal static class KernelConfigExtensions
-{
- ///
- /// Adds a text completion service to the list. It can be either an OpenAI or Azure OpenAI backend service.
- ///
- ///
- ///
- ///
- internal static void AddCompletionBackend(this KernelConfig kernelConfig, KernelSettings kernelSettings)
- {
- switch (kernelSettings.ServiceType.ToUpperInvariant())
- {
- case KernelSettings.AzureOpenAI:
- kernelConfig.AddAzureChatCompletionService(kernelSettings.DeploymentOrModelId, kernelSettings.Endpoint, kernelSettings.ApiKey);
- break;
-
- case KernelSettings.OpenAI:
- kernelConfig.AddOpenAITextCompletionService(modelId: kernelSettings.DeploymentOrModelId, apiKey: kernelSettings.ApiKey, orgId: kernelSettings.OrgId, serviceId: kernelSettings.ServiceId);
- break;
-
- default:
- throw new System.Exception($"Invalid service type value: {kernelSettings.ServiceType}");
- }
- }
-}
diff --git a/azure.yaml b/azure.yaml
index cf9b6d9db..f56fac572 100644
--- a/azure.yaml
+++ b/azure.yaml
@@ -3,6 +3,6 @@
name: sk-dev-team
services:
sk-func:
- project: ./sk-azfunc-server
+ project: ./src/apps/gh-flow-df
language: dotnet
host: function
\ No newline at end of file
diff --git a/sk-dev-team.sln b/sk-dev-team.sln
index 1ca548760..42943545f 100644
--- a/sk-dev-team.sln
+++ b/sk-dev-team.sln
@@ -3,39 +3,29 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.5.001.0
MinimumVisualStudioVersion = 10.0.40219.1
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "sk-csharp-azure-functions", "sk-azfunc-server\sk-csharp-azure-functions.csproj", "{C787026C-9435-4FD4-AEE5-B005EAEF9E3D}"
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{088E1138-FF7B-4179-AD37-4E3819C56D7E}"
EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "skills", "skills\skills.csproj", "{51F987E4-3E70-4DB9-9493-AFCFA0CE3773}"
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "apps", "apps", "{4D8667EC-09BE-4CB1-A278-E1CCD83B62B0}"
EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "cli", "cli\cli.csproj", "{C0073CEA-8A1B-43BC-BADE-F6323CDFA853}"
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "cli", "src\apps\cli\cli.csproj", "{1FE4A9AE-6403-48D6-8D06-A97CCCE608FA}"
EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "util", "util", "{16A0621E-E1B8-4737-9B3D-08EB9CEF87B0}"
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "gh-flow", "src\apps\gh-flow\gh-flow.csproj", "{37C45587-DD0C-4BFE-817A-21301567A94A}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "seed-memory", "util\seed-memory\seed-memory.csproj", "{94C4BF5F-50BF-41CF-8B94-11F39CA430FA}"
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "gh-flow-df", "src\apps\gh-flow-df\gh-flow-df.csproj", "{CF0F7B0D-3CC4-4068-A1A8-64E3151D01E3}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "seed-memory", "src\apps\seed-memory\seed-memory.csproj", "{110B2C34-0F48-41CE-BC8F-AE3D24E79627}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WorkflowsApp", "src\apps\WorkflowsApp\WorkflowsApp.csproj", "{F288CF45-81EF-4F57-ABAC-D7ABE894E7A0}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "libs", "libs", "{24EB6E3A-C080-4B27-8EA7-F6C91446B840}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.SemanticKernel", "src\libs\Elsa.SemanticKernel\Elsa.SemanticKernel.csproj", "{1F6EE104-0B3F-49C1-BE3B-B93CAD18BAD0}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MS.AI.DevTeam", "src\libs\MS.AI.DevTeam\MS.AI.DevTeam.csproj", "{A064E523-718C-4464-B8AD-BC00BF2E358A}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "skills", "src\libs\skills\skills.csproj", "{3EAFB48F-FBF5-4362-8696-976D7E1EA309}"
EndProject
Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|Any CPU = Debug|Any CPU
- Release|Any CPU = Release|Any CPU
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {C787026C-9435-4FD4-AEE5-B005EAEF9E3D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {C787026C-9435-4FD4-AEE5-B005EAEF9E3D}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {C787026C-9435-4FD4-AEE5-B005EAEF9E3D}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {C787026C-9435-4FD4-AEE5-B005EAEF9E3D}.Release|Any CPU.Build.0 = Release|Any CPU
- {51F987E4-3E70-4DB9-9493-AFCFA0CE3773}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {51F987E4-3E70-4DB9-9493-AFCFA0CE3773}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {51F987E4-3E70-4DB9-9493-AFCFA0CE3773}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {51F987E4-3E70-4DB9-9493-AFCFA0CE3773}.Release|Any CPU.Build.0 = Release|Any CPU
- {C0073CEA-8A1B-43BC-BADE-F6323CDFA853}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {C0073CEA-8A1B-43BC-BADE-F6323CDFA853}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {C0073CEA-8A1B-43BC-BADE-F6323CDFA853}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {C0073CEA-8A1B-43BC-BADE-F6323CDFA853}.Release|Any CPU.Build.0 = Release|Any CPU
- {94C4BF5F-50BF-41CF-8B94-11F39CA430FA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {94C4BF5F-50BF-41CF-8B94-11F39CA430FA}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {94C4BF5F-50BF-41CF-8B94-11F39CA430FA}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {94C4BF5F-50BF-41CF-8B94-11F39CA430FA}.Release|Any CPU.Build.0 = Release|Any CPU
- EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
@@ -43,6 +33,121 @@ Global
SolutionGuid = {30612385-E4F4-4FD9-B648-45AF74CB4915}
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
- {94C4BF5F-50BF-41CF-8B94-11F39CA430FA} = {16A0621E-E1B8-4737-9B3D-08EB9CEF87B0}
+ {4D8667EC-09BE-4CB1-A278-E1CCD83B62B0} = {088E1138-FF7B-4179-AD37-4E3819C56D7E}
+ {1FE4A9AE-6403-48D6-8D06-A97CCCE608FA} = {4D8667EC-09BE-4CB1-A278-E1CCD83B62B0}
+ {37C45587-DD0C-4BFE-817A-21301567A94A} = {4D8667EC-09BE-4CB1-A278-E1CCD83B62B0}
+ {CF0F7B0D-3CC4-4068-A1A8-64E3151D01E3} = {4D8667EC-09BE-4CB1-A278-E1CCD83B62B0}
+ {110B2C34-0F48-41CE-BC8F-AE3D24E79627} = {4D8667EC-09BE-4CB1-A278-E1CCD83B62B0}
+ {F288CF45-81EF-4F57-ABAC-D7ABE894E7A0} = {4D8667EC-09BE-4CB1-A278-E1CCD83B62B0}
+ {24EB6E3A-C080-4B27-8EA7-F6C91446B840} = {088E1138-FF7B-4179-AD37-4E3819C56D7E}
+ {1F6EE104-0B3F-49C1-BE3B-B93CAD18BAD0} = {24EB6E3A-C080-4B27-8EA7-F6C91446B840}
+ {A064E523-718C-4464-B8AD-BC00BF2E358A} = {24EB6E3A-C080-4B27-8EA7-F6C91446B840}
+ {3EAFB48F-FBF5-4362-8696-976D7E1EA309} = {088E1138-FF7B-4179-AD37-4E3819C56D7E}
+ EndGlobalSection
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|Any CPU = Release|Any CPU
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {1FE4A9AE-6403-48D6-8D06-A97CCCE608FA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {1FE4A9AE-6403-48D6-8D06-A97CCCE608FA}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {1FE4A9AE-6403-48D6-8D06-A97CCCE608FA}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {1FE4A9AE-6403-48D6-8D06-A97CCCE608FA}.Debug|x64.Build.0 = Debug|Any CPU
+ {1FE4A9AE-6403-48D6-8D06-A97CCCE608FA}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {1FE4A9AE-6403-48D6-8D06-A97CCCE608FA}.Debug|x86.Build.0 = Debug|Any CPU
+ {1FE4A9AE-6403-48D6-8D06-A97CCCE608FA}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {1FE4A9AE-6403-48D6-8D06-A97CCCE608FA}.Release|Any CPU.Build.0 = Release|Any CPU
+ {1FE4A9AE-6403-48D6-8D06-A97CCCE608FA}.Release|x64.ActiveCfg = Release|Any CPU
+ {1FE4A9AE-6403-48D6-8D06-A97CCCE608FA}.Release|x64.Build.0 = Release|Any CPU
+ {1FE4A9AE-6403-48D6-8D06-A97CCCE608FA}.Release|x86.ActiveCfg = Release|Any CPU
+ {1FE4A9AE-6403-48D6-8D06-A97CCCE608FA}.Release|x86.Build.0 = Release|Any CPU
+ {37C45587-DD0C-4BFE-817A-21301567A94A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {37C45587-DD0C-4BFE-817A-21301567A94A}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {37C45587-DD0C-4BFE-817A-21301567A94A}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {37C45587-DD0C-4BFE-817A-21301567A94A}.Debug|x64.Build.0 = Debug|Any CPU
+ {37C45587-DD0C-4BFE-817A-21301567A94A}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {37C45587-DD0C-4BFE-817A-21301567A94A}.Debug|x86.Build.0 = Debug|Any CPU
+ {37C45587-DD0C-4BFE-817A-21301567A94A}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {37C45587-DD0C-4BFE-817A-21301567A94A}.Release|Any CPU.Build.0 = Release|Any CPU
+ {37C45587-DD0C-4BFE-817A-21301567A94A}.Release|x64.ActiveCfg = Release|Any CPU
+ {37C45587-DD0C-4BFE-817A-21301567A94A}.Release|x64.Build.0 = Release|Any CPU
+ {37C45587-DD0C-4BFE-817A-21301567A94A}.Release|x86.ActiveCfg = Release|Any CPU
+ {37C45587-DD0C-4BFE-817A-21301567A94A}.Release|x86.Build.0 = Release|Any CPU
+ {CF0F7B0D-3CC4-4068-A1A8-64E3151D01E3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {CF0F7B0D-3CC4-4068-A1A8-64E3151D01E3}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {CF0F7B0D-3CC4-4068-A1A8-64E3151D01E3}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {CF0F7B0D-3CC4-4068-A1A8-64E3151D01E3}.Debug|x64.Build.0 = Debug|Any CPU
+ {CF0F7B0D-3CC4-4068-A1A8-64E3151D01E3}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {CF0F7B0D-3CC4-4068-A1A8-64E3151D01E3}.Debug|x86.Build.0 = Debug|Any CPU
+ {CF0F7B0D-3CC4-4068-A1A8-64E3151D01E3}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {CF0F7B0D-3CC4-4068-A1A8-64E3151D01E3}.Release|Any CPU.Build.0 = Release|Any CPU
+ {CF0F7B0D-3CC4-4068-A1A8-64E3151D01E3}.Release|x64.ActiveCfg = Release|Any CPU
+ {CF0F7B0D-3CC4-4068-A1A8-64E3151D01E3}.Release|x64.Build.0 = Release|Any CPU
+ {CF0F7B0D-3CC4-4068-A1A8-64E3151D01E3}.Release|x86.ActiveCfg = Release|Any CPU
+ {CF0F7B0D-3CC4-4068-A1A8-64E3151D01E3}.Release|x86.Build.0 = Release|Any CPU
+ {110B2C34-0F48-41CE-BC8F-AE3D24E79627}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {110B2C34-0F48-41CE-BC8F-AE3D24E79627}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {110B2C34-0F48-41CE-BC8F-AE3D24E79627}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {110B2C34-0F48-41CE-BC8F-AE3D24E79627}.Debug|x64.Build.0 = Debug|Any CPU
+ {110B2C34-0F48-41CE-BC8F-AE3D24E79627}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {110B2C34-0F48-41CE-BC8F-AE3D24E79627}.Debug|x86.Build.0 = Debug|Any CPU
+ {110B2C34-0F48-41CE-BC8F-AE3D24E79627}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {110B2C34-0F48-41CE-BC8F-AE3D24E79627}.Release|Any CPU.Build.0 = Release|Any CPU
+ {110B2C34-0F48-41CE-BC8F-AE3D24E79627}.Release|x64.ActiveCfg = Release|Any CPU
+ {110B2C34-0F48-41CE-BC8F-AE3D24E79627}.Release|x64.Build.0 = Release|Any CPU
+ {110B2C34-0F48-41CE-BC8F-AE3D24E79627}.Release|x86.ActiveCfg = Release|Any CPU
+ {110B2C34-0F48-41CE-BC8F-AE3D24E79627}.Release|x86.Build.0 = Release|Any CPU
+ {F288CF45-81EF-4F57-ABAC-D7ABE894E7A0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {F288CF45-81EF-4F57-ABAC-D7ABE894E7A0}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {F288CF45-81EF-4F57-ABAC-D7ABE894E7A0}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {F288CF45-81EF-4F57-ABAC-D7ABE894E7A0}.Debug|x64.Build.0 = Debug|Any CPU
+ {F288CF45-81EF-4F57-ABAC-D7ABE894E7A0}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {F288CF45-81EF-4F57-ABAC-D7ABE894E7A0}.Debug|x86.Build.0 = Debug|Any CPU
+ {F288CF45-81EF-4F57-ABAC-D7ABE894E7A0}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {F288CF45-81EF-4F57-ABAC-D7ABE894E7A0}.Release|Any CPU.Build.0 = Release|Any CPU
+ {F288CF45-81EF-4F57-ABAC-D7ABE894E7A0}.Release|x64.ActiveCfg = Release|Any CPU
+ {F288CF45-81EF-4F57-ABAC-D7ABE894E7A0}.Release|x64.Build.0 = Release|Any CPU
+ {F288CF45-81EF-4F57-ABAC-D7ABE894E7A0}.Release|x86.ActiveCfg = Release|Any CPU
+ {F288CF45-81EF-4F57-ABAC-D7ABE894E7A0}.Release|x86.Build.0 = Release|Any CPU
+ {1F6EE104-0B3F-49C1-BE3B-B93CAD18BAD0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {1F6EE104-0B3F-49C1-BE3B-B93CAD18BAD0}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {1F6EE104-0B3F-49C1-BE3B-B93CAD18BAD0}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {1F6EE104-0B3F-49C1-BE3B-B93CAD18BAD0}.Debug|x64.Build.0 = Debug|Any CPU
+ {1F6EE104-0B3F-49C1-BE3B-B93CAD18BAD0}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {1F6EE104-0B3F-49C1-BE3B-B93CAD18BAD0}.Debug|x86.Build.0 = Debug|Any CPU
+ {1F6EE104-0B3F-49C1-BE3B-B93CAD18BAD0}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {1F6EE104-0B3F-49C1-BE3B-B93CAD18BAD0}.Release|Any CPU.Build.0 = Release|Any CPU
+ {1F6EE104-0B3F-49C1-BE3B-B93CAD18BAD0}.Release|x64.ActiveCfg = Release|Any CPU
+ {1F6EE104-0B3F-49C1-BE3B-B93CAD18BAD0}.Release|x64.Build.0 = Release|Any CPU
+ {1F6EE104-0B3F-49C1-BE3B-B93CAD18BAD0}.Release|x86.ActiveCfg = Release|Any CPU
+ {1F6EE104-0B3F-49C1-BE3B-B93CAD18BAD0}.Release|x86.Build.0 = Release|Any CPU
+ {A064E523-718C-4464-B8AD-BC00BF2E358A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {A064E523-718C-4464-B8AD-BC00BF2E358A}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {A064E523-718C-4464-B8AD-BC00BF2E358A}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {A064E523-718C-4464-B8AD-BC00BF2E358A}.Debug|x64.Build.0 = Debug|Any CPU
+ {A064E523-718C-4464-B8AD-BC00BF2E358A}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {A064E523-718C-4464-B8AD-BC00BF2E358A}.Debug|x86.Build.0 = Debug|Any CPU
+ {A064E523-718C-4464-B8AD-BC00BF2E358A}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {A064E523-718C-4464-B8AD-BC00BF2E358A}.Release|Any CPU.Build.0 = Release|Any CPU
+ {A064E523-718C-4464-B8AD-BC00BF2E358A}.Release|x64.ActiveCfg = Release|Any CPU
+ {A064E523-718C-4464-B8AD-BC00BF2E358A}.Release|x64.Build.0 = Release|Any CPU
+ {A064E523-718C-4464-B8AD-BC00BF2E358A}.Release|x86.ActiveCfg = Release|Any CPU
+ {A064E523-718C-4464-B8AD-BC00BF2E358A}.Release|x86.Build.0 = Release|Any CPU
+ {3EAFB48F-FBF5-4362-8696-976D7E1EA309}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {3EAFB48F-FBF5-4362-8696-976D7E1EA309}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {3EAFB48F-FBF5-4362-8696-976D7E1EA309}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {3EAFB48F-FBF5-4362-8696-976D7E1EA309}.Debug|x64.Build.0 = Debug|Any CPU
+ {3EAFB48F-FBF5-4362-8696-976D7E1EA309}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {3EAFB48F-FBF5-4362-8696-976D7E1EA309}.Debug|x86.Build.0 = Debug|Any CPU
+ {3EAFB48F-FBF5-4362-8696-976D7E1EA309}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {3EAFB48F-FBF5-4362-8696-976D7E1EA309}.Release|Any CPU.Build.0 = Release|Any CPU
+ {3EAFB48F-FBF5-4362-8696-976D7E1EA309}.Release|x64.ActiveCfg = Release|Any CPU
+ {3EAFB48F-FBF5-4362-8696-976D7E1EA309}.Release|x64.Build.0 = Release|Any CPU
+ {3EAFB48F-FBF5-4362-8696-976D7E1EA309}.Release|x86.ActiveCfg = Release|Any CPU
+ {3EAFB48F-FBF5-4362-8696-976D7E1EA309}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal
diff --git a/WorkflowsApp/.env_example b/src/apps/WorkflowsApp/.env_example
similarity index 100%
rename from WorkflowsApp/.env_example
rename to src/apps/WorkflowsApp/.env_example
diff --git a/Elsa.SemanticKernel/NuGet.Config b/src/apps/WorkflowsApp/NuGet.Config
similarity index 76%
rename from Elsa.SemanticKernel/NuGet.Config
rename to src/apps/WorkflowsApp/NuGet.Config
index 5d2144320..a89a1e8b5 100644
--- a/Elsa.SemanticKernel/NuGet.Config
+++ b/src/apps/WorkflowsApp/NuGet.Config
@@ -3,7 +3,7 @@
-
+
diff --git a/WorkflowsApp/Pages/Index.cshtml b/src/apps/WorkflowsApp/Pages/Index.cshtml
similarity index 100%
rename from WorkflowsApp/Pages/Index.cshtml
rename to src/apps/WorkflowsApp/Pages/Index.cshtml
diff --git a/WorkflowsApp/Pages/_ViewImports.cshtml b/src/apps/WorkflowsApp/Pages/_ViewImports.cshtml
similarity index 100%
rename from WorkflowsApp/Pages/_ViewImports.cshtml
rename to src/apps/WorkflowsApp/Pages/_ViewImports.cshtml
diff --git a/WorkflowsApp/Program.cs b/src/apps/WorkflowsApp/Program.cs
similarity index 100%
rename from WorkflowsApp/Program.cs
rename to src/apps/WorkflowsApp/Program.cs
diff --git a/WorkflowsApp/Properties/launchSettings.json b/src/apps/WorkflowsApp/Properties/launchSettings.json
similarity index 100%
rename from WorkflowsApp/Properties/launchSettings.json
rename to src/apps/WorkflowsApp/Properties/launchSettings.json
diff --git a/WorkflowsApp/WorkflowsApp.csproj b/src/apps/WorkflowsApp/WorkflowsApp.csproj
similarity index 78%
rename from WorkflowsApp/WorkflowsApp.csproj
rename to src/apps/WorkflowsApp/WorkflowsApp.csproj
index 240d57ef4..413793f84 100644
--- a/WorkflowsApp/WorkflowsApp.csproj
+++ b/src/apps/WorkflowsApp/WorkflowsApp.csproj
@@ -7,13 +7,13 @@
-
-
-
-
-
-
-
+
diff --git a/src/libs/MS.AI.DevTeam/Actors/Architect/Architect.cs b/src/libs/MS.AI.DevTeam/Actors/Architect/Architect.cs
new file mode 100644
index 000000000..f12d90fe5
--- /dev/null
+++ b/src/libs/MS.AI.DevTeam/Actors/Architect/Architect.cs
@@ -0,0 +1,26 @@
+using Orleans.Runtime;
+
+namespace MS.AI.DevTeam;
+
+public class Architect : SemanticPersona, IArchitectSolutions
+{
+ public Architect( [PersistentState("state", "messages")]IPersistentState state) : base(state)
+ {
+
+ }
+ public Task GenerateProjectStructure(string ask)
+ {
+ throw new NotImplementedException();
+ }
+
+ public Task ReviewPlan(string plan)
+ {
+ throw new NotImplementedException();
+ }
+}
+
+public interface IArchitectSolutions : IGrainWithIntegerCompoundKey
+{
+ Task ReviewPlan(string plan);
+ Task GenerateProjectStructure(string ask);
+}
\ No newline at end of file
diff --git a/src/libs/MS.AI.DevTeam/Actors/Conductor/Conductor.cs b/src/libs/MS.AI.DevTeam/Actors/Conductor/Conductor.cs
new file mode 100644
index 000000000..cae93b2ca
--- /dev/null
+++ b/src/libs/MS.AI.DevTeam/Actors/Conductor/Conductor.cs
@@ -0,0 +1,88 @@
+using Orleans.Concurrency;
+using Orleans.Runtime;
+
+namespace MS.AI.DevTeam;
+
+public class Conductor : Grain, IOrchestrateWorkflows
+{
+ private readonly IManageGithub _ghService;
+ public Conductor( IManageGithub ghService)
+ {
+ _ghService = ghService;
+ }
+ public async Task InitialFlow(string input, string org, string repo, long parentNumber)
+ {
+ await _ghService.CreateBranch(new CreateBranchRequest
+ {
+ Org = org,
+ Repo = repo,
+ Branch = $"sk-{parentNumber}"
+ });
+
+ var pmIssue = await _ghService.CreateIssue(new CreateIssueRequest
+ {
+ Label = $"{nameof(PM)}.{nameof(PM.Readme)}",
+ Org = org,
+ Repo = repo,
+ Input = input,
+ ParentNumber = parentNumber
+ });
+ var devLeadIssue = await _ghService.CreateIssue(new CreateIssueRequest
+ {
+ Label = $"{nameof(DevLead)}.{nameof(DevLead.Plan)}",
+ Org = org,
+ Repo = repo,
+ Input = input,
+ ParentNumber = parentNumber
+ });
+ var suffix = $"{org}-{repo}";
+ var pm = GrainFactory.GetGrain(pmIssue.IssueNumber, suffix);
+ var devLead = GrainFactory.GetGrain(devLeadIssue.IssueNumber, suffix);
+ var lookup = GrainFactory.GetGrain(suffix);
+
+ var metadataList = new List{
+ new StoreMetadataPairs
+ {
+ Key = pmIssue.IssueNumber,
+ Value = new NewIssueResponse { CommentId = pmIssue.CommentId, IssueNumber = (int)parentNumber}
+ },
+ new StoreMetadataPairs
+ {
+ Key = devLeadIssue.IssueNumber,
+ Value = new NewIssueResponse { CommentId = devLeadIssue.CommentId, IssueNumber = (int)parentNumber}
+ }
+ };
+ await lookup.StoreMetadata(metadataList);
+
+ // await githubActor.CreatePR(); // TODO: this should happen when all tasks are done?
+ }
+ public async Task ImplementationFlow(DevLeadPlanResponse plan, string org, string repo, int parentNumber)
+ {
+ var suffix = $"{org}-{repo}";
+ var prompts = plan.steps.SelectMany(s => s.subtasks.Select(st => st.prompt));
+ var lookup = GrainFactory.GetGrain(suffix);
+ var metadataList = new List();
+ foreach(var prompt in prompts)
+ {
+ var issue = await _ghService.CreateIssue(new CreateIssueRequest
+ {
+ Label = $"{nameof(Dev)}.{nameof(Dev.Implement)}",
+ Org = org,
+ Repo = repo,
+ Input = prompt,
+ ParentNumber = parentNumber
+ });
+ metadataList.Add(new StoreMetadataPairs
+ {
+ Key = issue.IssueNumber,
+ Value = new NewIssueResponse { CommentId = issue.CommentId, IssueNumber = (int)parentNumber}
+ });
+ }
+ await lookup.StoreMetadata(metadataList);
+ }
+
+ public Task ScheduleCommitSandboxRun(CommitRequest commitRequest, MarkTaskCompleteRequest markTaskCompleteRequest)
+ {
+ throw new NotImplementedException();
+ }
+}
diff --git a/src/libs/MS.AI.DevTeam/Actors/Conductor/IOrchestrateWorkflows.cs b/src/libs/MS.AI.DevTeam/Actors/Conductor/IOrchestrateWorkflows.cs
new file mode 100644
index 000000000..b23349310
--- /dev/null
+++ b/src/libs/MS.AI.DevTeam/Actors/Conductor/IOrchestrateWorkflows.cs
@@ -0,0 +1,11 @@
+using Orleans.Concurrency;
+
+namespace MS.AI.DevTeam;
+
+public interface IOrchestrateWorkflows : IGrainWithIntegerCompoundKey
+{
+ [OneWay]
+ Task InitialFlow(string input, string org, string repo, long parentNumber);
+ [OneWay]
+ Task ImplementationFlow(DevLeadPlanResponse plan, string org, string repo, int parentNumber);
+}
\ No newline at end of file
diff --git a/src/libs/MS.AI.DevTeam/Actors/DevLead/DevLead.cs b/src/libs/MS.AI.DevTeam/Actors/DevLead/DevLead.cs
new file mode 100644
index 000000000..8563a21b8
--- /dev/null
+++ b/src/libs/MS.AI.DevTeam/Actors/DevLead/DevLead.cs
@@ -0,0 +1,47 @@
+namespace MS.AI.DevTeam;
+
+public static class DevLead {
+ public static SemanticFunctionConfig Plan = new SemanticFunctionConfig
+ {
+ PromptTemplate = """
+ You are a Dev Lead for an application team, building the application described below.
+ Please break down the steps and modules required to develop the complete application, describe each step in detail.
+ Make prescriptive architecture, language, and frameowrk choices, do not provide a range of choices.
+ For each step or module then break down the steps or subtasks required to complete that step or module.
+ For each subtask write an LLM prompt that would be used to tell a model to write the coee that will accomplish that subtask. If the subtask involves taking action/running commands tell the model to write the script that will run those commands.
+ In each LLM prompt restrict the model from outputting other text that is not in the form of code or code comments.
+ Please output a JSON array data structure, in the precise schema shown below, with a list of steps and a description of each step, and the steps or subtasks that each requires, and the LLM prompts for each subtask.
+ Example:
+ {
+ "steps": [
+ {
+ "step": "1",
+ "description": "This is the first step",
+ "subtasks": [
+ {
+ "subtask": "Subtask 1",
+ "description": "This is the first subtask",
+ "prompt": "Write the code to do the first subtask"
+ },
+ {
+ "subtask": "Subtask 2",
+ "description": "This is the second subtask",
+ "prompt": "Write the code to do the second subtask"
+ }
+ ]
+ }
+ ]
+ }
+ Do not output any other text.
+ Input: {{$input}}
+ """,
+ Name = nameof(Plan),
+ SkillName = nameof(DevLead),
+ Description = "From a simple description of an application output a development plan for building the application.",
+ MaxTokens = 6500,
+ Temperature = 0.0,
+ TopP = 0.0,
+ PPenalty = 0.0,
+ FPenalty = 0.0
+ };
+}
\ No newline at end of file
diff --git a/src/libs/MS.AI.DevTeam/Actors/DevLead/DeveloperLead.cs b/src/libs/MS.AI.DevTeam/Actors/DevLead/DeveloperLead.cs
new file mode 100644
index 000000000..033187aa8
--- /dev/null
+++ b/src/libs/MS.AI.DevTeam/Actors/DevLead/DeveloperLead.cs
@@ -0,0 +1,86 @@
+using Microsoft.SemanticKernel;
+using Microsoft.SemanticKernel.Orchestration;
+using Orleans.Runtime;
+using System.Text.Json;
+
+namespace MS.AI.DevTeam;
+public class DeveloperLead : SemanticPersona, ILeadDevelopment
+{
+ private readonly IKernel _kernel;
+ protected override string MemorySegment => "dev-lead-memory";
+
+ public DeveloperLead(IKernel kernel, [PersistentState("state", "messages")] IPersistentState state) : base(state)
+ {
+ _kernel = kernel;
+ }
+ public async Task CreatePlan(string ask)
+ {
+ // var architectId = Guid.NewGuid();
+ // var plan = "this is my plan";
+ // var architect = GrainFactory.GetGrain(architectId);
+ // var review = architect.ReviewPlan(plan);
+ // return Task.FromResult(plan);
+
+ var function = _kernel.LoadFunction(nameof(DevLead), nameof(DevLead.Plan));
+ var context = new ContextVariables();
+ context.Set("input", ask);
+ if (_state.State.History == null) _state.State.History = new List();
+ _state.State.History.Add(new ChatHistoryItem
+ {
+ Message = ask,
+ Order = _state.State.History.Count + 1,
+ UserType = ChatUserType.User
+ });
+ context.Set("input", ask);
+
+ var result = await _kernel.RunAsync(context, function);
+ var resultMessage = result.ToString();
+ _state.State.History.Add(new ChatHistoryItem
+ {
+ Message = resultMessage,
+ Order = _state.State.History.Count + 1,
+ UserType = ChatUserType.Agent
+ });
+ await _state.WriteStateAsync();
+
+ return resultMessage;
+ }
+
+ public Task GetLatestPlan()
+ {
+ var plan = _state.State.History.Last().Message;
+ var response = JsonSerializer.Deserialize(plan);
+ return Task.FromResult(response);
+ }
+}
+
+[GenerateSerializer]
+public class DevLeadPlanResponse
+{
+ [Id(0)]
+ public List steps { get; set; }
+}
+
+[GenerateSerializer]
+public class Step
+{
+ [Id(0)]
+ public string description { get; set; }
+ [Id(1)]
+ public string step { get; set; }
+ [Id(2)]
+ public List subtasks { get; set; }
+}
+
+[GenerateSerializer]
+public class Subtask
+{
+ [Id(0)]
+ public string subtask { get; set; }
+ [Id(1)]
+ public string prompt { get; set; }
+}
+
+
+
+
diff --git a/src/libs/MS.AI.DevTeam/Actors/DevLead/ILeadDevelopment.cs b/src/libs/MS.AI.DevTeam/Actors/DevLead/ILeadDevelopment.cs
new file mode 100644
index 000000000..18cf4f324
--- /dev/null
+++ b/src/libs/MS.AI.DevTeam/Actors/DevLead/ILeadDevelopment.cs
@@ -0,0 +1,7 @@
+namespace MS.AI.DevTeam;
+
+public interface ILeadDevelopment: IGrainWithIntegerCompoundKey, IChatHistory
+{
+ Task CreatePlan(string ask);
+ Task GetLatestPlan();
+}
\ No newline at end of file
diff --git a/src/libs/MS.AI.DevTeam/Actors/Developer/Dev.cs b/src/libs/MS.AI.DevTeam/Actors/Developer/Dev.cs
new file mode 100644
index 000000000..607d7842d
--- /dev/null
+++ b/src/libs/MS.AI.DevTeam/Actors/Developer/Dev.cs
@@ -0,0 +1,45 @@
+namespace MS.AI.DevTeam;
+
+public static class Dev {
+ public static SemanticFunctionConfig Implement = new SemanticFunctionConfig
+ {
+ PromptTemplate = """
+ You are a Developer for an application.
+ Please output the code required to accomplish the task assigned to you below and wrap it in a bash script that creates the files.
+ Do not use any IDE commands and do not build and run the code.
+ Make specific choices about implementation. Do not offer a range of options.
+ Use comments in the code to describe the intent. Do not include other text other than code and code comments.
+ Input: {{$input}}
+ """,
+ Name = nameof(Implement),
+ SkillName = nameof(Developer),
+ Description = "From a description of a coding task out put the code or scripts necessary to complete the task.",
+ MaxTokens = 6500,
+ Temperature = 0.0,
+ TopP = 0.0,
+ PPenalty = 0.0,
+ FPenalty = 0.0
+ };
+
+ public static SemanticFunctionConfig Improve = new SemanticFunctionConfig
+ {
+ PromptTemplate = """
+ You are a Developer for an application. Your job is to imrove the code that you are given in the input below.
+ Please output a new version of code that fixes any problems with this version.
+ If there is an error message in the input you should fix that error in the code.
+ Wrap the code output up in a bash script that creates the necessary files by overwriting any previous files.
+ Do not use any IDE commands and do not build and run the code.
+ Make specific choices about implementation. Do not offer a range of options.
+ Use comments in the code to describe the intent. Do not include other text other than code and code comments.
+ Input: {{$input}}
+ """,
+ Name = nameof(Improve),
+ SkillName = nameof(Developer),
+ Description = "From a description of a coding task out put the code or scripts necessary to complete the task.",
+ MaxTokens = 6500,
+ Temperature = 0.0,
+ TopP = 0.0,
+ PPenalty = 0.0,
+ FPenalty = 0.0
+ };
+}
diff --git a/src/libs/MS.AI.DevTeam/Actors/Developer/Developer.cs b/src/libs/MS.AI.DevTeam/Actors/Developer/Developer.cs
new file mode 100644
index 000000000..c062a6d62
--- /dev/null
+++ b/src/libs/MS.AI.DevTeam/Actors/Developer/Developer.cs
@@ -0,0 +1,45 @@
+using Microsoft.SemanticKernel;
+using Microsoft.SemanticKernel.Orchestration;
+using Orleans.Runtime;
+
+namespace MS.AI.DevTeam;
+
+public class Developer : SemanticPersona, IDevelopCode
+{
+ private readonly IKernel _kernel;
+ protected override string MemorySegment => "dev-memory";
+
+ public Developer(IKernel kernel, [PersistentState("state", "messages")]IPersistentState state) : base(state)
+ {
+ _kernel = kernel;
+ }
+
+ public async Task GenerateCode(string ask)
+ {
+ var function = _kernel.LoadFunction(nameof(Dev), nameof(Dev.Implement));
+ var context = new ContextVariables();
+ if (_state.State.History == null) _state.State.History = new List();
+ _state.State.History.Add(new ChatHistoryItem{
+ Message = ask,
+ Order = _state.State.History.Count+1,
+ UserType = ChatUserType.User
+ });
+ context.Set("input", ask);
+
+ var result = await _kernel.RunAsync(context, function);
+ var resultMessage = result.ToString();
+ _state.State.History.Add(new ChatHistoryItem{
+ Message = resultMessage,
+ Order = _state.State.History.Count+1,
+ UserType = ChatUserType.Agent
+ });
+ await _state.WriteStateAsync();
+
+ return resultMessage;
+ }
+
+ public Task ReviewPlan(string plan)
+ {
+ throw new NotImplementedException();
+ }
+}
diff --git a/src/libs/MS.AI.DevTeam/Actors/Developer/IDevelopCode.cs b/src/libs/MS.AI.DevTeam/Actors/Developer/IDevelopCode.cs
new file mode 100644
index 000000000..bafb81ac9
--- /dev/null
+++ b/src/libs/MS.AI.DevTeam/Actors/Developer/IDevelopCode.cs
@@ -0,0 +1,7 @@
+namespace MS.AI.DevTeam;
+
+public interface IDevelopCode : IGrainWithIntegerCompoundKey, IChatHistory
+{
+ Task GenerateCode(string ask);
+ Task ReviewPlan(string plan);
+}
\ No newline at end of file
diff --git a/src/libs/MS.AI.DevTeam/Actors/Lookup/ILookupMetadata.cs b/src/libs/MS.AI.DevTeam/Actors/Lookup/ILookupMetadata.cs
new file mode 100644
index 000000000..4bd1ba23c
--- /dev/null
+++ b/src/libs/MS.AI.DevTeam/Actors/Lookup/ILookupMetadata.cs
@@ -0,0 +1,7 @@
+namespace MS.AI.DevTeam;
+
+public interface ILookupMetadata : IGrainWithStringKey
+{
+ Task GetMetadata(int key);
+ Task StoreMetadata(List pairs);
+}
diff --git a/src/libs/MS.AI.DevTeam/Actors/Lookup/Lookup.cs b/src/libs/MS.AI.DevTeam/Actors/Lookup/Lookup.cs
new file mode 100644
index 000000000..d4c19da43
--- /dev/null
+++ b/src/libs/MS.AI.DevTeam/Actors/Lookup/Lookup.cs
@@ -0,0 +1,42 @@
+using Orleans.Runtime;
+
+namespace MS.AI.DevTeam;
+
+public class Lookup : Grain, ILookupMetadata
+{
+ protected readonly IPersistentState _state;
+ public Lookup([PersistentState("state", "messages")] IPersistentState state)
+ {
+ _state = state;
+ }
+
+ public Task GetMetadata(int key)
+ {
+ return Task.FromResult(_state.State.Metadata[key]);
+ }
+
+ public Task StoreMetadata(List pairs)
+ {
+ if(_state.State.Metadata == null) _state.State.Metadata = new Dictionary();
+ foreach(var pair in pairs)
+ {
+ _state.State.Metadata[pair.Key] = pair.Value;
+ }
+ return _state.WriteStateAsync();
+ }
+}
+
+[Serializable]
+public class ConductorLookup
+{
+ public Dictionary Metadata { get; set; }
+}
+
+[GenerateSerializer]
+public class StoreMetadataPairs
+{
+ [Id(0)]
+ public int Key { get; set; }
+ [Id(1)]
+ public NewIssueResponse Value { get; set; }
+}
\ No newline at end of file
diff --git a/src/libs/MS.AI.DevTeam/Actors/ProductManager/IManageProduct.cs b/src/libs/MS.AI.DevTeam/Actors/ProductManager/IManageProduct.cs
new file mode 100644
index 000000000..9cc36ac6e
--- /dev/null
+++ b/src/libs/MS.AI.DevTeam/Actors/ProductManager/IManageProduct.cs
@@ -0,0 +1,6 @@
+namespace MS.AI.DevTeam;
+
+public interface IManageProduct : IGrainWithIntegerCompoundKey, IChatHistory
+{
+ Task CreateReadme(string ask);
+}
\ No newline at end of file
diff --git a/src/libs/MS.AI.DevTeam/Actors/ProductManager/PM.cs b/src/libs/MS.AI.DevTeam/Actors/ProductManager/PM.cs
new file mode 100644
index 000000000..5eac53072
--- /dev/null
+++ b/src/libs/MS.AI.DevTeam/Actors/ProductManager/PM.cs
@@ -0,0 +1,23 @@
+namespace MS.AI.DevTeam;
+
+public static class PM
+{
+ public static SemanticFunctionConfig Readme = new SemanticFunctionConfig
+ {
+ PromptTemplate = """
+ You are a program manager on a software development team. You are working on an app described below.
+ Based on the input below, and any dialog or other context, please output a raw README.MD markdown file documenting the main features of the app and the architecture or code organization.
+ Do not describe how to create the application.
+ Write the README as if it were documenting the features and architecture of the application. You may include instructions for how to run the application.
+ Input: {{$input}}
+ """,
+ Name = nameof(Readme),
+ SkillName = nameof(PM),
+ Description = "From a simple description output a README.md file for a GitHub repository.",
+ MaxTokens = 6500,
+ Temperature = 0.0,
+ TopP = 0.0,
+ PPenalty = 0.0,
+ FPenalty = 0.0
+ };
+}
diff --git a/src/libs/MS.AI.DevTeam/Actors/ProductManager/ProductManager.cs b/src/libs/MS.AI.DevTeam/Actors/ProductManager/ProductManager.cs
new file mode 100644
index 000000000..e29051bb2
--- /dev/null
+++ b/src/libs/MS.AI.DevTeam/Actors/ProductManager/ProductManager.cs
@@ -0,0 +1,40 @@
+using Microsoft.SemanticKernel;
+using Microsoft.SemanticKernel.Orchestration;
+using Orleans.Runtime;
+
+namespace MS.AI.DevTeam;
+public class ProductManager : SemanticPersona, IManageProduct
+{
+ private readonly IKernel _kernel;
+ protected override string MemorySegment => "pm-memory";
+
+ public ProductManager(IKernel kernel,[PersistentState("state", "messages")] IPersistentState state) : base(state)
+ {
+ _kernel = kernel;
+ }
+ public async Task CreateReadme(string ask)
+ {
+ var function = _kernel.LoadFunction(nameof(PM), nameof(PM.Readme));
+ var context = new ContextVariables();
+ context.Set("input", ask);
+ if(_state.State.History == null) _state.State.History = new List();
+ _state.State.History.Add(new ChatHistoryItem
+ {
+ Message = ask,
+ Order = _state.State.History.Count + 1,
+ UserType = ChatUserType.User
+ });
+ context.Set("input", ask);
+
+ var result = await _kernel.RunAsync(context, function);
+ var resultMessage = result.ToString();
+ _state.State.History.Add(new ChatHistoryItem
+ {
+ Message = resultMessage,
+ Order = _state.State.History.Count + 1,
+ UserType = ChatUserType.Agent
+ });
+ await _state.WriteStateAsync();
+ return resultMessage;
+ }
+}
diff --git a/src/libs/MS.AI.DevTeam/Actors/Sandbox/IManageSandbox.cs b/src/libs/MS.AI.DevTeam/Actors/Sandbox/IManageSandbox.cs
new file mode 100644
index 000000000..d874fb952
--- /dev/null
+++ b/src/libs/MS.AI.DevTeam/Actors/Sandbox/IManageSandbox.cs
@@ -0,0 +1,6 @@
+namespace MS.AI.DevTeam;
+
+public interface IManageSandbox : IGrainWithIntegerCompoundKey
+{
+ Task ScheduleCommitSandboxRun(CommitRequest commitRequest, MarkTaskCompleteRequest markTaskCompleteRequest, SandboxRequest sandboxRequest);
+}
\ No newline at end of file
diff --git a/src/libs/MS.AI.DevTeam/Actors/Sandbox/Sandbox.cs b/src/libs/MS.AI.DevTeam/Actors/Sandbox/Sandbox.cs
new file mode 100644
index 000000000..6a5f28675
--- /dev/null
+++ b/src/libs/MS.AI.DevTeam/Actors/Sandbox/Sandbox.cs
@@ -0,0 +1,77 @@
+namespace MS.AI.DevTeam;
+using Orleans.Runtime;
+using Orleans.Timers;
+
+public class Sandbox : Grain, IManageSandbox, IRemindable
+{
+ private const string ReminderName = "SandboxRunReminder";
+ private readonly IManageGithub _ghService;
+ private readonly IManageAzure _azService;
+ private readonly IReminderRegistry _reminderRegistry;
+ private IGrainReminder? _reminder;
+
+ protected readonly IPersistentState _state;
+
+ public Sandbox([PersistentState("state", "messages")] IPersistentState state, IManageGithub ghService,
+ IReminderRegistry reminderRegistry, IManageAzure azService)
+ {
+ _ghService = ghService;
+ _reminderRegistry = reminderRegistry;
+ _azService = azService;
+ _state = state;
+ }
+ public async Task ScheduleCommitSandboxRun(CommitRequest commitRequest, MarkTaskCompleteRequest markTaskCompleteRequest, SandboxRequest sandboxRequest)
+ {
+ await StoreState(commitRequest, markTaskCompleteRequest, sandboxRequest);
+ _reminder = await _reminderRegistry.RegisterOrUpdateReminder(
+ callingGrainId: this.GetGrainId(),
+ reminderName: ReminderName,
+ dueTime: TimeSpan.Zero,
+ period: TimeSpan.FromMinutes(1));
+ }
+
+ async Task IRemindable.ReceiveReminder(string reminderName, TickStatus status)
+ {
+ if (!_state.State.IsCompleted)
+ {
+ var sandboxId = $"sk-sandbox-{_state.State.SandboxRequest.Org}-{_state.State.SandboxRequest.Repo}-{_state.State.SandboxRequest.ParentIssueNumber}-{_state.State.SandboxRequest.IssueNumber}";
+ if (await _azService.IsSandboxCompleted(sandboxId))
+ {
+ await _azService.DeleteSandbox(sandboxId);
+ await _ghService.CommitToBranch(_state.State.CommitRequest);
+ await _ghService.MarkTaskComplete(_state.State.MarkTaskCompleteRequest);
+ await Cleanup();
+ }
+ }
+ else
+ {
+ await Cleanup();
+ }
+ }
+
+ private async Task StoreState(CommitRequest commitRequest, MarkTaskCompleteRequest markTaskCompleteRequest, SandboxRequest sandboxRequest)
+ {
+ _state.State.CommitRequest = commitRequest;
+ _state.State.MarkTaskCompleteRequest = markTaskCompleteRequest;
+ _state.State.SandboxRequest = sandboxRequest;
+ _state.State.IsCompleted = false;
+ await _state.WriteStateAsync();
+ }
+
+ private async Task Cleanup()
+ {
+ _state.State.IsCompleted = true;
+ await _reminderRegistry.UnregisterReminder(
+ this.GetGrainId(), _reminder);
+ await _state.WriteStateAsync();
+ }
+}
+
+
+public class SandboxMetadata
+{
+ public CommitRequest CommitRequest { get; set; }
+ public MarkTaskCompleteRequest MarkTaskCompleteRequest { get; set; }
+ public SandboxRequest SandboxRequest { get; set; }
+ public bool IsCompleted { get; set; }
+}
diff --git a/src/libs/MS.AI.DevTeam/Actors/SemanticPersona.cs b/src/libs/MS.AI.DevTeam/Actors/SemanticPersona.cs
new file mode 100644
index 000000000..0bfb88adf
--- /dev/null
+++ b/src/libs/MS.AI.DevTeam/Actors/SemanticPersona.cs
@@ -0,0 +1,45 @@
+using Orleans.Runtime;
+
+public abstract class SemanticPersona : Grain, IChatHistory
+{
+ public SemanticPersona(
+ [PersistentState("state", "messages")] IPersistentState state)
+ {
+ _state = state;
+ }
+ protected virtual string MemorySegment { get; set; }
+ protected List History { get; set; }
+ protected readonly IPersistentState _state;
+
+ public async Task GetLastMessage()
+ {
+ return _state.State.History.Last().Message;
+ }
+}
+
+public interface IChatHistory
+{
+ Task GetLastMessage();
+}
+
+
+[Serializable]
+public class ChatHistoryItem
+{
+ public string Message { get; set; }
+ public ChatUserType UserType { get; set; }
+ public int Order { get; set; }
+
+}
+
+public class ChatHistory
+{
+ public List History { get; set; }
+}
+
+public enum ChatUserType
+{
+ System,
+ User,
+ Agent
+}
\ No newline at end of file
diff --git a/src/libs/MS.AI.DevTeam/Actors/Tester/Tester.cs b/src/libs/MS.AI.DevTeam/Actors/Tester/Tester.cs
new file mode 100644
index 000000000..0b7466a60
--- /dev/null
+++ b/src/libs/MS.AI.DevTeam/Actors/Tester/Tester.cs
@@ -0,0 +1,25 @@
+using Orleans.Runtime;
+
+public class Tester : SemanticPersona, ITestCode
+{
+ public Tester(
+ [PersistentState("state", "messages")]IPersistentState state) : base(state)
+ {
+
+ }
+ public Task ReviewPlan(string plan)
+ {
+ throw new NotImplementedException();
+ }
+
+ public Task TestCode(string ask)
+ {
+ throw new NotImplementedException();
+ }
+}
+
+public interface ITestCode : IGrainWithIntegerCompoundKey
+{
+ Task TestCode(string ask);
+ Task ReviewPlan(string plan);
+}
\ No newline at end of file
diff --git a/src/libs/MS.AI.DevTeam/Config/SemanticFunctionConfig.cs b/src/libs/MS.AI.DevTeam/Config/SemanticFunctionConfig.cs
new file mode 100644
index 000000000..1c61a8b0f
--- /dev/null
+++ b/src/libs/MS.AI.DevTeam/Config/SemanticFunctionConfig.cs
@@ -0,0 +1,38 @@
+using Microsoft.SemanticKernel;
+using Microsoft.SemanticKernel.SkillDefinition;
+
+namespace MS.AI.DevTeam;
+
+public class SemanticFunctionConfig
+{
+ public string PromptTemplate { get; set; }
+ public string Name { get; set; }
+ public string SkillName { get; set; }
+ public string Description { get; set; }
+ public int MaxTokens { get; set; }
+ public double Temperature { get; set; }
+ public double TopP { get; set; }
+ public double PPenalty { get; set; }
+ public double FPenalty { get; set; }
+ public static SemanticFunctionConfig ForSkillAndFunction(string skillName, string functionName) =>
+ (skillName, functionName) switch
+ {
+ (nameof(PM), nameof(PM.Readme)) => PM.Readme,
+ (nameof(DevLead), nameof(DevLead.Plan)) => DevLead.Plan,
+ // (nameof(CodeExplainer), nameof(CodeExplainer.Explain)) => CodeExplainer.Explain,
+ (nameof(Dev), nameof(Dev.Implement)) => Dev.Implement,
+ // (nameof(Developer), nameof(Developer.Improve)) => Developer.Improve,
+ _ => throw new ArgumentException($"Unable to find {skillName}.{functionName}")
+ };
+}
+
+public static class SemanticKernelExtensions
+{
+ public static ISKFunction LoadFunction(this IKernel kernel, string skill, string function)
+ {
+ var skillConfig = SemanticFunctionConfig.ForSkillAndFunction(skill, function);
+ return kernel.CreateSemanticFunction(skillConfig.PromptTemplate, skillConfig.Name, skillConfig.SkillName,
+ skillConfig.Description, skillConfig.MaxTokens, skillConfig.Temperature,
+ skillConfig.TopP, skillConfig.PPenalty, skillConfig.FPenalty);
+ }
+}
\ No newline at end of file
diff --git a/src/libs/MS.AI.DevTeam/MS.AI.DevTeam.csproj b/src/libs/MS.AI.DevTeam/MS.AI.DevTeam.csproj
new file mode 100644
index 000000000..1dfa8f6dd
--- /dev/null
+++ b/src/libs/MS.AI.DevTeam/MS.AI.DevTeam.csproj
@@ -0,0 +1,22 @@
+
+
+
+ net7.0
+ enable
+ enable
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/libs/MS.AI.DevTeam/Options/AzureOptions.cs b/src/libs/MS.AI.DevTeam/Options/AzureOptions.cs
new file mode 100644
index 000000000..362b1f883
--- /dev/null
+++ b/src/libs/MS.AI.DevTeam/Options/AzureOptions.cs
@@ -0,0 +1,11 @@
+public class AzureOptions
+{
+ public string SubscriptionId { get; set; }
+ public string Location { get; set; }
+ public string ContainerInstancesResourceGroup { get; set; }
+ public string FilesShareName { get; set; }
+ public string FilesAccountName { get; set; }
+ public string FilesAccountKey { get; set; }
+ public string CosmosConnectionString { get; set; }
+ public string SandboxImage { get; set; }
+}
\ No newline at end of file
diff --git a/src/libs/MS.AI.DevTeam/Options/GithubOptions.cs b/src/libs/MS.AI.DevTeam/Options/GithubOptions.cs
new file mode 100644
index 000000000..90ed5cdc0
--- /dev/null
+++ b/src/libs/MS.AI.DevTeam/Options/GithubOptions.cs
@@ -0,0 +1,6 @@
+public class GithubOptions
+{
+ public string AppKey { get; set; }
+ public int AppId { get; set; }
+ public long InstallationId { get; set; }
+}
diff --git a/src/libs/MS.AI.DevTeam/Options/OpenAIOptions.cs b/src/libs/MS.AI.DevTeam/Options/OpenAIOptions.cs
new file mode 100644
index 000000000..9f752153b
--- /dev/null
+++ b/src/libs/MS.AI.DevTeam/Options/OpenAIOptions.cs
@@ -0,0 +1,10 @@
+
+public class OpenAIOptions
+{
+ public string ServiceType { get; set; }
+ public string ServiceId { get; set; }
+ public string DeploymentOrModelId { get; set; }
+ public string EmbeddingDeploymentOrModelId { get; set; }
+ public string Endpoint { get; set; }
+ public string ApiKey { get; set; }
+}
diff --git a/src/libs/MS.AI.DevTeam/Options/QdrantOptions.cs b/src/libs/MS.AI.DevTeam/Options/QdrantOptions.cs
new file mode 100644
index 000000000..9d12defc4
--- /dev/null
+++ b/src/libs/MS.AI.DevTeam/Options/QdrantOptions.cs
@@ -0,0 +1,7 @@
+
+
+public class QdrantOptions
+{
+ public string Endpoint { get; set; }
+ public int VectorSize { get; set; }
+}
\ No newline at end of file
diff --git a/src/libs/MS.AI.DevTeam/Services/AzureService.cs b/src/libs/MS.AI.DevTeam/Services/AzureService.cs
new file mode 100644
index 000000000..a23d1e94d
--- /dev/null
+++ b/src/libs/MS.AI.DevTeam/Services/AzureService.cs
@@ -0,0 +1,151 @@
+using System.Text;
+using Azure;
+using Azure.Core;
+using Azure.Identity;
+using Azure.ResourceManager;
+using Azure.ResourceManager.ContainerInstance;
+using Azure.ResourceManager.ContainerInstance.Models;
+using Azure.ResourceManager.Resources;
+using Azure.Storage.Files.Shares;
+using Microsoft.Extensions.Options;
+
+
+namespace MS.AI.DevTeam;
+
+public class AzureService : IManageAzure
+{
+ private readonly AzureOptions _azSettings;
+
+ public AzureService(IOptions azOptions)
+ {
+ _azSettings = azOptions.Value;
+ }
+
+ public async Task DeleteSandbox(string sandboxId)
+ {
+ var client = new ArmClient(new DefaultAzureCredential());
+ var resourceGroupResourceId = ResourceGroupResource.CreateResourceIdentifier(_azSettings.SubscriptionId, _azSettings.ContainerInstancesResourceGroup);
+ var resourceGroupResource = client.GetResourceGroupResource(resourceGroupResourceId);
+
+ var collection = resourceGroupResource.GetContainerGroups();
+ var containerGroup = await collection.GetAsync(sandboxId);
+ await containerGroup.Value.DeleteAsync(WaitUntil.Started);
+ }
+
+ public async Task IsSandboxCompleted(string sandboxId)
+ {
+ var client = new ArmClient(new DefaultAzureCredential());
+ var resourceGroupResourceId = ResourceGroupResource.CreateResourceIdentifier(_azSettings.SubscriptionId, _azSettings.ContainerInstancesResourceGroup);
+ var resourceGroupResource = client.GetResourceGroupResource(resourceGroupResourceId);
+
+ var collection = resourceGroupResource.GetContainerGroups();
+ var containerGroup = await collection.GetAsync(sandboxId);
+ return containerGroup.Value.Data.ProvisioningState == "Succeeded"
+ && containerGroup.Value.Data.Containers.First().InstanceView.CurrentState.State == "Terminated";
+ }
+
+ public async Task RunInSandbox(SandboxRequest request)
+ {
+ var client = new ArmClient(new DefaultAzureCredential());
+ var runId = $"sk-sandbox-{request.Org}-{request.Repo}-{request.ParentIssueNumber}-{request.IssueNumber}";
+ var resourceGroupResourceId = ResourceGroupResource.CreateResourceIdentifier(_azSettings.SubscriptionId, _azSettings.ContainerInstancesResourceGroup);
+ var resourceGroupResource = client.GetResourceGroupResource(resourceGroupResourceId);
+ var scriptPath = $"/azfiles/output/{request.Org}-{request.Repo}/{request.ParentIssueNumber}/{request.IssueNumber}/run.sh";
+ var collection = resourceGroupResource.GetContainerGroups();
+ var data = new ContainerGroupData(new AzureLocation(_azSettings.Location), new ContainerInstanceContainer[]
+ {
+ new ContainerInstanceContainer(runId,_azSettings.SandboxImage,new ContainerResourceRequirements(new ContainerResourceRequestsContent(1.5,1)))
+ {
+ Command = { "/bin/bash", $"{scriptPath}" },
+ VolumeMounts =
+ {
+ new ContainerVolumeMount("azfiles","/azfiles/")
+ {
+ IsReadOnly = false,
+ }
+ },
+ }}, ContainerInstanceOperatingSystemType.Linux)
+ {
+ Volumes =
+ {
+ new ContainerVolume("azfiles")
+ {
+ AzureFile = new ContainerInstanceAzureFileVolume(_azSettings.FilesShareName,_azSettings.FilesAccountName)
+ {
+ StorageAccountKey = _azSettings.FilesAccountKey
+ },
+ },
+ },
+ RestartPolicy = ContainerGroupRestartPolicy.Never,
+ Sku = ContainerGroupSku.Standard,
+ Priority = ContainerGroupPriority.Regular
+ };
+ await collection.CreateOrUpdateAsync(WaitUntil.Completed, runId, data);
+ }
+
+ public async Task Store(SaveOutputRequest request)
+ {
+ var connectionString = $"DefaultEndpointsProtocol=https;AccountName={_azSettings.FilesAccountName};AccountKey={_azSettings.FilesAccountKey};EndpointSuffix=core.windows.net";
+ var parentDirName = $"{request.Directory}/{request.Org}-{request.Repo}";
+
+ var fileName = $"{request.FileName}.{request.Extension}";
+
+ var share = new ShareClient(connectionString, _azSettings.FilesShareName);
+ await share.CreateIfNotExistsAsync();
+ await share.GetDirectoryClient($"{request.Directory}").CreateIfNotExistsAsync(); ;
+
+ var parentDir = share.GetDirectoryClient(parentDirName);
+ await parentDir.CreateIfNotExistsAsync();
+
+ var parentIssueDir = parentDir.GetSubdirectoryClient($"{request.ParentIssueNumber}");
+ await parentIssueDir.CreateIfNotExistsAsync();
+
+ var directory = parentIssueDir.GetSubdirectoryClient($"{request.IssueNumber}");
+ await directory.CreateIfNotExistsAsync();
+
+ var file = directory.GetFileClient(fileName);
+ // hack to enable script to save files in the same directory
+ var cwdHack = "#!/bin/bash\n cd $(dirname $0)";
+ var output = request.Extension == "sh" ? request.Output.Replace("#!/bin/bash", cwdHack) : request.Output;
+ using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(output)))
+ {
+ await file.CreateAsync(stream.Length);
+ await file.UploadRangeAsync(
+ new HttpRange(0, stream.Length),
+ stream);
+ }
+ }
+}
+
+public interface IManageAzure
+{
+ Task Store(SaveOutputRequest request);
+ Task RunInSandbox(SandboxRequest request);
+ Task IsSandboxCompleted(string sandboxId);
+ Task DeleteSandbox(string sandboxId);
+}
+
+public class SaveOutputRequest
+{
+ public int ParentIssueNumber { get; set; }
+ public int IssueNumber { get; set; }
+ public string Output { get; set; }
+ public string Extension { get; set; }
+ public string Directory { get; set; }
+ public string FileName { get; set; }
+ public string Org { get; set; }
+ public string Repo { get; set; }
+}
+
+[GenerateSerializer]
+public class SandboxRequest
+{
+ [Id(0)]
+ public string Org { get; set; }
+ [Id(1)]
+ public string Repo { get; set; }
+ [Id(2)]
+ public int IssueNumber { get; set; }
+ [Id(3)]
+ public int ParentIssueNumber { get; set; }
+}
\ No newline at end of file
diff --git a/src/libs/MS.AI.DevTeam/Services/GithubAuthService.cs b/src/libs/MS.AI.DevTeam/Services/GithubAuthService.cs
new file mode 100644
index 000000000..8bc01b88f
--- /dev/null
+++ b/src/libs/MS.AI.DevTeam/Services/GithubAuthService.cs
@@ -0,0 +1,35 @@
+using Microsoft.Extensions.Options;
+using Octokit;
+
+public class GithubAuthService
+{
+ private readonly GithubOptions _githubSettings;
+
+ public GithubAuthService(IOptions ghOptions)
+ {
+ _githubSettings = ghOptions.Value;
+ }
+ public async Task GetGitHubClient()
+ {
+ // Use GitHubJwt library to create the GitHubApp Jwt Token using our private certificate PEM file
+ var generator = new GitHubJwt.GitHubJwtFactory(
+ new GitHubJwt.StringPrivateKeySource(_githubSettings.AppKey),
+ new GitHubJwt.GitHubJwtFactoryOptions
+ {
+ AppIntegrationId = _githubSettings.AppId, // The GitHub App Id
+ ExpirationSeconds = 600 // 10 minutes is the maximum time allowed
+ }
+ );
+
+ var jwtToken = generator.CreateEncodedJwtToken();
+ var appClient = new GitHubClient(new ProductHeaderValue("SK-DEV-APP"))
+ {
+ Credentials = new Credentials(jwtToken, AuthenticationType.Bearer)
+ };
+ var response = await appClient.GitHubApps.CreateInstallationToken(_githubSettings.InstallationId);
+ return new GitHubClient(new ProductHeaderValue($"SK-DEV-APP-Installation{_githubSettings.InstallationId}"))
+ {
+ Credentials = new Credentials(response.Token)
+ };
+ }
+}
\ No newline at end of file
diff --git a/src/libs/MS.AI.DevTeam/Services/GithubService.cs b/src/libs/MS.AI.DevTeam/Services/GithubService.cs
new file mode 100644
index 000000000..5666e12f7
--- /dev/null
+++ b/src/libs/MS.AI.DevTeam/Services/GithubService.cs
@@ -0,0 +1,197 @@
+using System.Text;
+using Azure.Storage.Files.Shares;
+using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Options;
+using Octokit;
+using Octokit.Helpers;
+
+
+namespace MS.AI.DevTeam;
+
+public class GithubService : IManageGithub
+{
+ private readonly GitHubClient _ghClient;
+ private readonly AzureOptions _azSettings;
+ private readonly ILogger logger;
+
+ public GithubService(GitHubClient ghClient, IOptions azOptions, ILogger logger)
+ {
+ _ghClient = ghClient;
+ _azSettings = azOptions.Value;
+ this.logger = logger;
+ }
+
+ public async Task CommitToBranch(CommitRequest request)
+ {
+ var connectionString = $"DefaultEndpointsProtocol=https;AccountName={_azSettings.FilesAccountName};AccountKey={_azSettings.FilesAccountKey};EndpointSuffix=core.windows.net";
+
+ var dirName = $"{request.Dir}/{request.Org}-{request.Repo}/{request.ParentNumber}/{request.Number}";
+ var share = new ShareClient(connectionString, _azSettings.FilesShareName);
+ var directory = share.GetDirectoryClient(dirName);
+
+ var remaining = new Queue();
+ remaining.Enqueue(directory);
+ while (remaining.Count > 0)
+ {
+ var dir = remaining.Dequeue();
+ await foreach (var item in dir.GetFilesAndDirectoriesAsync())
+ {
+ if (!item.IsDirectory && item.Name != "run.sh") // we don't want the generated script in the PR
+ {
+ try
+ {
+ var file = dir.GetFileClient(item.Name);
+ var filePath = file.Path.Replace($"{_azSettings.FilesShareName}/", "")
+ .Replace($"{dirName}/", "");
+ var fileStream = await file.OpenReadAsync();
+ using (var reader = new StreamReader(fileStream, Encoding.UTF8))
+ {
+ var value = reader.ReadToEnd();
+
+ await _ghClient.Repository.Content.CreateFile(
+ request.Org, request.Repo, filePath,
+ new CreateFileRequest($"Commit message", value, request.Branch)); // TODO: add more meaningfull commit message
+ }
+ }
+ catch (Exception ex)
+ {
+ logger.LogError(ex, $"Error while uploading file {item.Name}");
+ }
+ }
+ else if (item.IsDirectory)
+ {
+ remaining.Enqueue(dir.GetSubdirectoryClient(item.Name));
+ }
+ }
+ }
+ }
+
+ public async Task CreateBranch(CreateBranchRequest request)
+ {
+ var ghRepo = await _ghClient.Repository.Get(request.Org, request.Repo);
+ await _ghClient.Git.Reference.CreateBranch(request.Org, request.Repo, request.Branch, ghRepo.DefaultBranch);
+ }
+
+ public async Task CreateIssue(CreateIssueRequest request)
+ {
+ var newIssue = new NewIssue($"{request.Label} chain for #{request.ParentNumber}")
+ {
+ Body = request.Input,
+
+ };
+ newIssue.Labels.Add(request.Label);
+ var issue = await _ghClient.Issue.Create(request.Org, request.Repo, newIssue);
+ var commentBody = $" - [ ] #{issue.Number} - tracks {request.Label}";
+ var comment = await _ghClient.Issue.Comment.Create(request.Org, request.Repo, (int)request.ParentNumber, commentBody);
+ return new NewIssueResponse
+ {
+ IssueNumber = issue.Number,
+ CommentId = comment.Id
+ };
+
+ }
+
+ public async Task CreatePR(CreatePRRequest request)
+ {
+ var ghRepo = await _ghClient.Repository.Get(request.Org, request.Repo);
+ await _ghClient.PullRequest.Create(request.Org, request.Repo, new NewPullRequest($"New app #{request.Number}", request.Branch, ghRepo.DefaultBranch));
+ }
+
+ public async Task MarkTaskComplete(MarkTaskCompleteRequest request)
+ {
+ var comment = await _ghClient.Issue.Comment.Get(request.Org, request.Repo, request.CommentId);
+ var updatedComment = comment.Body.Replace("[ ]", "[x]");
+ await _ghClient.Issue.Comment.Update(request.Org, request.Repo, request.CommentId, updatedComment);
+ }
+
+ public async Task PostComment(PostCommentRequest request)
+ {
+ await _ghClient.Issue.Comment.Create(request.Org, request.Repo, request.Number, request.Content);
+ }
+}
+
+public interface IManageGithub
+{
+ Task CreateIssue(CreateIssueRequest request);
+ Task MarkTaskComplete(MarkTaskCompleteRequest request);
+
+ Task CreatePR(CreatePRRequest request);
+ Task CreateBranch(CreateBranchRequest request);
+ Task CommitToBranch(CommitRequest request);
+
+ Task PostComment(PostCommentRequest request);
+}
+
+[GenerateSerializer]
+public class MarkTaskCompleteRequest
+{
+ [Id(0)]
+ public string Org { get; set; }
+ [Id(1)]
+ public string Repo { get; set; }
+ [Id(2)]
+ public int CommentId { get; set; }
+}
+[GenerateSerializer]
+public class CreateIssueRequest
+{
+ [Id(0)]
+ public string Input { get; set; }
+ [Id(1)]
+ public string Label { get; set; }
+ [Id(2)]
+ public long ParentNumber { get; set; }
+ [Id(3)]
+ public string Org { get; set; }
+ [Id(4)]
+ public string Repo { get; set; }
+}
+
+public class CreateBranchRequest
+{
+ public string Org { get; set; }
+ public string Repo { get; set; }
+ public string Branch { get; set; }
+}
+
+public class CreatePRRequest
+{
+ public string Org { get; set; }
+ public string Repo { get; set; }
+ public string Branch { get; set; }
+ public int Number { get; set; }
+}
+
+public class PostCommentRequest
+{
+ public string Org { get; set; }
+ public string Repo { get; set; }
+ public string Content { get; set; }
+ public int Number { get; set; }
+}
+
+[GenerateSerializer]
+public class NewIssueResponse
+{
+ [Id(0)]
+ public int IssueNumber { get; set; }
+ [Id(1)]
+ public int CommentId { get; set; }
+}
+
+[GenerateSerializer]
+public class CommitRequest
+{
+ [Id(0)]
+ public string Dir { get; set; }
+ [Id(1)]
+ public string Org { get; set; }
+ [Id(2)]
+ public string Repo { get; set; }
+ [Id(3)]
+ public int ParentNumber { get; set; }
+ [Id(4)]
+ public int Number { get; set; }
+ [Id(5)]
+ public string Branch { get; set; }
+}
\ No newline at end of file
diff --git a/skills/Chat.cs b/src/libs/skills/Chat.cs
similarity index 100%
rename from skills/Chat.cs
rename to src/libs/skills/Chat.cs
diff --git a/skills/CodeExplainer.cs b/src/libs/skills/CodeExplainer.cs
similarity index 100%
rename from skills/CodeExplainer.cs
rename to src/libs/skills/CodeExplainer.cs
diff --git a/skills/DevLead.cs b/src/libs/skills/DevLead.cs
similarity index 100%
rename from skills/DevLead.cs
rename to src/libs/skills/DevLead.cs
diff --git a/skills/Developer.cs b/src/libs/skills/Developer.cs
similarity index 100%
rename from skills/Developer.cs
rename to src/libs/skills/Developer.cs
diff --git a/skills/PM.cs b/src/libs/skills/PM.cs
similarity index 100%
rename from skills/PM.cs
rename to src/libs/skills/PM.cs
diff --git a/skills/SemanticFunctionConfig.cs b/src/libs/skills/SemanticFunctionConfig.cs
similarity index 100%
rename from skills/SemanticFunctionConfig.cs
rename to src/libs/skills/SemanticFunctionConfig.cs
diff --git a/skills/skills.csproj b/src/libs/skills/skills.csproj
similarity index 100%
rename from skills/skills.csproj
rename to src/libs/skills/skills.csproj