Repository: microsoft/kiota (csharp)

Issue:
api manifests should not contain a kiota hash
When I generate an API manifest I get the following result

```json
{
  "applicationName": "application",
  "apiDependencies": {
    "github": {
      "apiDescriptionUrl": "https://raw.githubusercontent.com/APIs-guru/openapi-directory/gh-pages/v2/specs/github.com/api.github.com/1.1.4/openapi.json",
      "apiDeploymentBaseUrl": "https://api.github.com/",
      "requests": [
        {
          "method": "POST",
          "uriTemplate": "markdown"
        }
      ],
      "extensions": {
        "x-ms-kiota-hash": "75936866893F983D9B8E247A93D0F2DBE4F5B1CE4CC76EB85FEF8AE46B1791F7F130ACCF202043576645EBC8D3E2E6F2E76768F42FCC58945286D775253380C8"
      }
    }
  }
}
```

notice that it contains an extension with the kiota hash. 
This is caused because we need that kiota hash in the kiota manifest for the workspace, which we need/should keep. However it should not be in the plugin manifest.

Pull request:
Fixes #4561

Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 99c931129a..e8d8c116a9 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -21,6 +21,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 - Fixes request builder disambiguation when child nodes had different prefixes for different paths with same parameters.[#4448](https://github.com/microsoft/kiota/issues/4448) 
 - Do not generate CS8603 warnings when enabling backing store in CSharp generation.
 - Fixed excluding operation. [#4399](https://github.com/microsoft/kiota/issues/4399)
+- Fixed plugin generation of `ApiManifest` type to not include the `x-ms-kiota-hash` in the generated plugin. [#4561](https://github.com/microsoft/kiota/issues/4561)
 
 ## [1.13.0] - 2024-04-04
 
diff --git a/src/Kiota.Builder/Configuration/GenerationConfiguration.cs b/src/Kiota.Builder/Configuration/GenerationConfiguration.cs
index 4a22c24b8a..79d426987c 100644
--- a/src/Kiota.Builder/Configuration/GenerationConfiguration.cs
+++ b/src/Kiota.Builder/Configuration/GenerationConfiguration.cs
@@ -179,11 +179,14 @@ public ApiDependency ToApiDependency(string configurationHash, Dictionary<string
         {
             ApiDescriptionUrl = OpenAPIFilePath,
             ApiDeploymentBaseUrl = ApiRootUrl?.EndsWith('/') ?? false ? ApiRootUrl : $"{ApiRootUrl}/",
-            Extensions = new() {
-                { KiotaHashManifestExtensionKey, JsonValue.Create(configurationHash)}
-            },
+            Extensions = new(),
             Requests = templatesWithOperations.SelectMany(static x => x.Value.Select(y => new RequestInfo { Method = y.ToUpperInvariant(), UriTemplate = x.Key.DeSanitizeUrlTemplateParameter() })).ToList(),
         };
+
+        if (!string.IsNullOrEmpty(configurationHash))
+        {
+            dependency.Extensions.Add(KiotaHashManifestExtensionKey, JsonValue.Create(configurationHash));// only include non empty value.
+        }
         return dependency;
     }
     public bool IsPluginConfiguration => PluginTypes.Count != 0;
diff --git a/src/Kiota.Builder/Plugins/PluginsGenerationService.cs b/src/Kiota.Builder/Plugins/PluginsGenerationService.cs
index 09f073b182..93cc546e55 100644
--- a/src/Kiota.Builder/Plugins/PluginsGenerationService.cs
+++ b/src/Kiota.Builder/Plugins/PluginsGenerationService.cs
@@ -66,7 +66,8 @@ public async Task GenerateManifestAsync(CancellationToken cancellationToken = de
                     break;
                 case PluginType.APIManifest:
                     var apiManifest = new ApiManifestDocument("application"); //TODO add application name
-                    apiManifest.ApiDependencies.AddOrReplace(Configuration.ClientClassName, Configuration.ToApiDependency(OAIDocument.HashCode ?? string.Empty, TreeNode?.GetRequestInfo().ToDictionary(static x => x.Key, static x => x.Value) ?? []));
+                    // pass empty cong hash so that its not included in this manifest.
+                    apiManifest.ApiDependencies.AddOrReplace(Configuration.ClientClassName, Configuration.ToApiDependency(string.Empty, TreeNode?.GetRequestInfo().ToDictionary(static x => x.Key, static x => x.Value) ?? []));
                     apiManifest.Write(writer);
                     break;
                 case PluginType.OpenAI://TODO add support for OpenAI plugin type generation


Test patch:
diff --git a/tests/Kiota.Builder.Tests/Configuration/GenerationConfigurationTests.cs b/tests/Kiota.Builder.Tests/Configuration/GenerationConfigurationTests.cs
index 0ef9d2f6d1..6e3e95e9b5 100644
--- a/tests/Kiota.Builder.Tests/Configuration/GenerationConfigurationTests.cs
+++ b/tests/Kiota.Builder.Tests/Configuration/GenerationConfigurationTests.cs
@@ -36,9 +36,30 @@ public void ToApiDependency()
             { "foo/bar", new HashSet<string>{"GET"}}
         });
         Assert.NotNull(apiDependency);
+        Assert.NotNull(apiDependency.Extensions);
         Assert.Equal("foo", apiDependency.Extensions[GenerationConfiguration.KiotaHashManifestExtensionKey].GetValue<string>());
         Assert.NotEmpty(apiDependency.Requests);
         Assert.Equal("foo/bar", apiDependency.Requests[0].UriTemplate);
         Assert.Equal("GET", apiDependency.Requests[0].Method);
     }
+    [Fact]
+    public void ToApiDependencyDoesNotIncludeConfigHashIfEmpty()
+    {
+        var generationConfiguration = new GenerationConfiguration
+        {
+            ClientClassName = "class1",
+            IncludePatterns = null,
+            OpenAPIFilePath = "https://pet.store/openapi.yaml",
+            ApiRootUrl = "https://pet.store/api",
+        };
+        var apiDependency = generationConfiguration.ToApiDependency(string.Empty, new Dictionary<string, HashSet<string>>{
+            { "foo/bar", new HashSet<string>{"GET"}}
+        });
+        Assert.NotNull(apiDependency);
+        Assert.NotNull(apiDependency.Extensions);
+        Assert.False(apiDependency.Extensions.ContainsKey(GenerationConfiguration.KiotaHashManifestExtensionKey));
+        Assert.NotEmpty(apiDependency.Requests);
+        Assert.Equal("foo/bar", apiDependency.Requests[0].UriTemplate);
+        Assert.Equal("GET", apiDependency.Requests[0].Method);
+    }
 }