From 9f66f5d0fda651e6957c3acc10f8c544a4b473ea Mon Sep 17 00:00:00 2001 From: Christian Findlay <16697547+MelbourneDeveloper@users.noreply.github.com> Date: Wed, 22 Oct 2025 21:14:03 +1100 Subject: [PATCH 1/4] fix thing --- .../CodeGenerationHelpers.cs | 25 ++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/RestClient.Net.OpenApiGenerator/CodeGenerationHelpers.cs b/RestClient.Net.OpenApiGenerator/CodeGenerationHelpers.cs index 7172d4d6..1fdc115d 100644 --- a/RestClient.Net.OpenApiGenerator/CodeGenerationHelpers.cs +++ b/RestClient.Net.OpenApiGenerator/CodeGenerationHelpers.cs @@ -15,10 +15,33 @@ public static string ToPascalCase(string text) return text; } - var parts = text.Split(['-', '_', ' '], StringSplitOptions.RemoveEmptyEntries); + var sanitized = SanitizeIdentifier(text); + var parts = sanitized.Split(['-', '_', ' '], StringSplitOptions.RemoveEmptyEntries); return string.Join(string.Empty, parts.Select(p => char.ToUpperInvariant(p[0]) + p[1..])); } + /// Removes invalid C# identifier characters from a string. + /// The text to sanitize. + /// The sanitized text with invalid characters removed. + private static string SanitizeIdentifier(string text) + { + if (string.IsNullOrEmpty(text)) + { + return text; + } + + var result = new System.Text.StringBuilder(text.Length); + foreach (var c in text) + { + if (char.IsLetterOrDigit(c) || c == '_' || c == '-' || c == ' ') + { + _ = result.Append(c); + } + } + + return result.ToString(); + } + /// Converts a string to camelCase. /// The text to convert. /// The camelCase version of the text. From c85f54c01d3e6ad2cd086b2a571768ccbe5fc68a Mon Sep 17 00:00:00 2001 From: Christian Findlay <16697547+MelbourneDeveloper@users.noreply.github.com> Date: Wed, 22 Oct 2025 21:15:50 +1100 Subject: [PATCH 2/4] Fix test coverage --- .../MSTestSettings.cs | 1 - .../OpenApiCodeGeneratorTests.cs | 1459 +++++++++++++++++ ...stClient.Net.OpenApiGenerator.Tests.csproj | 1 + .../ModelGenerator.cs | 20 + .../Generated/NucliaDBApiExtensions.g.cs | 96 +- .../Generated/NucliaDBApiModels.g.cs | 321 ++-- .../Generated/NucliaDbMcpTools.g.cs | 24 +- .../Generated/JSONPlaceholderApiModels.g.cs | 1 + 8 files changed, 1702 insertions(+), 221 deletions(-) delete mode 100644 RestClient.Net.OpenApiGenerator.Tests/MSTestSettings.cs diff --git a/RestClient.Net.OpenApiGenerator.Tests/MSTestSettings.cs b/RestClient.Net.OpenApiGenerator.Tests/MSTestSettings.cs deleted file mode 100644 index aaf278c8..00000000 --- a/RestClient.Net.OpenApiGenerator.Tests/MSTestSettings.cs +++ /dev/null @@ -1 +0,0 @@ -[assembly: Parallelize(Scope = ExecutionScope.MethodLevel)] diff --git a/RestClient.Net.OpenApiGenerator.Tests/OpenApiCodeGeneratorTests.cs b/RestClient.Net.OpenApiGenerator.Tests/OpenApiCodeGeneratorTests.cs index e33d7e9d..6860d51e 100644 --- a/RestClient.Net.OpenApiGenerator.Tests/OpenApiCodeGeneratorTests.cs +++ b/RestClient.Net.OpenApiGenerator.Tests/OpenApiCodeGeneratorTests.cs @@ -519,4 +519,1463 @@ public void Generate_CreatesPrivateStaticFuncFields() && result.ExtensionMethodsCode.Contains(", cancellationToken)") ); } + + [TestMethod] + public void Generate_HandlesAnyOfSchemasInProperties() + { + var specWithAnyOf = """ + { + "openapi": "3.0.0", + "info": { "title": "Test API", "version": "1.0.0" }, + "servers": [{ "url": "https://api.test.com" }], + "paths": { + "/kb": { + "get": { + "operationId": "getKb", + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/KnowledgeBoxObj" + } + } + } + } + } + } + } + }, + "components": { + "schemas": { + "KnowledgeBoxObj": { + "type": "object", + "required": ["uuid"], + "properties": { + "slug": { + "anyOf": [ + { "type": "string", "maxLength": 250 }, + { "type": "null" } + ] + }, + "uuid": { + "type": "string" + }, + "config": { + "anyOf": [ + { "$ref": "#/components/schemas/KnowledgeBoxConfig" }, + { "type": "null" } + ] + }, + "model": { + "anyOf": [ + { "$ref": "#/components/schemas/SemanticModelMetadata" }, + { "type": "null" } + ] + } + } + }, + "KnowledgeBoxConfig": { + "type": "object", + "properties": { + "title": { "type": "string" } + } + }, + "SemanticModelMetadata": { + "type": "object", + "properties": { + "similarity_function": { "type": "string" } + } + } + } + } + } + """; + + var result = GetSuccessResult( + OpenApiCodeGenerator.Generate( + specWithAnyOf, + "TestApi", + "TestApiExtensions", + Path.GetTempPath() + ) + ); + + // Verify anyOf properties are correctly typed - THIS PROVES BUG #142 IS FIXED + Assert.IsTrue(result.ModelsCode.Contains("public record KnowledgeBoxObj(")); + Assert.IsTrue(result.ModelsCode.Contains("string? Slug"), $"Expected 'string? Slug' but got: {result.ModelsCode}"); + Assert.IsTrue(result.ModelsCode.Contains("string Uuid"), $"Expected 'string Uuid' but got: {result.ModelsCode}"); + Assert.IsTrue(result.ModelsCode.Contains("KnowledgeBoxConfig? Config"), $"Expected 'KnowledgeBoxConfig? Config' but got: {result.ModelsCode}"); + Assert.IsTrue(result.ModelsCode.Contains("SemanticModelMetadata? Model"), $"Expected 'SemanticModelMetadata? Model' but got: {result.ModelsCode}"); + Assert.IsFalse(result.ModelsCode.Contains("object Slug"), "Should not have 'object Slug'"); + Assert.IsFalse(result.ModelsCode.Contains("object Config"), "Should not have 'object Config'"); + Assert.IsFalse(result.ModelsCode.Contains("object Model"), "Should not have 'object Model'"); + } + + [TestMethod] + public void Generate_HandlesAnyOfWithInteger() + { + var spec = """ + { + "openapi": "3.0.0", + "info": { "title": "Test API", "version": "1.0.0" }, + "servers": [{ "url": "https://api.test.com" }], + "paths": { + "/resource": { + "get": { + "operationId": "getResource", + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Resource" + } + } + } + } + } + } + } + }, + "components": { + "schemas": { + "Resource": { + "type": "object", + "properties": { + "count": { + "anyOf": [ + { "type": "integer" }, + { "type": "null" } + ] + } + } + } + } + } + } + """; + + var result = GetSuccessResult( + OpenApiCodeGenerator.Generate(spec, "TestApi", "TestApiExtensions", Path.GetTempPath()) + ); + + Assert.IsTrue(result.ModelsCode.Contains("int? Count")); + Assert.IsFalse(result.ModelsCode.Contains("object Count")); + } + + [TestMethod] + public void Generate_HandlesArrayOfIntegers() + { + var spec = """ + { + "openapi": "3.0.0", + "info": { "title": "Test API", "version": "1.0.0" }, + "servers": [{ "url": "https://api.test.com" }], + "paths": { + "/numbers": { + "get": { + "operationId": "getNumbers", + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "integer" + } + } + } + } + } + } + } + } + } + } + """; + + var result = GetSuccessResult( + OpenApiCodeGenerator.Generate(spec, "TestApi", "TestApiExtensions", Path.GetTempPath()) + ); + + Assert.IsTrue(result.ExtensionMethodsCode.Contains("Result,")); + } + + [TestMethod] + public void Generate_HandlesInt64Format() + { + var spec = """ + { + "openapi": "3.0.0", + "info": { "title": "Test API", "version": "1.0.0" }, + "servers": [{ "url": "https://api.test.com" }], + "paths": { + "/resource/{id}": { + "get": { + "operationId": "getResource", + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Resource" + } + } + } + } + } + } + } + }, + "components": { + "schemas": { + "Resource": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int64" + } + } + } + } + } + } + """; + + var result = GetSuccessResult( + OpenApiCodeGenerator.Generate(spec, "TestApi", "TestApiExtensions", Path.GetTempPath()) + ); + + Assert.IsTrue(result.ModelsCode.Contains("long Id")); + Assert.IsTrue(result.ExtensionMethodsCode.Contains("long id")); + } + + [TestMethod] + public void Generate_HandlesDoubleFormat() + { + var spec = """ + { + "openapi": "3.0.0", + "info": { "title": "Test API", "version": "1.0.0" }, + "servers": [{ "url": "https://api.test.com" }], + "paths": { + "/resource": { + "get": { + "operationId": "getResource", + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Resource" + } + } + } + } + } + } + } + }, + "components": { + "schemas": { + "Resource": { + "type": "object", + "properties": { + "price": { + "type": "number", + "format": "double" + }, + "rating": { + "type": "number" + } + } + } + } + } + } + """; + + var result = GetSuccessResult( + OpenApiCodeGenerator.Generate(spec, "TestApi", "TestApiExtensions", Path.GetTempPath()) + ); + + Assert.IsTrue(result.ModelsCode.Contains("double Price")); + Assert.IsTrue(result.ModelsCode.Contains("float Rating")); + } + + [TestMethod] + public void Generate_HandlesBooleanType() + { + var spec = """ + { + "openapi": "3.0.0", + "info": { "title": "Test API", "version": "1.0.0" }, + "servers": [{ "url": "https://api.test.com" }], + "paths": { + "/resource": { + "get": { + "operationId": "getResource", + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Resource" + } + } + } + } + } + } + } + }, + "components": { + "schemas": { + "Resource": { + "type": "object", + "properties": { + "isActive": { + "type": "boolean" + } + } + } + } + } + } + """; + + var result = GetSuccessResult( + OpenApiCodeGenerator.Generate(spec, "TestApi", "TestApiExtensions", Path.GetTempPath()) + ); + + Assert.IsTrue(result.ModelsCode.Contains("bool IsActive")); + } + + [TestMethod] + public void Generate_SkipsStringEnums() + { + var spec = """ + { + "openapi": "3.0.0", + "info": { "title": "Test API", "version": "1.0.0" }, + "servers": [{ "url": "https://api.test.com" }], + "paths": { + "/resource": { + "get": { + "operationId": "getResource", + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Resource" + } + } + } + } + } + } + } + }, + "components": { + "schemas": { + "Status": { + "type": "string", + "enum": ["active", "inactive", "pending"] + }, + "Resource": { + "type": "object", + "properties": { + "status": { + "$ref": "#/components/schemas/Status" + } + } + } + } + } + } + """; + + var result = GetSuccessResult( + OpenApiCodeGenerator.Generate(spec, "TestApi", "TestApiExtensions", Path.GetTempPath()) + ); + + // String enums should not generate records, and references should map to string + Assert.IsFalse(result.ModelsCode.Contains("public record Status")); + Assert.IsTrue(result.ModelsCode.Contains("string Status")); + } + + [TestMethod] + public void Generate_HandlesArrayOfReferences() + { + var spec = """ + { + "openapi": "3.0.0", + "info": { "title": "Test API", "version": "1.0.0" }, + "servers": [{ "url": "https://api.test.com" }], + "paths": { + "/items": { + "get": { + "operationId": "getItems", + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Item" + } + } + } + } + } + } + } + } + }, + "components": { + "schemas": { + "Item": { + "type": "object", + "properties": { + "name": { + "type": "string" + } + } + } + } + } + } + """; + + var result = GetSuccessResult( + OpenApiCodeGenerator.Generate(spec, "TestApi", "TestApiExtensions", Path.GetTempPath()) + ); + + Assert.IsTrue(result.ExtensionMethodsCode.Contains("Result,")); + } + + [TestMethod] + public void Generate_HandlesComplexNestedStructures() + { + var spec = """ + { + "openapi": "3.0.0", + "info": { "title": "Test API", "version": "1.0.0" }, + "servers": [{ "url": "https://api.test.com" }], + "paths": { + "/order": { + "get": { + "operationId": "getOrder", + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Order" + } + } + } + } + } + } + } + }, + "components": { + "schemas": { + "Order": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int64" + }, + "customer": { + "$ref": "#/components/schemas/Customer" + }, + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/OrderItem" + } + }, + "total": { + "type": "number", + "format": "double" + } + } + }, + "Customer": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "email": { + "type": "string" + } + } + }, + "OrderItem": { + "type": "object", + "properties": { + "productId": { + "type": "integer" + }, + "quantity": { + "type": "integer" + }, + "price": { + "type": "number" + } + } + } + } + } + } + """; + + var result = GetSuccessResult( + OpenApiCodeGenerator.Generate(spec, "TestApi", "TestApiExtensions", Path.GetTempPath()) + ); + + // Verify Order model + Assert.IsTrue(result.ModelsCode.Contains("public record Order(")); + Assert.IsTrue(result.ModelsCode.Contains("long Id")); + Assert.IsTrue(result.ModelsCode.Contains("Customer Customer")); + Assert.IsTrue(result.ModelsCode.Contains("List Items")); + Assert.IsTrue(result.ModelsCode.Contains("double Total")); + + // Verify Customer model + Assert.IsTrue(result.ModelsCode.Contains("public record Customer(")); + Assert.IsTrue(result.ModelsCode.Contains("string Name")); + Assert.IsTrue(result.ModelsCode.Contains("string Email")); + + // Verify OrderItem model + Assert.IsTrue(result.ModelsCode.Contains("public record OrderItem(")); + Assert.IsTrue(result.ModelsCode.Contains("int ProductId")); + Assert.IsTrue(result.ModelsCode.Contains("int Quantity")); + Assert.IsTrue(result.ModelsCode.Contains("float Price")); + } + + [TestMethod] + public void Generate_HandlesPutMethod() + { + var spec = """ + { + "openapi": "3.0.0", + "info": { "title": "Test API", "version": "1.0.0" }, + "servers": [{ "url": "https://api.test.com" }], + "paths": { + "/pets/{petId}": { + "put": { + "operationId": "updatePet", + "parameters": [ + { + "name": "petId", + "in": "path", + "required": true, + "schema": { + "type": "integer" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + } + }, + "components": { + "schemas": { + "Pet": { + "type": "object", + "properties": { + "name": { + "type": "string" + } + } + } + } + } + } + """; + + var result = GetSuccessResult( + OpenApiCodeGenerator.Generate(spec, "TestApi", "TestApiExtensions", Path.GetTempPath()) + ); + + Assert.IsTrue(result.ExtensionMethodsCode.Contains("UpdatePet")); + Assert.IsTrue(result.ExtensionMethodsCode.Contains("CreatePut")); + } + + [TestMethod] + public void Generate_HandlesPatchMethod() + { + var spec = """ + { + "openapi": "3.0.0", + "info": { "title": "Test API", "version": "1.0.0" }, + "servers": [{ "url": "https://api.test.com" }], + "paths": { + "/pets/{petId}": { + "patch": { + "operationId": "patchPet", + "parameters": [ + { + "name": "petId", + "in": "path", + "required": true, + "schema": { + "type": "integer" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PetUpdate" + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + } + }, + "components": { + "schemas": { + "Pet": { + "type": "object", + "properties": { + "name": { + "type": "string" + } + } + }, + "PetUpdate": { + "type": "object", + "properties": { + "name": { + "type": "string" + } + } + } + } + } + } + """; + + var result = GetSuccessResult( + OpenApiCodeGenerator.Generate(spec, "TestApi", "TestApiExtensions", Path.GetTempPath()) + ); + + Assert.IsTrue(result.ExtensionMethodsCode.Contains("PatchPet")); + Assert.IsTrue(result.ExtensionMethodsCode.Contains("CreatePatch")); + } + + [TestMethod] + public void Generate_HandlesOptionalQueryParameters() + { + var spec = """ + { + "openapi": "3.0.0", + "info": { "title": "Test API", "version": "1.0.0" }, + "servers": [{ "url": "https://api.test.com" }], + "paths": { + "/pets": { + "get": { + "operationId": "listPets", + "parameters": [ + { + "name": "limit", + "in": "query", + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "offset", + "in": "query", + "required": false, + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "description": "Success" + } + } + } + } + } + } + """; + + var result = GetSuccessResult( + OpenApiCodeGenerator.Generate(spec, "TestApi", "TestApiExtensions", Path.GetTempPath()) + ); + + Assert.IsTrue(result.ExtensionMethodsCode.Contains("int? limit")); + Assert.IsTrue(result.ExtensionMethodsCode.Contains("int? offset")); + Assert.IsTrue(result.ExtensionMethodsCode.Contains("BuildQueryString")); + } + + [TestMethod] + public void Generate_HandlesHeaderParameters() + { + var spec = """ + { + "openapi": "3.0.0", + "info": { "title": "Test API", "version": "1.0.0" }, + "servers": [{ "url": "https://api.test.com" }], + "paths": { + "/pets": { + "get": { + "operationId": "listPets", + "parameters": [ + { + "name": "X-API-Key", + "in": "header", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success" + } + } + } + } + } + } + """; + + var result = GetSuccessResult( + OpenApiCodeGenerator.Generate(spec, "TestApi", "TestApiExtensions", Path.GetTempPath()) + ); + + // Just verify it compiled and generated - the actual parameter handling is implementation detail + Assert.IsFalse(string.IsNullOrEmpty(result.ExtensionMethodsCode)); + Assert.IsTrue(result.ExtensionMethodsCode.Contains("ListPets")); + } + + [TestMethod] + public void Generate_HandlesPathAndQueryParametersCombined() + { + var spec = """ + { + "openapi": "3.0.0", + "info": { "title": "Test API", "version": "1.0.0" }, + "servers": [{ "url": "https://api.test.com" }], + "paths": { + "/pets/{petId}/friends": { + "get": { + "operationId": "getPetFriends", + "parameters": [ + { + "name": "petId", + "in": "path", + "required": true, + "schema": { + "type": "integer" + } + }, + { + "name": "limit", + "in": "query", + "required": false, + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "description": "Success" + } + } + } + } + } + } + """; + + var result = GetSuccessResult( + OpenApiCodeGenerator.Generate(spec, "TestApi", "TestApiExtensions", Path.GetTempPath()) + ); + + Assert.IsTrue(result.ExtensionMethodsCode.Contains("petId")); + Assert.IsTrue(result.ExtensionMethodsCode.Contains("limit")); + } + + [TestMethod] + public void Generate_HandlesMultilineDescriptions() + { + var spec = """ + { + "openapi": "3.0.0", + "info": { "title": "Test API", "version": "1.0.0" }, + "servers": [{ "url": "https://api.test.com" }], + "paths": { + "/pets": { + "get": { + "operationId": "listPets", + "description": "List all pets\n\n---\n\nReturns a paginated list of pets", + "responses": { + "200": { + "description": "Success" + } + } + } + } + } + } + """; + + var result = GetSuccessResult( + OpenApiCodeGenerator.Generate(spec, "TestApi", "TestApiExtensions", Path.GetTempPath()) + ); + + // Should only include the summary before the --- separator + Assert.IsTrue(result.ExtensionMethodsCode.Contains("/// List all pets")); + Assert.IsFalse(result.ExtensionMethodsCode.Contains("Returns a paginated list")); + } + + [TestMethod] + public void Generate_HandlesNoPathParameters() + { + var spec = """ + { + "openapi": "3.0.0", + "info": { "title": "Test API", "version": "1.0.0" }, + "servers": [{ "url": "https://api.test.com" }], + "paths": { + "/health": { + "get": { + "operationId": "getHealth", + "responses": { + "200": { + "description": "Success" + } + } + } + } + } + } + """; + + var result = GetSuccessResult( + OpenApiCodeGenerator.Generate(spec, "TestApi", "TestApiExtensions", Path.GetTempPath()) + ); + + Assert.IsTrue(result.ExtensionMethodsCode.Contains("GetHealth")); + Assert.IsTrue(result.ExtensionMethodsCode.Contains("Unit.Value")); + } + + [TestMethod] + public void Generate_HandlesDefaultParameterValues() + { + var spec = """ + { + "openapi": "3.0.0", + "info": { "title": "Test API", "version": "1.0.0" }, + "servers": [{ "url": "https://api.test.com" }], + "paths": { + "/pets": { + "get": { + "operationId": "listPets", + "parameters": [ + { + "name": "limit", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "default": 10 + } + } + ], + "responses": { + "200": { + "description": "Success" + } + } + } + } + } + } + """; + + var result = GetSuccessResult( + OpenApiCodeGenerator.Generate(spec, "TestApi", "TestApiExtensions", Path.GetTempPath()) + ); + + Assert.IsTrue(result.ExtensionMethodsCode.Contains("limit = 10")); + } + + [TestMethod] + public void Generate_SanitizesParameterNames() + { + var spec = """ + { + "openapi": "3.0.0", + "info": { "title": "Test API", "version": "1.0.0" }, + "servers": [{ "url": "https://api.test.com" }], + "paths": { + "/pets/{pet_id}": { + "get": { + "operationId": "getPet", + "parameters": [ + { + "name": "pet_id", + "in": "path", + "required": true, + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "description": "Success" + } + } + } + } + } + } + """; + + var result = GetSuccessResult( + OpenApiCodeGenerator.Generate(spec, "TestApi", "TestApiExtensions", Path.GetTempPath()) + ); + + // Parameter name should be converted to camelCase + Assert.IsTrue(result.ExtensionMethodsCode.Contains("int petId")); + // But path template should preserve original name + Assert.IsTrue(result.ExtensionMethodsCode.Contains("{petId}")); + } + + [TestMethod] + public void Generate_HandlesOperationWithoutOperationId() + { + var spec = """ + { + "openapi": "3.0.0", + "info": { "title": "Test API", "version": "1.0.0" }, + "servers": [{ "url": "https://api.test.com" }], + "paths": { + "/pets": { + "get": { + "responses": { + "200": { + "description": "Success" + } + } + } + } + } + } + """; + + var result = GetSuccessResult( + OpenApiCodeGenerator.Generate(spec, "TestApi", "TestApiExtensions", Path.GetTempPath()) + ); + + // Should generate method name from path and HTTP method + Assert.IsTrue(result.ExtensionMethodsCode.Contains("GetPets")); + } + + [TestMethod] + public void Generate_HandlesMultipleResponseTypes() + { + var spec = """ + { + "openapi": "3.0.0", + "info": { "title": "Test API", "version": "1.0.0" }, + "servers": [{ "url": "https://api.test.com" }], + "paths": { + "/pets": { + "get": { + "operationId": "listPets", + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + } + } + } + }, + "components": { + "schemas": { + "Pet": { + "type": "object", + "properties": { + "name": { "type": "string" } + } + }, + "Error": { + "type": "object", + "properties": { + "message": { "type": "string" } + } + } + } + } + } + """; + + var result = GetSuccessResult( + OpenApiCodeGenerator.Generate(spec, "TestApi", "TestApiExtensions", Path.GetTempPath()) + ); + + Assert.IsTrue(result.ExtensionMethodsCode.Contains("Result")); + } + + [TestMethod] + public void Generate_HandlesEmptyResponseContent() + { + var spec = """ + { + "openapi": "3.0.0", + "info": { "title": "Test API", "version": "1.0.0" }, + "servers": [{ "url": "https://api.test.com" }], + "paths": { + "/pets/{petId}": { + "delete": { + "operationId": "deletePet", + "parameters": [ + { + "name": "petId", + "in": "path", + "required": true, + "schema": { + "type": "integer" + } + } + ], + "responses": { + "204": { + "description": "Deleted" + } + } + } + } + } + } + """; + + var result = GetSuccessResult( + OpenApiCodeGenerator.Generate(spec, "TestApi", "TestApiExtensions", Path.GetTempPath()) + ); + + Assert.IsTrue(result.ExtensionMethodsCode.Contains("DeletePet")); + Assert.IsTrue(result.ExtensionMethodsCode.Contains("CreateDelete")); + } + + [TestMethod] + public void Generate_HandlesRequiredHeaderParameters() + { + var spec = """ + { + "openapi": "3.0.0", + "info": { "title": "Test API", "version": "1.0.0" }, + "servers": [{ "url": "https://api.test.com" }], + "paths": { + "/pets": { + "get": { + "operationId": "listPets", + "parameters": [ + { + "name": "Authorization", + "in": "header", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "X-Request-ID", + "in": "header", + "required": false, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success" + } + } + } + } + } + } + """; + + var result = GetSuccessResult( + OpenApiCodeGenerator.Generate(spec, "TestApi", "TestApiExtensions", Path.GetTempPath()) + ); + + Assert.IsTrue(result.ExtensionMethodsCode.Contains("authorization"), "Should contain 'authorization'"); + Assert.IsTrue(result.ExtensionMethodsCode.Contains("xRequestID"), "Should contain 'xRequestID'"); + } + + [TestMethod] + public void Generate_HandlesStringDefaultValues() + { + var spec = """ + { + "openapi": "3.0.0", + "info": { "title": "Test API", "version": "1.0.0" }, + "servers": [{ "url": "https://api.test.com" }], + "paths": { + "/search": { + "get": { + "operationId": "search", + "parameters": [ + { + "name": "query", + "in": "query", + "required": false, + "schema": { + "type": "string", + "default": "test" + } + } + ], + "responses": { + "200": { + "description": "Success" + } + } + } + } + } + } + """; + + var result = GetSuccessResult( + OpenApiCodeGenerator.Generate(spec, "TestApi", "TestApiExtensions", Path.GetTempPath()) + ); + + Assert.IsTrue(result.ExtensionMethodsCode.Contains("query = \"test\"")); + } + + [TestMethod] + public void Generate_HandlesOperationWithOnlyErrorResponse() + { + var spec = """ + { + "openapi": "3.0.0", + "info": { "title": "Test API", "version": "1.0.0" }, + "servers": [{ "url": "https://api.test.com" }], + "paths": { + "/test": { + "get": { + "operationId": "testOp", + "responses": { + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + } + } + } + }, + "components": { + "schemas": { + "Error": { + "type": "object", + "properties": { + "message": { "type": "string" } + } + } + } + } + } + """; + + var result = GetSuccessResult( + OpenApiCodeGenerator.Generate(spec, "TestApi", "TestApiExtensions", Path.GetTempPath()) + ); + + Assert.IsTrue(result.ExtensionMethodsCode.Contains("TestOp")); + } + + [TestMethod] + public void Generate_HandlesRequiredQueryParameters() + { + var spec = """ + { + "openapi": "3.0.0", + "info": { "title": "Test API", "version": "1.0.0" }, + "servers": [{ "url": "https://api.test.com" }], + "paths": { + "/search": { + "get": { + "operationId": "search", + "parameters": [ + { + "name": "query", + "in": "query", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success" + } + } + } + } + } + } + """; + + var result = GetSuccessResult( + OpenApiCodeGenerator.Generate(spec, "TestApi", "TestApiExtensions", Path.GetTempPath()) + ); + + // Required query params should not be nullable + Assert.IsTrue(result.ExtensionMethodsCode.Contains("string query")); + Assert.IsFalse(result.ExtensionMethodsCode.Contains("string? query")); + } + + [TestMethod] + public void Generate_HandlesPostWithoutRequestBody() + { + var spec = """ + { + "openapi": "3.0.0", + "info": { "title": "Test API", "version": "1.0.0" }, + "servers": [{ "url": "https://api.test.com" }], + "paths": { + "/action": { + "post": { + "operationId": "performAction", + "responses": { + "200": { + "description": "Success" + } + } + } + } + } + } + """; + + var result = GetSuccessResult( + OpenApiCodeGenerator.Generate(spec, "TestApi", "TestApiExtensions", Path.GetTempPath()) + ); + + Assert.IsTrue(result.ExtensionMethodsCode.Contains("PerformAction")); + Assert.IsTrue(result.ExtensionMethodsCode.Contains("CreatePost")); + } + + [TestMethod] + public void Generate_HandlesBooleanDefaultValue() + { + var spec = """ + { + "openapi": "3.0.0", + "info": { "title": "Test API", "version": "1.0.0" }, + "servers": [{ "url": "https://api.test.com" }], + "paths": { + "/items": { + "get": { + "operationId": "listItems", + "parameters": [ + { + "name": "includeDeleted", + "in": "query", + "required": false, + "schema": { + "type": "boolean", + "default": false + } + } + ], + "responses": { + "200": { + "description": "Success" + } + } + } + } + } + } + """; + + var result = GetSuccessResult( + OpenApiCodeGenerator.Generate(spec, "TestApi", "TestApiExtensions", Path.GetTempPath()) + ); + + Assert.IsTrue(result.ExtensionMethodsCode.Contains("includeDeleted = false")); + } + + [TestMethod] + public void Generate_HandlesPathWithMultipleOperations() + { + var spec = """ + { + "openapi": "3.0.0", + "info": { "title": "Test API", "version": "1.0.0" }, + "servers": [{ "url": "https://api.test.com" }], + "paths": { + "/pets/{petId}": { + "get": { + "operationId": "getPet", + "parameters": [ + { + "name": "petId", + "in": "path", + "required": true, + "schema": { "type": "integer" } + } + ], + "responses": { + "200": { "description": "Success" } + } + }, + "put": { + "operationId": "updatePet", + "parameters": [ + { + "name": "petId", + "in": "path", + "required": true, + "schema": { "type": "integer" } + } + ], + "responses": { + "200": { "description": "Success" } + } + }, + "delete": { + "operationId": "deletePet", + "parameters": [ + { + "name": "petId", + "in": "path", + "required": true, + "schema": { "type": "integer" } + } + ], + "responses": { + "204": { "description": "Deleted" } + } + } + } + } + } + """; + + var result = GetSuccessResult( + OpenApiCodeGenerator.Generate(spec, "TestApi", "TestApiExtensions", Path.GetTempPath()) + ); + + Assert.IsTrue(result.ExtensionMethodsCode.Contains("GetPet")); + Assert.IsTrue(result.ExtensionMethodsCode.Contains("UpdatePet")); + Assert.IsTrue(result.ExtensionMethodsCode.Contains("DeletePet")); + } } diff --git a/RestClient.Net.OpenApiGenerator.Tests/RestClient.Net.OpenApiGenerator.Tests.csproj b/RestClient.Net.OpenApiGenerator.Tests/RestClient.Net.OpenApiGenerator.Tests.csproj index 4a963d6d..1d62fbc5 100644 --- a/RestClient.Net.OpenApiGenerator.Tests/RestClient.Net.OpenApiGenerator.Tests.csproj +++ b/RestClient.Net.OpenApiGenerator.Tests/RestClient.Net.OpenApiGenerator.Tests.csproj @@ -9,6 +9,7 @@ + diff --git a/RestClient.Net.OpenApiGenerator/ModelGenerator.cs b/RestClient.Net.OpenApiGenerator/ModelGenerator.cs index 16c91c1d..64533ee8 100644 --- a/RestClient.Net.OpenApiGenerator/ModelGenerator.cs +++ b/RestClient.Net.OpenApiGenerator/ModelGenerator.cs @@ -33,6 +33,7 @@ public static string GenerateModels(OpenApiDocument document, string @namespace) var modelsCode = string.Join("\n\n", models); return $$""" + #nullable enable namespace {{@namespace}}; {{modelsCode}} @@ -131,6 +132,25 @@ public static string MapOpenApiType( return "object"; } + // Handle anyOf schemas + if (schemaObj.AnyOf != null && schemaObj.AnyOf.Count > 0) + { + // Filter out null types and get the first non-null type + // Handle both OpenApiSchema with Type != Null and OpenApiSchemaReference + var nonNullSchema = schemaObj.AnyOf.FirstOrDefault(s => + s is OpenApiSchemaReference + || (s is OpenApiSchema os && os.Type != JsonSchemaType.Null) + ); + + if (nonNullSchema != null) + { + // Recursively resolve the type + var baseType = MapOpenApiType(nonNullSchema, schemas); + // Make it nullable since it's in an anyOf with null + return baseType.EndsWith('?') ? baseType : $"{baseType}?"; + } + } + // Handle arrays if (schemaObj.Type == JsonSchemaType.Array) { diff --git a/Samples/NucliaDbClient/Generated/NucliaDBApiExtensions.g.cs b/Samples/NucliaDbClient/Generated/NucliaDBApiExtensions.g.cs index 5f761e89..b82b8c2d 100644 --- a/Samples/NucliaDbClient/Generated/NucliaDBApiExtensions.g.cs +++ b/Samples/NucliaDbClient/Generated/NucliaDBApiExtensions.g.cs @@ -57,7 +57,7 @@ public static Task>> AskK /// List resources of a Knowledge Box public static Task>> CatalogGetKbKbidCatalogAsync( this HttpClient httpClient, - string kbid, string query = "", object? filterExpression = null, List? filters = null, List? faceted = null, string sortField = "", object? sortLimit = null, string sortOrder = "desc", int pageNumber = 0, int pageSize = 20, object? withStatus = null, object? rangeCreationStart = null, object? rangeCreationEnd = null, object? rangeModificationStart = null, object? rangeModificationEnd = null, object? hidden = null, List? show = null, + string kbid, string query = "", string? filterExpression = null, List? filters = null, List? faceted = null, string sortField = "", int? sortLimit = null, string sortOrder = "desc", int pageNumber = 0, int pageSize = 20, string? withStatus = null, string? rangeCreationStart = null, string? rangeCreationEnd = null, string? rangeModificationStart = null, string? rangeModificationEnd = null, bool? hidden = null, List? show = null, CancellationToken cancellationToken = default ) => _catalogGetKbKbidCatalogAsync(httpClient, (kbid, query, filterExpression, filters, faceted, sortField, sortLimit, sortOrder, pageNumber, pageSize, withStatus, rangeCreationStart, rangeCreationEnd, rangeModificationStart, rangeModificationEnd, hidden, show), cancellationToken); @@ -211,7 +211,7 @@ public static Task>> SendFeedbackE /// Find on a Knowledge Box public static Task>> FindKnowledgeboxKbKbidFindAsync( this HttpClient httpClient, - string kbid, string query = "", object? filterExpression = null, List? fields = null, List? filters = null, object? topK = null, object? minScore = null, object? minScoreSemantic = null, float minScoreBm25 = 0, object? vectorset = null, object? rangeCreationStart = null, object? rangeCreationEnd = null, object? rangeModificationStart = null, object? rangeModificationEnd = null, List? features = null, bool debug = false, bool highlight = false, List? show = null, List? fieldType = null, List? extracted = null, bool withDuplicates = false, bool withSynonyms = false, bool autofilter = false, List? securityGroups = null, bool showHidden = false, string rankFusion = "rrf", object? reranker = null, object? searchConfiguration = null, string xNdbClient = "api", string? xNucliadbUser = null, string? xForwardedFor = null, + string kbid, string query = "", string? filterExpression = null, List? fields = null, List? filters = null, int? topK = null, float? minScore = null, float? minScoreSemantic = null, float minScoreBm25 = 0, string? vectorset = null, string? rangeCreationStart = null, string? rangeCreationEnd = null, string? rangeModificationStart = null, string? rangeModificationEnd = null, List? features = null, bool debug = false, bool highlight = false, List? show = null, List? fieldType = null, List? extracted = null, bool withDuplicates = false, bool withSynonyms = false, bool autofilter = false, List? securityGroups = null, bool showHidden = false, string rankFusion = "rrf", string? reranker = null, string? searchConfiguration = null, string xNdbClient = "api", string? xNucliadbUser = null, string? xForwardedFor = null, CancellationToken cancellationToken = default ) => _findKnowledgeboxKbKbidFindAsync(httpClient, (kbid, query, filterExpression, fields, filters, topK, minScore, minScoreSemantic, minScoreBm25, vectorset, rangeCreationStart, rangeCreationEnd, rangeModificationStart, rangeModificationEnd, features, debug, highlight, show, fieldType, extracted, withDuplicates, withSynonyms, autofilter, securityGroups, showHidden, rankFusion, reranker, searchConfiguration, xNdbClient, xNucliadbUser, xForwardedFor), cancellationToken); @@ -330,14 +330,14 @@ public static Task>> PredictProxyE /// Provides the status of the processing of the given Knowledge Box. public static Task>> ProcessingStatusKbKbidProcessingStatusAsync( this HttpClient httpClient, - string kbid, object? cursor = null, object? scheduled = null, int limit = 20, + string kbid, string? cursor = null, bool? scheduled = null, int limit = 20, CancellationToken cancellationToken = default ) => _processingStatusKbKbidProcessingStatusAsync(httpClient, (kbid, cursor, scheduled, limit), cancellationToken); /// --- ## Authorization roles Authenticated user needs to fulfill one of this roles, otherwise the request will be rejected with a `403` response. - `WRITER` public static Task>> TusPostRidPrefixKbKbidResourcePathRidFileFieldTusuploadAsync( this HttpClient httpClient, - string kbid, string pathRid, string field, object body, object? xExtractStrategy = null, object? xSplitStrategy = null, + string kbid, string pathRid, string field, object body, string? xExtractStrategy = null, string? xSplitStrategy = null, CancellationToken cancellationToken = default ) => _tusPostRidPrefixKbKbidResourcePathRidFileFieldTusuploadAsync(httpClient, (kbid, pathRid, field, xExtractStrategy, xSplitStrategy, body), cancellationToken); @@ -351,7 +351,7 @@ public static Task>> UploadInforma /// Upload a file as a field on an existing resource, if the field exists will return a conflict (419) public static Task>> UploadRidPrefixKbKbidResourcePathRidFileFieldUploadAsync( this HttpClient httpClient, - string kbid, string pathRid, string field, object body, object? xFilename = null, object? xPassword = null, object? xLanguage = null, object? xMd5 = null, object? xExtractStrategy = null, object? xSplitStrategy = null, + string kbid, string pathRid, string field, object body, string? xFilename = null, string? xPassword = null, string? xLanguage = null, string? xMd5 = null, string? xExtractStrategy = null, string? xSplitStrategy = null, CancellationToken cancellationToken = default ) => _uploadRidPrefixKbKbidResourcePathRidFileFieldUploadAsync(httpClient, (kbid, pathRid, field, xFilename, xPassword, xLanguage, xMd5, xExtractStrategy, xSplitStrategy, body), cancellationToken); @@ -421,7 +421,7 @@ public static Task>> DownloadField /// --- ## Authorization roles Authenticated user needs to fulfill one of this roles, otherwise the request will be rejected with a `403` response. - `WRITER` public static Task>> ReprocessFileFieldKbKbidResourceRidFileFieldIdReprocessAsync( this HttpClient httpClient, - string kbid, string rid, string fieldId, object body, bool resetTitle = false, string? xNucliadbUser = null, object? xFilePassword = null, + string kbid, string rid, string fieldId, object body, bool resetTitle = false, string? xNucliadbUser = null, string? xFilePassword = null, CancellationToken cancellationToken = default ) => _reprocessFileFieldKbKbidResourceRidFileFieldIdReprocessAsync(httpClient, (kbid, rid, fieldId, resetTitle, xNucliadbUser, xFilePassword, body), cancellationToken); @@ -463,7 +463,7 @@ public static Task /// Search on a single resource public static Task>> ResourceSearchKbKbidResourceRidSearchAsync( this HttpClient httpClient, - string kbid, string rid, string query, object? filterExpression = null, List? fields = null, List? filters = null, List? faceted = null, object? sortField = null, string sortOrder = "desc", object? topK = null, object? rangeCreationStart = null, object? rangeCreationEnd = null, object? rangeModificationStart = null, object? rangeModificationEnd = null, bool highlight = false, bool debug = false, string xNdbClient = "api", + string kbid, string rid, string query, string? filterExpression = null, List? fields = null, List? filters = null, List? faceted = null, string? sortField = null, string sortOrder = "desc", int? topK = null, string? rangeCreationStart = null, string? rangeCreationEnd = null, string? rangeModificationStart = null, string? rangeModificationEnd = null, bool highlight = false, bool debug = false, string xNdbClient = "api", CancellationToken cancellationToken = default ) => _resourceSearchKbKbidResourceRidSearchAsync(httpClient, (kbid, rid, query, filterExpression, fields, filters, faceted, sortField, sortOrder, topK, rangeCreationStart, rangeCreationEnd, rangeModificationStart, rangeModificationEnd, highlight, debug, xNdbClient), cancellationToken); @@ -484,7 +484,7 @@ public static Task>> ResourceFieldRi /// --- ## Authorization roles Authenticated user needs to fulfill one of this roles, otherwise the request will be rejected with a `403` response. - `READER` public static Task>> ResourceFieldRidPrefixKbKbidResourceRidFieldTypeFieldIdGetAsync( this HttpClient httpClient, - string kbid, string rid, string fieldType, string fieldId, List? show = null, List? extracted = null, object? page = null, + string kbid, string rid, string fieldType, string fieldId, List? show = null, List? extracted = null, string? page = null, CancellationToken cancellationToken = default ) => _resourceFieldRidPrefixKbKbidResourceRidFieldTypeFieldIdGetAsync(httpClient, (kbid, rid, fieldType, fieldId, show, extracted, page), cancellationToken); @@ -519,7 +519,7 @@ public static Task>> SchemaForConf /// Search on a Knowledge Box and retrieve separate results for documents, paragraphs, and sentences. Usually, it is better to use `find` public static Task>> SearchKnowledgeboxKbKbidSearchAsync( this HttpClient httpClient, - string kbid, string query = "", object? filterExpression = null, List? fields = null, List? filters = null, List? faceted = null, string sortField = "", object? sortLimit = null, string sortOrder = "desc", int topK = 20, object? minScore = null, object? minScoreSemantic = null, float minScoreBm25 = 0, object? vectorset = null, object? rangeCreationStart = null, object? rangeCreationEnd = null, object? rangeModificationStart = null, object? rangeModificationEnd = null, List? features = null, bool debug = false, bool highlight = false, List? show = null, List? fieldType = null, List? extracted = null, bool withDuplicates = false, bool withSynonyms = false, bool autofilter = false, List? securityGroups = null, bool showHidden = false, string xNdbClient = "api", string? xNucliadbUser = null, string? xForwardedFor = null, + string kbid, string query = "", string? filterExpression = null, List? fields = null, List? filters = null, List? faceted = null, string sortField = "", int? sortLimit = null, string sortOrder = "desc", int topK = 20, float? minScore = null, float? minScoreSemantic = null, float minScoreBm25 = 0, string? vectorset = null, string? rangeCreationStart = null, string? rangeCreationEnd = null, string? rangeModificationStart = null, string? rangeModificationEnd = null, List? features = null, bool debug = false, bool highlight = false, List? show = null, List? fieldType = null, List? extracted = null, bool withDuplicates = false, bool withSynonyms = false, bool autofilter = false, List? securityGroups = null, bool showHidden = false, string xNdbClient = "api", string? xNucliadbUser = null, string? xForwardedFor = null, CancellationToken cancellationToken = default ) => _searchKnowledgeboxKbKbidSearchAsync(httpClient, (kbid, query, filterExpression, fields, filters, faceted, sortField, sortLimit, sortOrder, topK, minScore, minScoreSemantic, minScoreBm25, vectorset, rangeCreationStart, rangeCreationEnd, rangeModificationStart, rangeModificationEnd, features, debug, highlight, show, fieldType, extracted, withDuplicates, withSynonyms, autofilter, securityGroups, showHidden, xNdbClient, xNucliadbUser, xForwardedFor), cancellationToken); @@ -624,7 +624,7 @@ public static Task>> DownloadField /// --- ## Authorization roles Authenticated user needs to fulfill one of this roles, otherwise the request will be rejected with a `403` response. - `WRITER` public static Task>> TusPostRslugPrefixKbKbidSlugRslugFileFieldTusuploadAsync( this HttpClient httpClient, - string kbid, string rslug, string field, object body, object? xExtractStrategy = null, object? xSplitStrategy = null, + string kbid, string rslug, string field, object body, string? xExtractStrategy = null, string? xSplitStrategy = null, CancellationToken cancellationToken = default ) => _tusPostRslugPrefixKbKbidSlugRslugFileFieldTusuploadAsync(httpClient, (kbid, rslug, field, xExtractStrategy, xSplitStrategy, body), cancellationToken); @@ -645,7 +645,7 @@ public static Task>> UploadInforma /// Upload a file as a field on an existing resource, if the field exists will return a conflict (419) public static Task>> UploadRslugPrefixKbKbidSlugRslugFileFieldUploadAsync( this HttpClient httpClient, - string kbid, string rslug, string field, object body, object? xFilename = null, object? xPassword = null, object? xLanguage = null, object? xMd5 = null, object? xExtractStrategy = null, object? xSplitStrategy = null, + string kbid, string rslug, string field, object body, string? xFilename = null, string? xPassword = null, string? xLanguage = null, string? xMd5 = null, string? xExtractStrategy = null, string? xSplitStrategy = null, CancellationToken cancellationToken = default ) => _uploadRslugPrefixKbKbidSlugRslugFileFieldUploadAsync(httpClient, (kbid, rslug, field, xFilename, xPassword, xLanguage, xMd5, xExtractStrategy, xSplitStrategy, body), cancellationToken); @@ -687,7 +687,7 @@ public static Task>> ResourceFieldRs /// --- ## Authorization roles Authenticated user needs to fulfill one of this roles, otherwise the request will be rejected with a `403` response. - `READER` public static Task>> ResourceFieldRslugPrefixKbKbidSlugRslugFieldTypeFieldIdGetAsync( this HttpClient httpClient, - string kbid, string rslug, string fieldType, string fieldId, List? show = null, List? extracted = null, object? page = null, + string kbid, string rslug, string fieldType, string fieldId, List? show = null, List? extracted = null, string? page = null, CancellationToken cancellationToken = default ) => _resourceFieldRslugPrefixKbKbidSlugRslugFieldTypeFieldIdGetAsync(httpClient, (kbid, rslug, fieldType, fieldId, show, extracted, page), cancellationToken); @@ -743,7 +743,7 @@ public static Task>> SplitStrategy /// Suggestions on a knowledge box public static Task>> SuggestKnowledgeboxKbKbidSuggestAsync( this HttpClient httpClient, - string kbid, string query, List? fields = null, List? filters = null, List? faceted = null, object? rangeCreationStart = null, object? rangeCreationEnd = null, object? rangeModificationStart = null, object? rangeModificationEnd = null, List? features = null, List? show = null, List? fieldType = null, bool debug = false, bool highlight = false, bool showHidden = false, string xNdbClient = "api", string? xNucliadbUser = null, string? xForwardedFor = null, + string kbid, string query, List? fields = null, List? filters = null, List? faceted = null, string? rangeCreationStart = null, string? rangeCreationEnd = null, string? rangeModificationStart = null, string? rangeModificationEnd = null, List? features = null, List? show = null, List? fieldType = null, bool debug = false, bool highlight = false, bool showHidden = false, string xNdbClient = "api", string? xNucliadbUser = null, string? xForwardedFor = null, CancellationToken cancellationToken = default ) => _suggestKnowledgeboxKbKbidSuggestAsync(httpClient, (kbid, query, fields, filters, faceted, rangeCreationStart, rangeCreationEnd, rangeModificationStart, rangeModificationEnd, features, show, fieldType, debug, highlight, showHidden, xNdbClient, xNucliadbUser, xForwardedFor), cancellationToken); @@ -757,14 +757,14 @@ public static Task>> S /// --- ## Authorization roles Authenticated user needs to fulfill one of this roles, otherwise the request will be rejected with a `403` response. - `WRITER` public static Task>> TusPostKbKbidTusuploadAsync( this HttpClient httpClient, - string kbid, object body, object? xExtractStrategy = null, object? xSplitStrategy = null, + string kbid, object body, string? xExtractStrategy = null, string? xSplitStrategy = null, CancellationToken cancellationToken = default ) => _tusPostKbKbidTusuploadAsync(httpClient, (kbid, xExtractStrategy, xSplitStrategy, body), cancellationToken); /// TUS Server information public static Task>> TusOptionsKbKbidTusuploadAsync( this HttpClient httpClient, - string kbid, object? rid = null, object? rslug = null, object? uploadId = null, object? field = null, + string kbid, string? rid = null, string? rslug = null, string? uploadId = null, string? field = null, CancellationToken cancellationToken = default ) => _tusOptionsKbKbidTusuploadAsync(httpClient, (kbid, rid, rslug, uploadId, field), cancellationToken); @@ -785,7 +785,7 @@ public static Task>> UploadInforma /// Upload a file onto a Knowledge Box, field id will be file and rid will be autogenerated. public static Task>> UploadKbKbidUploadAsync( this HttpClient httpClient, - string kbid, object body, object? xFilename = null, object? xPassword = null, object? xLanguage = null, object? xMd5 = null, object? xExtractStrategy = null, object? xSplitStrategy = null, + string kbid, object body, string? xFilename = null, string? xPassword = null, string? xLanguage = null, string? xMd5 = null, string? xExtractStrategy = null, string? xSplitStrategy = null, CancellationToken cancellationToken = default ) => _uploadKbKbidUploadAsync(httpClient, (kbid, xFilename, xPassword, xLanguage, xMd5, xExtractStrategy, xSplitStrategy, body), cancellationToken); @@ -837,8 +837,8 @@ public static Task>> LearningConfi deserializeError: DeserializeJson ); - private static GetAsync? filters, List? faceted, string sortField, object? sortLimit, string sortOrder, int pageNumber, int pageSize, object? withStatus, object? rangeCreationStart, object? rangeCreationEnd, object? rangeModificationStart, object? rangeModificationEnd, object? hidden, List? show)> _catalogGetKbKbidCatalogAsync { get; } = - RestClient.Net.HttpClientFactoryExtensions.CreateGet? filters, List? faceted, string sortField, object? sortLimit, string sortOrder, int pageNumber, int pageSize, object? withStatus, object? rangeCreationStart, object? rangeCreationEnd, object? rangeModificationStart, object? rangeModificationEnd, object? hidden, List? show)>( + private static GetAsync? filters, List? faceted, string sortField, int? sortLimit, string sortOrder, int pageNumber, int pageSize, string? withStatus, string? rangeCreationStart, string? rangeCreationEnd, string? rangeModificationStart, string? rangeModificationEnd, bool? hidden, List? show)> _catalogGetKbKbidCatalogAsync { get; } = + RestClient.Net.HttpClientFactoryExtensions.CreateGet? filters, List? faceted, string sortField, int? sortLimit, string sortOrder, int pageNumber, int pageSize, string? withStatus, string? rangeCreationStart, string? rangeCreationEnd, string? rangeModificationStart, string? rangeModificationEnd, bool? hidden, List? show)>( url: BaseUrl, buildRequest: static param => new HttpRequestParts(new RelativeUrl($"/api/v1/kb/{param.kbid}/catalog{BuildQueryString(("query", param.query), ("filter_expression", param.filterExpression), ("filters", param.filters), ("faceted", param.faceted), ("sort_field", param.sortField), ("sort_limit", param.sortLimit), ("sort_order", param.sortOrder), ("page_number", param.pageNumber), ("page_size", param.pageSize), ("with_status", param.withStatus), ("range_creation_start", param.rangeCreationStart), ("range_creation_end", param.rangeCreationEnd), ("range_modification_start", param.rangeModificationStart), ("range_modification_end", param.rangeModificationEnd), ("hidden", param.hidden), ("show", param.show))}"), null, null), deserializeSuccess: DeserializeJson, @@ -1013,8 +1013,8 @@ public static Task>> LearningConfi deserializeError: DeserializeJson ); - private static GetAsync? fields, List? filters, object? topK, object? minScore, object? minScoreSemantic, float minScoreBm25, object? vectorset, object? rangeCreationStart, object? rangeCreationEnd, object? rangeModificationStart, object? rangeModificationEnd, List? features, bool debug, bool highlight, List? show, List? fieldType, List? extracted, bool withDuplicates, bool withSynonyms, bool autofilter, List? securityGroups, bool showHidden, string rankFusion, object? reranker, object? searchConfiguration, string xNdbClient, string? xNucliadbUser, string? xForwardedFor)> _findKnowledgeboxKbKbidFindAsync { get; } = - RestClient.Net.HttpClientFactoryExtensions.CreateGet? fields, List? filters, object? topK, object? minScore, object? minScoreSemantic, float minScoreBm25, object? vectorset, object? rangeCreationStart, object? rangeCreationEnd, object? rangeModificationStart, object? rangeModificationEnd, List? features, bool debug, bool highlight, List? show, List? fieldType, List? extracted, bool withDuplicates, bool withSynonyms, bool autofilter, List? securityGroups, bool showHidden, string rankFusion, object? reranker, object? searchConfiguration, string xNdbClient, string? xNucliadbUser, string? xForwardedFor)>( + private static GetAsync? fields, List? filters, int? topK, float? minScore, float? minScoreSemantic, float minScoreBm25, string? vectorset, string? rangeCreationStart, string? rangeCreationEnd, string? rangeModificationStart, string? rangeModificationEnd, List? features, bool debug, bool highlight, List? show, List? fieldType, List? extracted, bool withDuplicates, bool withSynonyms, bool autofilter, List? securityGroups, bool showHidden, string rankFusion, string? reranker, string? searchConfiguration, string xNdbClient, string? xNucliadbUser, string? xForwardedFor)> _findKnowledgeboxKbKbidFindAsync { get; } = + RestClient.Net.HttpClientFactoryExtensions.CreateGet? fields, List? filters, int? topK, float? minScore, float? minScoreSemantic, float minScoreBm25, string? vectorset, string? rangeCreationStart, string? rangeCreationEnd, string? rangeModificationStart, string? rangeModificationEnd, List? features, bool debug, bool highlight, List? show, List? fieldType, List? extracted, bool withDuplicates, bool withSynonyms, bool autofilter, List? securityGroups, bool showHidden, string rankFusion, string? reranker, string? searchConfiguration, string xNdbClient, string? xNucliadbUser, string? xForwardedFor)>( url: BaseUrl, buildRequest: static param => new HttpRequestParts(new RelativeUrl($"/api/v1/kb/{param.kbid}/find{BuildQueryString(("query", param.query), ("filter_expression", param.filterExpression), ("fields", param.fields), ("filters", param.filters), ("top_k", param.topK), ("min_score", param.minScore), ("min_score_semantic", param.minScoreSemantic), ("min_score_bm25", param.minScoreBm25), ("vectorset", param.vectorset), ("range_creation_start", param.rangeCreationStart), ("range_creation_end", param.rangeCreationEnd), ("range_modification_start", param.rangeModificationStart), ("range_modification_end", param.rangeModificationEnd), ("features", param.features), ("debug", param.debug), ("highlight", param.highlight), ("show", param.show), ("field_type", param.fieldType), ("extracted", param.extracted), ("with_duplicates", param.withDuplicates), ("with_synonyms", param.withSynonyms), ("autofilter", param.autofilter), ("security_groups", param.securityGroups), ("show_hidden", param.showHidden), ("rank_fusion", param.rankFusion), ("reranker", param.reranker), ("search_configuration", param.searchConfiguration))}"), null, new Dictionary { ["x-ndb-client"] = param.xNdbClient.ToString(), ["x-nucliadb-user"] = param.xNucliadbUser?.ToString() ?? string.Empty, ["x-forwarded-for"] = param.xForwardedFor?.ToString() ?? string.Empty }), deserializeSuccess: DeserializeJson, @@ -1149,16 +1149,16 @@ public static Task>> LearningConfi deserializeError: DeserializeJson ); - private static GetAsync _processingStatusKbKbidProcessingStatusAsync { get; } = - RestClient.Net.HttpClientFactoryExtensions.CreateGet( + private static GetAsync _processingStatusKbKbidProcessingStatusAsync { get; } = + RestClient.Net.HttpClientFactoryExtensions.CreateGet( url: BaseUrl, buildRequest: static param => new HttpRequestParts(new RelativeUrl($"/api/v1/kb/{param.kbid}/processing-status{BuildQueryString(("cursor", param.cursor), ("scheduled", param.scheduled), ("limit", param.limit))}"), null, null), deserializeSuccess: DeserializeJson, deserializeError: DeserializeError ); - private static PostAsync _tusPostRidPrefixKbKbidResourcePathRidFileFieldTusuploadAsync { get; } = - RestClient.Net.HttpClientFactoryExtensions.CreatePost( + private static PostAsync _tusPostRidPrefixKbKbidResourcePathRidFileFieldTusuploadAsync { get; } = + RestClient.Net.HttpClientFactoryExtensions.CreatePost( url: BaseUrl, buildRequest: static param => new HttpRequestParts(new RelativeUrl($"/api/v1/kb/{param.kbid}/resource/{param.pathRid}/file/{param.field}/tusupload"), CreateJsonContent(param.Body), new Dictionary { ["x-extract-strategy"] = param.xExtractStrategy?.ToString() ?? string.Empty, ["x-split-strategy"] = param.xSplitStrategy?.ToString() ?? string.Empty }), deserializeSuccess: DeserializeJson, @@ -1173,8 +1173,8 @@ public static Task>> LearningConfi deserializeError: DeserializeJson ); - private static PostAsync _uploadRidPrefixKbKbidResourcePathRidFileFieldUploadAsync { get; } = - RestClient.Net.HttpClientFactoryExtensions.CreatePost( + private static PostAsync _uploadRidPrefixKbKbidResourcePathRidFileFieldUploadAsync { get; } = + RestClient.Net.HttpClientFactoryExtensions.CreatePost( url: BaseUrl, buildRequest: static param => new HttpRequestParts(new RelativeUrl($"/api/v1/kb/{param.kbid}/resource/{param.pathRid}/file/{param.field}/upload"), CreateJsonContent(param.Body), new Dictionary { ["x-filename"] = param.xFilename?.ToString() ?? string.Empty, ["x-password"] = param.xPassword?.ToString() ?? string.Empty, ["x-language"] = param.xLanguage?.ToString() ?? string.Empty, ["x-md5"] = param.xMd5?.ToString() ?? string.Empty, ["x-extract-strategy"] = param.xExtractStrategy?.ToString() ?? string.Empty, ["x-split-strategy"] = param.xSplitStrategy?.ToString() ?? string.Empty }), deserializeSuccess: DeserializeJson, @@ -1253,8 +1253,8 @@ public static Task>> LearningConfi deserializeError: DeserializeJson ); - private static PostAsync _reprocessFileFieldKbKbidResourceRidFileFieldIdReprocessAsync { get; } = - RestClient.Net.HttpClientFactoryExtensions.CreatePost( + private static PostAsync _reprocessFileFieldKbKbidResourceRidFileFieldIdReprocessAsync { get; } = + RestClient.Net.HttpClientFactoryExtensions.CreatePost( url: BaseUrl, buildRequest: static param => new HttpRequestParts(new RelativeUrl($"/api/v1/kb/{param.kbid}/resource/{param.rid}/file/{param.fieldId}/reprocess?reset_title={param.resetTitle}"), CreateJsonContent(param.Body), new Dictionary { ["x-nucliadb-user"] = param.xNucliadbUser?.ToString() ?? string.Empty, ["x-file-password"] = param.xFilePassword?.ToString() ?? string.Empty }), deserializeSuccess: DeserializeJson, @@ -1301,8 +1301,8 @@ public static Task>> LearningConfi deserializeError: DeserializeJson ); - private static GetAsync? fields, List? filters, List? faceted, object? sortField, string sortOrder, object? topK, object? rangeCreationStart, object? rangeCreationEnd, object? rangeModificationStart, object? rangeModificationEnd, bool highlight, bool debug, string xNdbClient)> _resourceSearchKbKbidResourceRidSearchAsync { get; } = - RestClient.Net.HttpClientFactoryExtensions.CreateGet? fields, List? filters, List? faceted, object? sortField, string sortOrder, object? topK, object? rangeCreationStart, object? rangeCreationEnd, object? rangeModificationStart, object? rangeModificationEnd, bool highlight, bool debug, string xNdbClient)>( + private static GetAsync? fields, List? filters, List? faceted, string? sortField, string sortOrder, int? topK, string? rangeCreationStart, string? rangeCreationEnd, string? rangeModificationStart, string? rangeModificationEnd, bool highlight, bool debug, string xNdbClient)> _resourceSearchKbKbidResourceRidSearchAsync { get; } = + RestClient.Net.HttpClientFactoryExtensions.CreateGet? fields, List? filters, List? faceted, string? sortField, string sortOrder, int? topK, string? rangeCreationStart, string? rangeCreationEnd, string? rangeModificationStart, string? rangeModificationEnd, bool highlight, bool debug, string xNdbClient)>( url: BaseUrl, buildRequest: static param => new HttpRequestParts(new RelativeUrl($"/api/v1/kb/{param.kbid}/resource/{param.rid}/search{BuildQueryString(("query", param.query), ("filter_expression", param.filterExpression), ("fields", param.fields), ("filters", param.filters), ("faceted", param.faceted), ("sort_field", param.sortField), ("sort_order", param.sortOrder), ("top_k", param.topK), ("range_creation_start", param.rangeCreationStart), ("range_creation_end", param.rangeCreationEnd), ("range_modification_start", param.rangeModificationStart), ("range_modification_end", param.rangeModificationEnd), ("highlight", param.highlight), ("debug", param.debug))}"), null, new Dictionary { ["x-ndb-client"] = param.xNdbClient.ToString() }), deserializeSuccess: DeserializeJson, @@ -1325,8 +1325,8 @@ public static Task>> LearningConfi deserializeError: DeserializeJson ); - private static GetAsync? show, List? extracted, object? page)> _resourceFieldRidPrefixKbKbidResourceRidFieldTypeFieldIdGetAsync { get; } = - RestClient.Net.HttpClientFactoryExtensions.CreateGet? show, List? extracted, object? page)>( + private static GetAsync? show, List? extracted, string? page)> _resourceFieldRidPrefixKbKbidResourceRidFieldTypeFieldIdGetAsync { get; } = + RestClient.Net.HttpClientFactoryExtensions.CreateGet? show, List? extracted, string? page)>( url: BaseUrl, buildRequest: static param => new HttpRequestParts(new RelativeUrl($"/api/v1/kb/{param.kbid}/resource/{param.rid}/{param.fieldType}/{param.fieldId}{BuildQueryString(("show", param.show), ("extracted", param.extracted), ("page", param.page))}"), null, null), deserializeSuccess: DeserializeJson, @@ -1365,8 +1365,8 @@ public static Task>> LearningConfi deserializeError: DeserializeJson ); - private static GetAsync? fields, List? filters, List? faceted, string sortField, object? sortLimit, string sortOrder, int topK, object? minScore, object? minScoreSemantic, float minScoreBm25, object? vectorset, object? rangeCreationStart, object? rangeCreationEnd, object? rangeModificationStart, object? rangeModificationEnd, List? features, bool debug, bool highlight, List? show, List? fieldType, List? extracted, bool withDuplicates, bool withSynonyms, bool autofilter, List? securityGroups, bool showHidden, string xNdbClient, string? xNucliadbUser, string? xForwardedFor)> _searchKnowledgeboxKbKbidSearchAsync { get; } = - RestClient.Net.HttpClientFactoryExtensions.CreateGet? fields, List? filters, List? faceted, string sortField, object? sortLimit, string sortOrder, int topK, object? minScore, object? minScoreSemantic, float minScoreBm25, object? vectorset, object? rangeCreationStart, object? rangeCreationEnd, object? rangeModificationStart, object? rangeModificationEnd, List? features, bool debug, bool highlight, List? show, List? fieldType, List? extracted, bool withDuplicates, bool withSynonyms, bool autofilter, List? securityGroups, bool showHidden, string xNdbClient, string? xNucliadbUser, string? xForwardedFor)>( + private static GetAsync? fields, List? filters, List? faceted, string sortField, int? sortLimit, string sortOrder, int topK, float? minScore, float? minScoreSemantic, float minScoreBm25, string? vectorset, string? rangeCreationStart, string? rangeCreationEnd, string? rangeModificationStart, string? rangeModificationEnd, List? features, bool debug, bool highlight, List? show, List? fieldType, List? extracted, bool withDuplicates, bool withSynonyms, bool autofilter, List? securityGroups, bool showHidden, string xNdbClient, string? xNucliadbUser, string? xForwardedFor)> _searchKnowledgeboxKbKbidSearchAsync { get; } = + RestClient.Net.HttpClientFactoryExtensions.CreateGet? fields, List? filters, List? faceted, string sortField, int? sortLimit, string sortOrder, int topK, float? minScore, float? minScoreSemantic, float minScoreBm25, string? vectorset, string? rangeCreationStart, string? rangeCreationEnd, string? rangeModificationStart, string? rangeModificationEnd, List? features, bool debug, bool highlight, List? show, List? fieldType, List? extracted, bool withDuplicates, bool withSynonyms, bool autofilter, List? securityGroups, bool showHidden, string xNdbClient, string? xNucliadbUser, string? xForwardedFor)>( url: BaseUrl, buildRequest: static param => new HttpRequestParts(new RelativeUrl($"/api/v1/kb/{param.kbid}/search{BuildQueryString(("query", param.query), ("filter_expression", param.filterExpression), ("fields", param.fields), ("filters", param.filters), ("faceted", param.faceted), ("sort_field", param.sortField), ("sort_limit", param.sortLimit), ("sort_order", param.sortOrder), ("top_k", param.topK), ("min_score", param.minScore), ("min_score_semantic", param.minScoreSemantic), ("min_score_bm25", param.minScoreBm25), ("vectorset", param.vectorset), ("range_creation_start", param.rangeCreationStart), ("range_creation_end", param.rangeCreationEnd), ("range_modification_start", param.rangeModificationStart), ("range_modification_end", param.rangeModificationEnd), ("features", param.features), ("debug", param.debug), ("highlight", param.highlight), ("show", param.show), ("field_type", param.fieldType), ("extracted", param.extracted), ("with_duplicates", param.withDuplicates), ("with_synonyms", param.withSynonyms), ("autofilter", param.autofilter), ("security_groups", param.securityGroups), ("show_hidden", param.showHidden))}"), null, new Dictionary { ["x-ndb-client"] = param.xNdbClient.ToString(), ["x-nucliadb-user"] = param.xNucliadbUser?.ToString() ?? string.Empty, ["x-forwarded-for"] = param.xForwardedFor?.ToString() ?? string.Empty }), deserializeSuccess: DeserializeJson, @@ -1485,8 +1485,8 @@ public static Task>> LearningConfi deserializeError: DeserializeJson ); - private static PostAsync _tusPostRslugPrefixKbKbidSlugRslugFileFieldTusuploadAsync { get; } = - RestClient.Net.HttpClientFactoryExtensions.CreatePost( + private static PostAsync _tusPostRslugPrefixKbKbidSlugRslugFileFieldTusuploadAsync { get; } = + RestClient.Net.HttpClientFactoryExtensions.CreatePost( url: BaseUrl, buildRequest: static param => new HttpRequestParts(new RelativeUrl($"/api/v1/kb/{param.kbid}/slug/{param.rslug}/file/{param.field}/tusupload"), CreateJsonContent(param.Body), new Dictionary { ["x-extract-strategy"] = param.xExtractStrategy?.ToString() ?? string.Empty, ["x-split-strategy"] = param.xSplitStrategy?.ToString() ?? string.Empty }), deserializeSuccess: DeserializeJson, @@ -1509,8 +1509,8 @@ public static Task>> LearningConfi deserializeError: DeserializeJson ); - private static PostAsync _uploadRslugPrefixKbKbidSlugRslugFileFieldUploadAsync { get; } = - RestClient.Net.HttpClientFactoryExtensions.CreatePost( + private static PostAsync _uploadRslugPrefixKbKbidSlugRslugFileFieldUploadAsync { get; } = + RestClient.Net.HttpClientFactoryExtensions.CreatePost( url: BaseUrl, buildRequest: static param => new HttpRequestParts(new RelativeUrl($"/api/v1/kb/{param.kbid}/slug/{param.rslug}/file/{param.field}/upload"), CreateJsonContent(param.Body), new Dictionary { ["x-filename"] = param.xFilename?.ToString() ?? string.Empty, ["x-password"] = param.xPassword?.ToString() ?? string.Empty, ["x-language"] = param.xLanguage?.ToString() ?? string.Empty, ["x-md5"] = param.xMd5?.ToString() ?? string.Empty, ["x-extract-strategy"] = param.xExtractStrategy?.ToString() ?? string.Empty, ["x-split-strategy"] = param.xSplitStrategy?.ToString() ?? string.Empty }), deserializeSuccess: DeserializeJson, @@ -1557,8 +1557,8 @@ public static Task>> LearningConfi deserializeError: DeserializeJson ); - private static GetAsync? show, List? extracted, object? page)> _resourceFieldRslugPrefixKbKbidSlugRslugFieldTypeFieldIdGetAsync { get; } = - RestClient.Net.HttpClientFactoryExtensions.CreateGet? show, List? extracted, object? page)>( + private static GetAsync? show, List? extracted, string? page)> _resourceFieldRslugPrefixKbKbidSlugRslugFieldTypeFieldIdGetAsync { get; } = + RestClient.Net.HttpClientFactoryExtensions.CreateGet? show, List? extracted, string? page)>( url: BaseUrl, buildRequest: static param => new HttpRequestParts(new RelativeUrl($"/api/v1/kb/{param.kbid}/slug/{param.rslug}/{param.fieldType}/{param.fieldId}{BuildQueryString(("show", param.show), ("extracted", param.extracted), ("page", param.page))}"), null, null), deserializeSuccess: DeserializeJson, @@ -1621,8 +1621,8 @@ public static Task>> LearningConfi deserializeError: DeserializeJson ); - private static GetAsync? fields, List? filters, List? faceted, object? rangeCreationStart, object? rangeCreationEnd, object? rangeModificationStart, object? rangeModificationEnd, List? features, List? show, List? fieldType, bool debug, bool highlight, bool showHidden, string xNdbClient, string? xNucliadbUser, string? xForwardedFor)> _suggestKnowledgeboxKbKbidSuggestAsync { get; } = - RestClient.Net.HttpClientFactoryExtensions.CreateGet? fields, List? filters, List? faceted, object? rangeCreationStart, object? rangeCreationEnd, object? rangeModificationStart, object? rangeModificationEnd, List? features, List? show, List? fieldType, bool debug, bool highlight, bool showHidden, string xNdbClient, string? xNucliadbUser, string? xForwardedFor)>( + private static GetAsync? fields, List? filters, List? faceted, string? rangeCreationStart, string? rangeCreationEnd, string? rangeModificationStart, string? rangeModificationEnd, List? features, List? show, List? fieldType, bool debug, bool highlight, bool showHidden, string xNdbClient, string? xNucliadbUser, string? xForwardedFor)> _suggestKnowledgeboxKbKbidSuggestAsync { get; } = + RestClient.Net.HttpClientFactoryExtensions.CreateGet? fields, List? filters, List? faceted, string? rangeCreationStart, string? rangeCreationEnd, string? rangeModificationStart, string? rangeModificationEnd, List? features, List? show, List? fieldType, bool debug, bool highlight, bool showHidden, string xNdbClient, string? xNucliadbUser, string? xForwardedFor)>( url: BaseUrl, buildRequest: static param => new HttpRequestParts(new RelativeUrl($"/api/v1/kb/{param.kbid}/suggest{BuildQueryString(("query", param.query), ("fields", param.fields), ("filters", param.filters), ("faceted", param.faceted), ("range_creation_start", param.rangeCreationStart), ("range_creation_end", param.rangeCreationEnd), ("range_modification_start", param.rangeModificationStart), ("range_modification_end", param.rangeModificationEnd), ("features", param.features), ("show", param.show), ("field_type", param.fieldType), ("debug", param.debug), ("highlight", param.highlight), ("show_hidden", param.showHidden))}"), null, new Dictionary { ["x-ndb-client"] = param.xNdbClient.ToString(), ["x-nucliadb-user"] = param.xNucliadbUser?.ToString() ?? string.Empty, ["x-forwarded-for"] = param.xForwardedFor?.ToString() ?? string.Empty }), deserializeSuccess: DeserializeJson, @@ -1637,16 +1637,16 @@ public static Task>> LearningConfi deserializeError: DeserializeJson ); - private static PostAsync _tusPostKbKbidTusuploadAsync { get; } = - RestClient.Net.HttpClientFactoryExtensions.CreatePost( + private static PostAsync _tusPostKbKbidTusuploadAsync { get; } = + RestClient.Net.HttpClientFactoryExtensions.CreatePost( url: BaseUrl, buildRequest: static param => new HttpRequestParts(new RelativeUrl($"/api/v1/kb/{param.kbid}/tusupload"), CreateJsonContent(param.Body), new Dictionary { ["x-extract-strategy"] = param.xExtractStrategy?.ToString() ?? string.Empty, ["x-split-strategy"] = param.xSplitStrategy?.ToString() ?? string.Empty }), deserializeSuccess: DeserializeJson, deserializeError: DeserializeJson ); - private static OptionsAsync _tusOptionsKbKbidTusuploadAsync { get; } = - RestClient.Net.HttpClientFactoryExtensions.CreateOptions( + private static OptionsAsync _tusOptionsKbKbidTusuploadAsync { get; } = + RestClient.Net.HttpClientFactoryExtensions.CreateOptions( url: BaseUrl, buildRequest: static param => new HttpRequestParts(new RelativeUrl($"/api/v1/kb/{param.kbid}/tusupload{BuildQueryString(("rid", param.rid), ("rslug", param.rslug), ("upload_id", param.uploadId), ("field", param.field))}"), null, null), deserializeSuccess: DeserializeJson, @@ -1669,8 +1669,8 @@ public static Task>> LearningConfi deserializeError: DeserializeJson ); - private static PostAsync _uploadKbKbidUploadAsync { get; } = - RestClient.Net.HttpClientFactoryExtensions.CreatePost( + private static PostAsync _uploadKbKbidUploadAsync { get; } = + RestClient.Net.HttpClientFactoryExtensions.CreatePost( url: BaseUrl, buildRequest: static param => new HttpRequestParts(new RelativeUrl($"/api/v1/kb/{param.kbid}/upload"), CreateJsonContent(param.Body), new Dictionary { ["x-filename"] = param.xFilename?.ToString() ?? string.Empty, ["x-password"] = param.xPassword?.ToString() ?? string.Empty, ["x-language"] = param.xLanguage?.ToString() ?? string.Empty, ["x-md5"] = param.xMd5?.ToString() ?? string.Empty, ["x-extract-strategy"] = param.xExtractStrategy?.ToString() ?? string.Empty, ["x-split-strategy"] = param.xSplitStrategy?.ToString() ?? string.Empty }), deserializeSuccess: DeserializeJson, diff --git a/Samples/NucliaDbClient/Generated/NucliaDBApiModels.g.cs b/Samples/NucliaDbClient/Generated/NucliaDBApiModels.g.cs index 2dfca7d4..bca128e8 100644 --- a/Samples/NucliaDbClient/Generated/NucliaDBApiModels.g.cs +++ b/Samples/NucliaDbClient/Generated/NucliaDBApiModels.g.cs @@ -1,3 +1,4 @@ +#nullable enable namespace NucliaDB.Generated; /// HTTPValidationError @@ -58,7 +59,7 @@ public record AndResourceFilterExpression(List Operands); /// Text /// Language /// IdsParagraphs -public record Answer(string Text, object Language, List IdsParagraphs); +public record Answer(string Text, string? Language, List IdsParagraphs); /// AnyNode /// Prop @@ -66,13 +67,13 @@ public record Answer(string Text, object Language, List IdsParagraphs); /// Match /// Type /// Group -public record AnyNode(string Prop, object Value, string Match, object Type, object Group); +public record AnyNode(string Prop, string? Value, string Match, string? Type, string? Group); /// AppliedDataAugmentation /// Question and answers generated by the Question Answers agent /// New text fields. Only generated by the Generator agent as of now. /// Indicates if the FieldMetadata was changed by the agents -public record AppliedDataAugmentation(object Qas, List NewTextFields, bool Changed); +public record AppliedDataAugmentation(QuestionAnswers? Qas, List NewTextFields, bool Changed); /// AskRequest /// A dictionary containing optional audit-specific metadata, such as user_id, environment, or other contextual information. This metadata can be leveraged for filtering and analyzing activity logs in future operations. Each key-value pair represents a piece of metadata relevant to the user's request. @@ -120,7 +121,7 @@ public record AppliedDataAugmentation(object Qas, List NewTextFiel /// Whether to generate an answer using the generative model. If set to false, the response will only contain the retrieval results. /// Load ask parameters from this configuration. Parameters in the request override parameters from the configuration. /// Reasoning options for the generative model. Set to True to enable default reasoning, False to disable, or provide a Reasoning object for custom options. -public record AskRequest(object AuditMetadata, string Query, int TopK, object FilterExpression, List Fields, object Filters, object KeywordFilters, object Vectorset, object MinScore, List Features, object RangeCreationStart, object RangeCreationEnd, object RangeModificationStart, object RangeModificationEnd, List Show, List FieldTypeFilter, List Extracted, object Context, object ChatHistory, object ExtraContext, object ExtraContextImages, object QueryImage, bool Autofilter, bool Highlight, List ResourceFilters, object Prompt, object RankFusion, object Reranker, bool Citations, object CitationThreshold, object Security, bool ShowHidden, List RagStrategies, List RagImagesStrategies, bool Debug, object GenerativeModel, object GenerativeModelSeed, object MaxTokens, bool Rephrase, object ChatHistoryRelevanceThreshold, bool PreferMarkdown, object AnswerJsonSchema, bool GenerateAnswer, object SearchConfiguration, object Reasoning); +public record AskRequest(object? AuditMetadata, string Query, int TopK, FilterExpression? FilterExpression, List Fields, List? Filters, List? KeywordFilters, string? Vectorset, float? MinScore, List Features, string? RangeCreationStart, string? RangeCreationEnd, string? RangeModificationStart, string? RangeModificationEnd, List Show, List FieldTypeFilter, List Extracted, List? Context, List? ChatHistory, List? ExtraContext, List? ExtraContextImages, Image? QueryImage, bool Autofilter, bool Highlight, List ResourceFilters, string? Prompt, string? RankFusion, string? Reranker, bool Citations, float? CitationThreshold, RequestSecurity? Security, bool ShowHidden, List RagStrategies, List RagImagesStrategies, bool Debug, string? GenerativeModel, int? GenerativeModelSeed, int? MaxTokens, bool Rephrase, float? ChatHistoryRelevanceThreshold, bool PreferMarkdown, object? AnswerJsonSchema, bool GenerateAnswer, string? SearchConfiguration, Reasoning? Reasoning); /// AskRetrievalMatch /// Id of the matching text block @@ -129,14 +130,14 @@ public record AskRetrievalMatch(string Id); /// AskTimings /// Time the LLM took to generate the first chunk of the answer /// Total time the LLM took to generate the answer -public record AskTimings(object GenerativeFirstChunk, object GenerativeTotal); +public record AskTimings(float? GenerativeFirstChunk, float? GenerativeTotal); /// AskTokens /// Number of LLM tokens used for the context in the query /// Number of LLM tokens used for the answer /// Number of Nuclia LLM tokens used for the context in the query /// Number of Nuclia LLM tokens used for the answer -public record AskTokens(int Input, int Output, object InputNuclia, object OutputNuclia); +public record AskTokens(int Input, int Output, float? InputNuclia, float? OutputNuclia); /// AugmentedContext /// Paragraphs added to the context as a result of using the `rag_strategies` parameter, typically the neighbouring_paragraphs or the conversation strategies @@ -157,7 +158,7 @@ public record AugmentedField(FieldMetadata Metadata, AppliedDataAugmentation App /// Metadata about the position of the text block in the original document. /// The parent text block that was augmented for. /// AugmentationType -public record AugmentedTextBlock(string Id, string Text, object Position, object Parent, string AugmentationType); +public record AugmentedTextBlock(string Id, string Text, TextPosition? Position, string? Parent, string AugmentationType); /// Returns only documents that match this filter expression. Filtering examples can be found here: https://docs.nuclia.dev/docs/rag/advanced/search-filters This allows building complex filtering expressions and replaces the following parameters: `filters`, `range_*`, `with_status`. /// Filter to apply to resources @@ -184,7 +185,7 @@ public record CatalogQuery(string Field, string Match, string Query); /// Resources created after this date will be filtered out of search results. Datetime are represented as a str in ISO 8601 format, like: 2008-09-15T15:53:00+05:00. /// Resources modified before this date will be filtered out of search results. Datetime are represented as a str in ISO 8601 format, like: 2008-09-15T15:53:00+05:00. /// Resources modified after this date will be filtered out of search results. Datetime are represented as a str in ISO 8601 format, like: 2008-09-15T15:53:00+05:00. -public record CatalogRequest(object Query, object FilterExpression, List Faceted, object Sort, int PageNumber, int PageSize, object Hidden, List Show, object Filters, object WithStatus, object RangeCreationStart, object RangeCreationEnd, object RangeModificationStart, object RangeModificationEnd); +public record CatalogRequest(string? Query, CatalogFilterExpression? FilterExpression, List Faceted, SortOptions? Sort, int PageNumber, int PageSize, bool? Hidden, List Show, List? Filters, string? WithStatus, string? RangeCreationStart, string? RangeCreationEnd, string? RangeModificationStart, string? RangeModificationEnd); /// ChatContextMessage /// Author @@ -202,7 +203,7 @@ public record Classification(string Labelset, string Label); /// ContentType /// Filename /// Md5 -public record CloudLink(object Uri, object Size, object ContentType, object Filename, object Md5); +public record CloudLink(string? Uri, int? Size, string? ContentType, string? Filename, string? Md5); /// The purpose of this field is to show a cherry-picked set of fields from computed metadata without having to load the whole computed metadata field. /// FieldClassifications @@ -219,7 +220,7 @@ public record Consumption(TokensDetail NormalizedTokens, TokensDetail CustomerKe /// Error /// Status /// Errors -public record ConversationFieldData(object Value, object Extracted, object Error, object Status, object Errors); +public record ConversationFieldData(FieldConversation? Value, ConversationFieldExtractedData? Extracted, Error? Error, string? Status, List? Errors); /// ConversationFieldExtractedData /// Text @@ -227,7 +228,7 @@ public record ConversationFieldData(object Value, object Extracted, object Error /// LargeMetadata /// Vectors /// QuestionAnswers -public record ConversationFieldExtractedData(object Text, object Metadata, object LargeMetadata, object Vectors, object QuestionAnswers); +public record ConversationFieldExtractedData(ExtractedText? Text, FieldComputedMetadata? Metadata, LargeComputedMetadata? LargeMetadata, VectorObject? Vectors, FieldQuestionAnswers? QuestionAnswers); /// ConversationalStrategy /// Name @@ -241,19 +242,19 @@ public record ConversationalStrategy(string Name, bool AttachmentsText, bool Att /// System prompt given to the generative model responsible of generating the answer. This can help customize the behavior of the model when generating the answer. If not specified, the default model provider's prompt is used. /// User prompt given to the generative model responsible of generating the answer. Use the words {context} and {question} in brackets where you want those fields to be placed, in case you want them in your prompt. Context will be the data returned by the retrieval step and question will be the user's query. /// Rephrase prompt given to the generative model responsible for rephrasing the query for a more effective retrieval step. This is only used if the `rephrase` flag is set to true in the request. If not specified, Nuclia's default prompt is used. It must include the {question} placeholder. The placeholder will be replaced with the original question -public record CustomPrompt(object System, object User, object Rephrase); +public record CustomPrompt(string? System, string? User, string? Rephrase); /// Matches all fields created in a date range /// Prop /// Start of the date range. Leave blank for unbounded /// End of the date range. Leave blank for unbounded -public record DateCreated(string Prop, object Since, object Until); +public record DateCreated(string Prop, string? Since, string? Until); /// Matches all fields modified in a date range /// Prop /// Start of the date range. Leave blank for unbounded /// End of the date range. Leave blank for unbounded -public record DateModified(string Prop, object Since, object Until); +public record DateModified(string Prop, string? Since, string? Until); /// DestinationNode /// Prop @@ -261,7 +262,7 @@ public record DateModified(string Prop, object Since, object Until); /// Match /// Type /// Group -public record DestinationNode(string Prop, object Value, string Match, object Type, object Group); +public record DestinationNode(string Prop, string? Value, string Match, string? Type, string? Group); /// DirectionalRelation /// Entity @@ -272,19 +273,19 @@ public record DestinationNode(string Prop, object Value, string Match, object Ty /// Direction /// Metadata /// ResourceId -public record DirectionalRelation(string Entity, string EntityType, string EntitySubtype, string Relation, string RelationLabel, string Direction, object Metadata, string ResourceId); +public record DirectionalRelation(string Entity, string EntityType, string EntitySubtype, string Relation, string RelationLabel, string Direction, RelationMetadata? Metadata, string ResourceId); /// Matches fields that contains a detected entity /// Prop /// Type of the entity. e.g: PERSON /// Value of the entity. e.g: Anna. If blank, matches any entity of the given type -public record EntityInput(string Prop, string Subtype, object Value); +public record EntityInput(string Prop, string Subtype, string? Value); /// EntityOutput /// Token /// Root /// Type -public record EntityOutput(object Token, object Root, object Type); +public record EntityOutput(string? Token, string? Root, string? Type); /// EntitySubgraph /// RelatedTo @@ -296,7 +297,7 @@ public record EntitySubgraph(List RelatedTo); /// CodeStr /// Created /// Severity -public record Error(string Body, int Code, string CodeStr, object Created, string Severity); +public record Error(string Body, int Code, string CodeStr, string? Created, string Severity); /// Extra /// Arbitrary JSON metadata provided by the user that is not meant to be searchable, but can be serialized on results. @@ -306,7 +307,7 @@ public record Extra(object Metadata); /// Text /// SplitText /// DeletedSplits -public record ExtractedText(object Text, object SplitText, object DeletedSplits); +public record ExtractedText(string? Text, object? SplitText, List? DeletedSplits); /// FeedbackRequest /// Id of the request to provide feedback for. This id is returned in the response header `Nuclia-Learning-Id` of the chat endpoint. @@ -314,13 +315,13 @@ public record ExtractedText(object Text, object SplitText, object DeletedSplits) /// Task /// Feedback text /// Text block id -public record FeedbackRequest(string Ident, bool Good, string Task, object Feedback, object TextBlockId); +public record FeedbackRequest(string Ident, bool Good, string Task, string? Feedback, string? TextBlockId); /// Matches a field or set of fields /// Prop /// Type /// Name of the field to match. If blank, matches all fields of the given type -public record Field(string Prop, string Type, object Name); +public record Field(string Prop, string Type, string? Name); /// FieldClassification /// Field @@ -331,7 +332,7 @@ public record FieldClassification(FieldID Field, List Classifica /// Metadata /// SplitMetadata /// DeletedSplits -public record FieldComputedMetadata(FieldMetadata Metadata, object SplitMetadata, object DeletedSplits); +public record FieldComputedMetadata(FieldMetadata Metadata, object? SplitMetadata, List? DeletedSplits); /// This is a metadata representation of a conversation about how many pages of messages and total of messages we have. This class is used mainly when exposing a conversation in the resource level /// Pages @@ -339,7 +340,7 @@ public record FieldComputedMetadata(FieldMetadata Metadata, object SplitMetadata /// Total /// ExtractStrategy /// SplitStrategy -public record FieldConversation(object Pages, object Size, object Total, object ExtractStrategy, object SplitStrategy); +public record FieldConversation(int? Pages, int? Size, int? Total, string? ExtractStrategy, string? SplitStrategy); /// Wrapper for the entities extracted from a field (required because protobuf doesn't support lists of lists) /// Entities @@ -364,7 +365,7 @@ public record FieldExtensionStrategy(string Name, List Fields); /// External /// Id of the Nuclia extract strategy used at processing time. If not set, the default strategy was used. Extract strategies are defined at the learning configuration api. /// Id of the Nuclia split strategy used at processing time. If not set, the default strategy was used. Split strategies are defined at the learning configuration api. -public record FieldFile(object Added, object File, object Language, object Password, bool External, object ExtractStrategy, object SplitStrategy); +public record FieldFile(string? Added, CloudLink? File, string? Language, string? Password, bool External, string? ExtractStrategy, string? SplitStrategy); /// FieldID /// FieldType @@ -374,7 +375,7 @@ public record FieldID(string FieldType, string Field); /// FieldLargeMetadata /// Entities /// Tokens -public record FieldLargeMetadata(object Entities, object Tokens); +public record FieldLargeMetadata(List? Entities, object? Tokens); /// FieldLink /// Added @@ -387,7 +388,7 @@ public record FieldLargeMetadata(object Entities, object Tokens); /// Xpath /// Id of the Nuclia extract strategy used at processing time. If not set, the default strategy was used. Extract strategies are defined at the learning configuration api. /// Id of the Nuclia split strategy used at processing time. If not set, the default strategy was used. Split strategies are defined at the learning configuration api. -public record FieldLink(object Added, object Headers, object Cookies, object Uri, object Language, object Localstorage, object CssSelector, object Xpath, object ExtractStrategy, object SplitStrategy); +public record FieldLink(string? Added, object? Headers, object? Cookies, string? Uri, string? Language, object? Localstorage, string? CssSelector, string? Xpath, string? ExtractStrategy, string? SplitStrategy); /// FieldMetadata /// Links @@ -406,19 +407,19 @@ public record FieldLink(object Added, object Headers, object Cookies, object Uri /// Positions /// Relations /// MimeType -public record FieldMetadata(List Links, List Paragraphs, object Ner, object Entities, List Classifications, object LastIndex, object LastUnderstanding, object LastExtract, object LastSummary, object LastProcessingStart, object Thumbnail, object Language, object Summary, object Positions, object Relations, object MimeType); +public record FieldMetadata(List Links, List Paragraphs, object Ner, object Entities, List Classifications, string? LastIndex, string? LastUnderstanding, string? LastExtract, string? LastSummary, string? LastProcessingStart, CloudLink? Thumbnail, string? Language, string? Summary, object Positions, List? Relations, string? MimeType); /// Matches fields with a mimetype /// Prop /// Type of the mimetype to match. e.g: In image/jpeg, type is image /// Type of the mimetype to match. e.g: In image/jpeg, subtype is jpeg.Leave blank to match all mimetype of the type -public record FieldMimetype(string Prop, string Type, object Subtype); +public record FieldMimetype(string Prop, string Type, string? Subtype); /// FieldQuestionAnswers /// QuestionAnswers /// SplitQuestionAnswers /// DeletedSplits -public record FieldQuestionAnswers(QuestionAnswers QuestionAnswers, object SplitQuestionAnswers, object DeletedSplits); +public record FieldQuestionAnswers(QuestionAnswers QuestionAnswers, object? SplitQuestionAnswers, List? DeletedSplits); /// FieldText /// Body @@ -426,7 +427,7 @@ public record FieldQuestionAnswers(QuestionAnswers QuestionAnswers, object Split /// Md5 /// Id of the Nuclia extract strategy used at processing time. If not set, the default strategy was used. Extract strategies are defined at the learning configuration api. /// Id of the Nuclia split strategy used at processing time. If not set, the default strategy was used. Split strategies are defined at the learning configuration api. -public record FieldText(object Body, object Format, object Md5, object ExtractStrategy, object SplitStrategy); +public record FieldText(string? Body, string? Format, string? Md5, string? ExtractStrategy, string? SplitStrategy); /// FileExtractedData /// Language @@ -442,7 +443,7 @@ public record FieldText(object Body, object Format, object Md5, object ExtractSt /// Icon /// NestedPosition /// NestedListPosition -public record FileExtractedData(object Language, object Md5, object Metadata, object Nested, object FileGenerated, object FileRowsPreviews, object FilePreview, object FilePagesPreviews, object FileThumbnail, object Field, object Icon, object NestedPosition, object NestedListPosition); +public record FileExtractedData(string? Language, string? Md5, object? Metadata, object? Nested, object? FileGenerated, object? FileRowsPreviews, CloudLink? FilePreview, FilePages? FilePagesPreviews, CloudLink? FileThumbnail, string? Field, string? Icon, object? NestedPosition, object? NestedListPosition); /// FileFieldData /// Value @@ -450,7 +451,7 @@ public record FileExtractedData(object Language, object Md5, object Metadata, ob /// Error /// Status /// Errors -public record FileFieldData(object Value, object Extracted, object Error, object Status, object Errors); +public record FileFieldData(FieldFile? Value, FileFieldExtractedData? Extracted, Error? Error, string? Status, List? Errors); /// FileFieldExtractedData /// Text @@ -459,26 +460,26 @@ public record FileFieldData(object Value, object Extracted, object Error, object /// Vectors /// QuestionAnswers /// File -public record FileFieldExtractedData(object Text, object Metadata, object LargeMetadata, object Vectors, object QuestionAnswers, object File); +public record FileFieldExtractedData(ExtractedText? Text, FieldComputedMetadata? Metadata, LargeComputedMetadata? LargeMetadata, VectorObject? Vectors, FieldQuestionAnswers? QuestionAnswers, FileExtractedData? File); /// FilePages /// Pages /// Positions /// Structures -public record FilePages(object Pages, object Positions, object Structures); +public record FilePages(List? Pages, List? Positions, List? Structures); /// Filter /// All /// Any /// None /// NotAll -public record Filter(object All, object Any, object None, object NotAll); +public record Filter(List? All, List? Any, List? None, List? NotAll); /// Returns only documents that match this filter expression. Filtering examples can be found here: https://docs.nuclia.dev/docs/rag/advanced/search-filters This allows building complex filtering expressions and replaces the following parameters: `fields`, `filters`, `range_*`, `resource_filters`, `keyword_filters`. /// Filter to apply to fields /// Filter to apply to each text block /// Operator -public record FilterExpression(object Field, object Paragraph, string Operator); +public record FilterExpression(object? Field, object? Paragraph, string Operator); /// FindField /// Paragraphs @@ -497,7 +498,7 @@ public record FindField(object Paragraphs); /// Reference to the extracted image that represents this paragraph /// The referenced image of the paragraph is a table /// Relevant relations from which the paragraph was found, will only be filled if using the Graph RAG Strategy -public record FindParagraph(float Score, string ScoreType, int Order, string Text, string Id, object Labels, object Position, bool FuzzyResult, bool PageWithVisual, object Reference, bool IsATable, object RelevantRelations); +public record FindParagraph(float Score, string ScoreType, int Order, string Text, string Id, List? Labels, TextPosition? Position, bool FuzzyResult, bool PageWithVisual, string? Reference, bool IsATable, Relations? RelevantRelations); /// FindRequest /// A dictionary containing optional audit-specific metadata, such as user_id, environment, or other contextual information. This metadata can be leveraged for filtering and analyzing activity logs in future operations. Each key-value pair represents a piece of metadata relevant to the user's request. @@ -534,7 +535,7 @@ public record FindParagraph(float Score, string ScoreType, int Order, string Tex /// List of keyword filter expressions to apply to the retrieval step. The text block search will only be performed on the documents that contain the specified keywords. The filters are case-insensitive, and only alphanumeric characters and spaces are allowed. Filtering examples can be found here: https://docs.nuclia.dev/docs/rag/advanced/search-filters /// Load find parameters from this configuration. Parameters in the request override parameters from the configuration. /// The generative model used to rephrase the query. If not provided, the model configured for the Knowledge Box is used. -public record FindRequest(object AuditMetadata, string Query, object FilterExpression, List Fields, object Filters, int TopK, object MinScore, object RangeCreationStart, object RangeCreationEnd, object RangeModificationStart, object RangeModificationEnd, bool Debug, bool Highlight, List Show, List FieldTypeFilter, List Extracted, object Vector, object Vectorset, bool WithDuplicates, bool WithSynonyms, bool Autofilter, List ResourceFilters, object Security, bool ShowHidden, bool Rephrase, object RephrasePrompt, object QueryImage, object GraphQuery, List Features, object RankFusion, object Reranker, object KeywordFilters, object SearchConfiguration, object GenerativeModel); +public record FindRequest(object? AuditMetadata, string Query, FilterExpression? FilterExpression, List Fields, List? Filters, int TopK, float? MinScore, string? RangeCreationStart, string? RangeCreationEnd, string? RangeModificationStart, string? RangeModificationEnd, bool Debug, bool Highlight, List Show, List FieldTypeFilter, List Extracted, List? Vector, string? Vectorset, bool WithDuplicates, bool WithSynonyms, bool Autofilter, List ResourceFilters, RequestSecurity? Security, bool ShowHidden, bool Rephrase, string? RephrasePrompt, Image? QueryImage, object? GraphQuery, List Features, string? RankFusion, string? Reranker, List? KeywordFilters, string? SearchConfiguration, string? GenerativeModel); /// FindResource /// Id @@ -559,7 +560,7 @@ public record FindRequest(object AuditMetadata, string Query, object FilterExpre /// Data /// Resource security metadata /// Fields -public record FindResource(string Id, object Slug, object Title, object Summary, object Icon, object Thumbnail, object Metadata, object Usermetadata, object Fieldmetadata, object Computedmetadata, object Created, object Modified, object LastSeqid, object LastAccountSeq, object Queue, object Hidden, object Origin, object Extra, object Relations, object Data, object Security, object Fields); +public record FindResource(string Id, string? Slug, string? Title, string? Summary, string? Icon, string? Thumbnail, Metadata? Metadata, UserMetadata? Usermetadata, List? Fieldmetadata, ComputedMetadata? Computedmetadata, string? Created, string? Modified, int? LastSeqid, int? LastAccountSeq, string? Queue, bool? Hidden, Origin? Origin, Extra? Extra, List? Relations, ResourceData? Data, ResourceSecurity? Security, object Fields); /// FullResourceApplyTo /// Resources from matches containing any of these labels won't expand to the full resource. This may be useful to exclude long and not interesting resources and expend less tokens @@ -570,7 +571,7 @@ public record FullResourceApplyTo(List Exclude); /// Maximum number of full documents to retrieve. If not specified, all matching documents are retrieved. /// Whether to include the remaining text blocks after the maximum number of resources has been reached. /// Define which resources to exclude from serialization -public record FullResourceStrategy(string Name, object Count, bool IncludeRemainingTextBlocks, object ApplyTo); +public record FullResourceStrategy(string Name, int? Count, bool IncludeRemainingTextBlocks, FullResourceApplyTo? ApplyTo); /// GenericFieldData /// Value @@ -578,7 +579,7 @@ public record FullResourceStrategy(string Name, object Count, bool IncludeRemain /// Error /// Status /// Errors -public record GenericFieldData(object Value, object Extracted, object Error, object Status, object Errors); +public record GenericFieldData(string? Value, TextFieldExtractedData? Extracted, Error? Error, string? Status, List? Errors); /// Returns only relations from documents that match this filter expression. Filtering examples can be found here: https://docs.nuclia.dev/docs/rag/advanced/search-filters /// Filter to apply to fields @@ -589,7 +590,7 @@ public record GraphFilterExpression(object Field); /// Match /// Type /// Group -public record GraphNodeInput(object Value, string Match, object Type, object Group); +public record GraphNodeInput(string? Value, string Match, string? Type, string? Group); /// GraphNodeOutput /// Value @@ -603,7 +604,7 @@ public record GraphNodeOutput(string Value, string Type, string Group); /// Security metadata for the request. If not provided, the search request is done without the security lookup phase. /// If set to false (default), excludes hidden resources from search /// Query -public record GraphNodesSearchRequest(int TopK, object FilterExpression, object Security, bool ShowHidden, object Query); +public record GraphNodesSearchRequest(int TopK, GraphFilterExpression? FilterExpression, RequestSecurity? Security, bool ShowHidden, object Query); /// GraphNodesSearchResponse /// Nodes @@ -615,7 +616,7 @@ public record GraphNodesSearchResponse(List Nodes); /// Relation /// Destination /// Undirected -public record GraphPathInput(string Prop, object Source, object Relation, object Destination, bool Undirected); +public record GraphPathInput(string Prop, GraphNodeInput? Source, GraphRelationInput? Relation, GraphNodeInput? Destination, bool Undirected); /// GraphPathOutput /// Source @@ -626,7 +627,7 @@ public record GraphPathOutput(GraphNodeOutput Source, GraphRelationOutput Relati /// GraphRelationInput /// Label /// Type -public record GraphRelationInput(object Label, object Type); +public record GraphRelationInput(string? Label, string? Type); /// GraphRelationOutput /// Label @@ -639,7 +640,7 @@ public record GraphRelationOutput(string Label, string Type); /// Security metadata for the request. If not provided, the search request is done without the security lookup phase. /// If set to false (default), excludes hidden resources from search /// Query -public record GraphRelationsSearchRequest(int TopK, object FilterExpression, object Security, bool ShowHidden, object Query); +public record GraphRelationsSearchRequest(int TopK, GraphFilterExpression? FilterExpression, RequestSecurity? Security, bool ShowHidden, object Query); /// GraphRelationsSearchResponse /// Relations @@ -651,7 +652,7 @@ public record GraphRelationsSearchResponse(List Relations); /// Security metadata for the request. If not provided, the search request is done without the security lookup phase. /// If set to false (default), excludes hidden resources from search /// Query -public record GraphSearchRequest(int TopK, object FilterExpression, object Security, bool ShowHidden, object Query); +public record GraphSearchRequest(int TopK, GraphFilterExpression? FilterExpression, RequestSecurity? Security, bool ShowHidden, object Query); /// GraphSearchResponse /// Paths @@ -695,7 +696,7 @@ public record Kind(string Prop, string KindValue); /// Sentences /// Shards /// IndexSize -public record KnowledgeboxCounters(int Resources, int Paragraphs, int Fields, int Sentences, object Shards, float IndexSize); +public record KnowledgeboxCounters(int Resources, int Paragraphs, int Fields, int Sentences, List? Shards, float IndexSize); /// Find on knowledgebox results /// Resources @@ -712,7 +713,7 @@ public record KnowledgeboxCounters(int Resources, int Paragraphs, int Fields, in /// The minimum scores that have been used for the search operation. /// List of ids of best matching paragraphs. The list is sorted by decreasing relevance (most relevant first). /// Metrics information about the search operation. The metadata included in this field is subject to change and should not be used in production. This is only available if the `debug` parameter is set to true in the request. -public record KnowledgeboxFindResults(object Resources, object Relations, object Query, object RephrasedQuery, int Total, int PageNumber, int PageSize, bool NextPage, object Nodes, object Shards, List Autofilters, object MinScore, List BestMatches, object Metrics); +public record KnowledgeboxFindResults(object Resources, Relations? Relations, string? Query, string? RephrasedQuery, int Total, int PageNumber, int PageSize, bool NextPage, List? Nodes, List? Shards, List Autofilters, float? MinScore, List BestMatches, object? Metrics); /// Search on knowledgebox results /// Resources @@ -723,19 +724,19 @@ public record KnowledgeboxFindResults(object Resources, object Relations, object /// Nodes /// Shards /// List of filters automatically applied to the search query -public record KnowledgeboxSearchResults(object Resources, object Sentences, object Paragraphs, object Fulltext, object Relations, object Nodes, object Shards, List Autofilters); +public record KnowledgeboxSearchResults(object Resources, Sentences? Sentences, Paragraphs? Paragraphs, Resources? Fulltext, Relations? Relations, List? Nodes, List? Shards, List Autofilters); /// Suggest on resource results /// Paragraphs /// Entities /// Shards -public record KnowledgeboxSuggestResults(object Paragraphs, object Entities, object Shards); +public record KnowledgeboxSuggestResults(Paragraphs? Paragraphs, RelatedEntities? Entities, List? Shards); /// Matches fields/paragraphs with a label (or labelset) /// Prop /// The labelset to match /// The label to match. If blank, matches all labels in the given labelset -public record Label(string Prop, string Labelset, object LabelValue); +public record Label(string Prop, string Labelset, string? LabelValue); /// Matches the language of the field /// Prop @@ -747,7 +748,7 @@ public record Language(string Prop, bool OnlyPrimary, string LanguageValue); /// Metadata /// SplitMetadata /// DeletedSplits -public record LargeComputedMetadata(object Metadata, object SplitMetadata, object DeletedSplits); +public record LargeComputedMetadata(FieldLargeMetadata? Metadata, object? SplitMetadata, List? DeletedSplits); /// LinkExtractedData /// Date @@ -762,7 +763,7 @@ public record LargeComputedMetadata(object Metadata, object SplitMetadata, objec /// Type /// Embed /// FileGenerated -public record LinkExtractedData(object Date, object Language, object Title, object Metadata, object LinkThumbnail, object LinkPreview, object Field, object LinkImage, object Description, object Type, object Embed, object FileGenerated); +public record LinkExtractedData(string? Date, string? Language, string? Title, object? Metadata, CloudLink? LinkThumbnail, CloudLink? LinkPreview, string? Field, CloudLink? LinkImage, string? Description, string? Type, string? Embed, object? FileGenerated); /// LinkFieldData /// Value @@ -770,7 +771,7 @@ public record LinkExtractedData(object Date, object Language, object Title, obje /// Error /// Status /// Errors -public record LinkFieldData(object Value, object Extracted, object Error, object Status, object Errors); +public record LinkFieldData(FieldLink? Value, LinkFieldExtractedData? Extracted, Error? Error, string? Status, List? Errors); /// LinkFieldExtractedData /// Text @@ -779,19 +780,19 @@ public record LinkFieldData(object Value, object Extracted, object Error, object /// Vectors /// QuestionAnswers /// Link -public record LinkFieldExtractedData(object Text, object Metadata, object LargeMetadata, object Vectors, object QuestionAnswers, object Link); +public record LinkFieldExtractedData(ExtractedText? Text, FieldComputedMetadata? Metadata, LargeComputedMetadata? LargeMetadata, VectorObject? Vectors, FieldQuestionAnswers? QuestionAnswers, LinkExtractedData? Link); /// MaxTokens /// Use to limit the amount of tokens used in the LLM context /// Use to limit the amount of tokens used in the LLM answer -public record MaxTokens(object Context, object Answer); +public record MaxTokens(int? Context, int? Answer); /// Metadata /// MetadataValue /// Language /// Languages /// Status -public record Metadata(object MetadataValue, object Language, object Languages, string Status); +public record Metadata(object MetadataValue, string? Language, List? Languages, string Status); /// RAG strategy to enrich the context with metadata of the matching paragraphs or its resources. This strategy can be combined with any of the other strategies. /// Name @@ -801,7 +802,7 @@ public record MetadataExtensionStrategy(string Name, List Types); /// MinScore /// Minimum semantic similarity score used to filter vector index search. If not specified, the default minimum score of the semantic model associated to the Knowledge Box will be used. Check out the documentation for more information on how to use this parameter: https://docs.nuclia.dev/docs/rag/advanced/search#minimum-score /// Minimum score used to filter bm25 index search. Check out the documentation for more information on how to use this parameter: https://docs.nuclia.dev/docs/rag/advanced/search#minimum-score -public record MinScore(object Semantic, float Bm25); +public record MinScore(float? Semantic, float Bm25); /// NeighbouringParagraphsStrategy /// Name @@ -817,7 +818,7 @@ public record NestedListPosition(List Positions); /// Start /// End /// Page -public record NestedPosition(object Start, object End, object Page); +public record NestedPosition(int? Start, int? End, int? Page); /// NewTextField /// TextField @@ -884,7 +885,7 @@ public record OrResourceFilterExpression(List Operands); /// Related /// Path of the original resource. Typically used to store folder structure information of the resource at the origin system. It can be later used for filtering on search endpoints with '/origin.path/{path}' /// Source -public record Origin(object SourceId, object Url, object Created, object Modified, object Metadata, List Tags, List Collaborators, object Filename, List Related, object Path, object Source); +public record Origin(string? SourceId, string? Url, string? Created, string? Modified, object Metadata, List Tags, List Collaborators, string? Filename, List Related, string? Path, string? Source); /// Matches the origin collaborators /// Prop @@ -895,17 +896,17 @@ public record OriginCollaborator(string Prop, string Collaborator); /// Prop /// Metadata field /// Value of the metadata field. If blank, matches any document with the given metadata field set (to any value) -public record OriginMetadata(string Prop, string Field, object Value); +public record OriginMetadata(string Prop, string Field, string? Value); /// Matches the origin path /// Prop /// Prefix of the path, matches all paths under this prefixe.g: `prefix=/dir/` matches `/dir` and `/dir/a/b` but not `/dirrrr` -public record OriginPath(string Prop, object Prefix); +public record OriginPath(string Prop, string? Prefix); /// Matches the origin source id /// Prop /// Source ID -public record OriginSource(string Prop, object Id); +public record OriginSource(string Prop, string? Id); /// Matches all fields with a given origin tag /// Prop @@ -915,17 +916,17 @@ public record OriginTag(string Prop, string Tag); /// PageImageStrategy /// Name /// Maximum number of images to retrieve from the page. By default, at most 5 images are retrieved. -public record PageImageStrategy(string Name, object Count); +public record PageImageStrategy(string Name, int? Count); /// PageInformation /// Page /// PageWithVisual -public record PageInformation(object Page, object PageWithVisual); +public record PageInformation(int? Page, bool? PageWithVisual); /// PagePositions /// Start /// End -public record PagePositions(object Start, object End); +public record PagePositions(int? Start, int? End); /// PageStructure /// Page @@ -970,7 +971,7 @@ public record ParagraphRelations(List Parents, List Siblings, Li /// PageSize /// NextPage /// Minimum bm25 score used to filter bm25 index search. Results with a lower score have been ignored. -public record Paragraphs(List Results, object Facets, object Query, int Total, int PageNumber, int PageSize, bool NextPage, float MinScore); +public record Paragraphs(List Results, object? Facets, string? Query, int Total, int PageNumber, int PageSize, bool NextPage, float MinScore); /// Position /// Start @@ -993,18 +994,18 @@ public record PreQueriesStrategy(string Name, List Queries, float Main /// Weight of the prequery in the context. The weight is used to scale the results of the prequery before adding them to the context.The weight should be a positive number, and they are normalized so that the sum of all weights for all prequeries is 1. /// Identifier of the prequery. If not specified, it is autogenerated based on the index of the prequery in the list (prequery_0, prequery_1, ...). /// If set to true, the prequery results are used to filter the scope of the remaining queries. The resources of the most relevant paragraphs of the prefilter queries are used as resource filters for the main query and other prequeries with the prefilter flag set to false. -public record PreQuery(FindRequest Request, float Weight, object Id, bool Prefilter); +public record PreQuery(FindRequest Request, float Weight, string? Id, bool Prefilter); /// PredictReranker /// Name /// Number of elements reranker will use. Window must be greater or equal to top_k. Greater values will improve results at cost of retrieval and reranking time. By default, this reranker uses a default of 2 times top_k -public record PredictReranker(string Name, object Window); +public record PredictReranker(string Name, int? Window); /// Question /// Text /// Language /// IdsParagraphs -public record Question(string Text, object Language, List IdsParagraphs); +public record Question(string Text, string? Language, List IdsParagraphs); /// QuestionAnswer /// Question @@ -1031,7 +1032,7 @@ public record Reasoning(bool Display, string Effort, int BudgetTokens); /// k parameter changes the influence top-ranked and lower-ranked elements have. Research has shown that 60 is a performant value across datasets /// Number of elements for retrieval to do RRF. Window must be greater or equal to top_k. Greater values will increase probability of multi match at cost of retrieval time /// Boosting -public record ReciprocalRankFusion(string Name, float K, object Window, ReciprocalRankFusionWeights Boosting); +public record ReciprocalRankFusion(string Name, float K, int? Window, ReciprocalRankFusionWeights Boosting); /// ReciprocalRankFusionWeights /// Keyword @@ -1052,7 +1053,7 @@ public record RelatedEntity(string Family, string Value); /// Prop /// Label /// Type -public record RelationInput(string Prop, object Label, object Type); +public record RelationInput(string Prop, string? Label, string? Type); /// RelationOutput /// Relation @@ -1060,13 +1061,13 @@ public record RelationInput(string Prop, object Label, object Type); /// Metadata /// From /// To -public record RelationOutput(string Relation, object Label, object Metadata, object From, RelationEntity To); +public record RelationOutput(string Relation, string? Label, RelationMetadata? Metadata, RelationEntity? From, RelationEntity To); /// RelationEntity /// Value /// Type /// Group -public record RelationEntity(string Value, string Type, object Group); +public record RelationEntity(string Value, string Type, string? Group); /// RelationMetadata /// ParagraphId @@ -1075,7 +1076,7 @@ public record RelationEntity(string Value, string Type, object Group); /// ToStart /// ToEnd /// DataAugmentationTaskId -public record RelationMetadata(object ParagraphId, object SourceStart, object SourceEnd, object ToStart, object ToEnd, object DataAugmentationTaskId); +public record RelationMetadata(string? ParagraphId, int? SourceStart, int? SourceEnd, int? ToStart, int? ToEnd, string? DataAugmentationTaskId); /// Relations /// Entities @@ -1084,7 +1085,7 @@ public record Relations(object Entities); /// Representation /// IsATable /// ReferenceFile -public record Representation(object IsATable, object ReferenceFile); +public record Representation(bool? IsATable, string? ReferenceFile); /// Security metadata for the search request /// List of group ids to do the request with. @@ -1094,7 +1095,7 @@ public record RequestSecurity(List Groups); /// Prop /// UUID of the resource to match /// Slug of the resource to match -public record ResourceInput(string Prop, object Id, object Slug); +public record ResourceInput(string Prop, string? Id, string? Slug); /// ResourceOutput /// Id @@ -1118,12 +1119,12 @@ public record ResourceInput(string Prop, object Id, object Slug); /// Relations /// Data /// Resource security metadata -public record ResourceOutput(string Id, object Slug, object Title, object Summary, object Icon, object Thumbnail, object Metadata, object Usermetadata, object Fieldmetadata, object Computedmetadata, object Created, object Modified, object LastSeqid, object LastAccountSeq, object Queue, object Hidden, object Origin, object Extra, object Relations, object Data, object Security); +public record ResourceOutput(string Id, string? Slug, string? Title, string? Summary, string? Icon, string? Thumbnail, Metadata? Metadata, UserMetadata? Usermetadata, List? Fieldmetadata, ComputedMetadata? Computedmetadata, string? Created, string? Modified, int? LastSeqid, int? LastAccountSeq, string? Queue, bool? Hidden, Origin? Origin, Extra? Extra, List? Relations, ResourceData? Data, ResourceSecurity? Security); /// ResourceAgentsRequest /// Filters to apply to the agents. If None, all curently configured agents are applied. /// AgentIds -public record ResourceAgentsRequest(object Filters, object AgentIds); +public record ResourceAgentsRequest(List? Filters, List? AgentIds); /// ResourceAgentsResponse /// Results @@ -1135,13 +1136,13 @@ public record ResourceAgentsResponse(object Results); /// Links /// Conversations /// Generics -public record ResourceData(object Texts, object Files, object Links, object Conversations, object Generics); +public record ResourceData(object? Texts, object? Files, object? Links, object? Conversations, object? Generics); /// Matches resources with a mimetype. The mimetype of a resource can be assigned independently of the mimetype of its fields. In resources with multiple fields, you may prefer to use `field_mimetype` /// Prop /// Type of the mimetype to match. e.g: In image/jpeg, type is image /// Type of the mimetype to match. e.g: In image/jpeg, subtype is jpeg.Leave blank to match all mimetype of the type -public record ResourceMimetype(string Prop, string Type, object Subtype); +public record ResourceMimetype(string Prop, string Type, string? Subtype); /// ResourceResult /// Score @@ -1149,7 +1150,7 @@ public record ResourceMimetype(string Prop, string Type, object Subtype); /// FieldType /// Field /// Labels -public record ResourceResult(object Score, string Rid, string FieldType, string Field, object Labels); +public record ResourceResult(float? Score, string Rid, string FieldType, string Field, List? Labels); /// Search on resource results /// Sentences @@ -1157,7 +1158,7 @@ public record ResourceResult(object Score, string Rid, string FieldType, string /// Relations /// Nodes /// Shards -public record ResourceSearchResults(object Sentences, object Paragraphs, object Relations, object Nodes, object Shards); +public record ResourceSearchResults(Sentences? Sentences, Paragraphs? Paragraphs, Relations? Relations, List? Nodes, List? Shards); /// Security metadata for the resource /// List of group ids that can access the resource. @@ -1172,15 +1173,15 @@ public record ResourceSecurity(List AccessGroups); /// PageSize /// NextPage /// Minimum bm25 score used to filter bm25 index search. Results with a lower score have been ignored. -public record Resources(List Results, object Facets, object Query, int Total, int PageNumber, int PageSize, bool NextPage, float MinScore); +public record Resources(List Results, object? Facets, string? Query, int Total, int PageNumber, int PageSize, bool NextPage, float MinScore); /// Row /// Cell -public record Row(object Cell); +public record Row(List? Cell); /// RowsPreview /// Sheets -public record RowsPreview(object Sheets); +public record RowsPreview(object? Sheets); /// SearchRequest /// A dictionary containing optional audit-specific metadata, such as user_id, environment, or other contextual information. This metadata can be leveraged for filtering and analyzing activity logs in future operations. Each key-value pair represents a piece of metadata relevant to the user's request. @@ -1213,7 +1214,7 @@ public record RowsPreview(object Sheets); /// List of search features to use. Each value corresponds to a lookup into on of the different indexes /// The list of facets to calculate. The facets follow the same syntax as filters: https://docs.nuclia.dev/docs/rag/advanced/search-filters /// Options for results sorting -public record SearchRequest(object AuditMetadata, string Query, object FilterExpression, List Fields, object Filters, int TopK, object MinScore, object RangeCreationStart, object RangeCreationEnd, object RangeModificationStart, object RangeModificationEnd, bool Debug, bool Highlight, List Show, List FieldTypeFilter, List Extracted, object Vector, object Vectorset, bool WithDuplicates, bool WithSynonyms, bool Autofilter, List ResourceFilters, object Security, bool ShowHidden, bool Rephrase, object RephrasePrompt, object QueryImage, List Features, List Faceted, object Sort); +public record SearchRequest(object? AuditMetadata, string Query, FilterExpression? FilterExpression, List Fields, List? Filters, int TopK, float? MinScore, string? RangeCreationStart, string? RangeCreationEnd, string? RangeModificationStart, string? RangeModificationEnd, bool Debug, bool Highlight, List Show, List FieldTypeFilter, List Extracted, List? Vector, string? Vectorset, bool WithDuplicates, bool WithSynonyms, bool Autofilter, List ResourceFilters, RequestSecurity? Security, bool ShowHidden, bool Rephrase, string? RephrasePrompt, Image? QueryImage, List Features, List Faceted, SortOptions? Sort); /// Sentences /// Results @@ -1225,13 +1226,13 @@ public record Sentences(List Results, object Facet /// Sheet /// Rows -public record Sheet(object Rows); +public record Sheet(List? Rows); /// SortOptions /// Field /// Limit /// Order -public record SortOptions(string Field, object Limit, string Order); +public record SortOptions(string Field, int? Limit, string Order); /// SourceNode /// Prop @@ -1239,14 +1240,14 @@ public record SortOptions(string Field, object Limit, string Order); /// Match /// Type /// Group -public record SourceNode(string Prop, object Value, string Match, object Type, object Group); +public record SourceNode(string Prop, string? Value, string Match, string? Type, string? Group); /// Model for the request payload of the summarize endpoint /// The generative model to use for the summarization. If not provided, the model configured for the Knowledge Box is used. /// Optional custom prompt input by the user /// Uids or slugs of the resources to summarize. If the resources are not found, they will be ignored. /// SummaryKind -public record SummarizeRequest(object GenerativeModel, object UserPrompt, List Resources, string SummaryKind); +public record SummarizeRequest(string? GenerativeModel, string? UserPrompt, List Resources, string SummaryKind); /// SummarizedResource /// Summary of the resource @@ -1257,12 +1258,12 @@ public record SummarizedResource(string Summary, int Tokens); /// Individual resource summaries. The key is the resource id or slug. /// Global summary of all resources combined. /// Consumption -public record SummarizedResponse(object Resources, string Summary, object Consumption); +public record SummarizedResponse(object Resources, string Summary, Consumption? Consumption); /// SyncAskMetadata /// Number of tokens used in the LLM context and answer /// Timings of the generative model -public record SyncAskMetadata(object Tokens, object Timings); +public record SyncAskMetadata(AskTokens? Tokens, AskTimings? Timings); /// SyncAskResponse /// The generative answer to the query @@ -1282,7 +1283,7 @@ public record SyncAskMetadata(object Tokens, object Timings); /// The consumption of the query execution. Return only if 'X-show-consumption' header is set to true in the request. /// Error details message in case there was an error /// Debug information about the ask operation. The metadata included in this field is subject to change and should not be used in production. Note that it is only available if the `debug` parameter is set to true in the request. -public record SyncAskResponse(string Answer, object Reasoning, object AnswerJson, string Status, KnowledgeboxFindResults RetrievalResults, List RetrievalBestMatches, object Prequeries, string LearningId, object Relations, object Citations, object AugmentedContext, object PromptContext, object PredictRequest, object Metadata, object Consumption, object ErrorDetails, object Debug); +public record SyncAskResponse(string Answer, string? Reasoning, object? AnswerJson, string Status, KnowledgeboxFindResults RetrievalResults, List RetrievalBestMatches, object? Prequeries, string LearningId, Relations? Relations, object Citations, AugmentedContext? AugmentedContext, List? PromptContext, object? PredictRequest, SyncAskMetadata? Metadata, Consumption? Consumption, string? ErrorDetails, object? Debug); /// TableImageStrategy /// Name @@ -1294,7 +1295,7 @@ public record TableImageStrategy(string Name); /// Error /// Status /// Errors -public record TextFieldData(object Value, object Extracted, object Error, object Status, object Errors); +public record TextFieldData(FieldText? Value, TextFieldExtractedData? Extracted, Error? Error, string? Status, List? Errors); /// TextFieldExtractedData /// Text @@ -1302,7 +1303,7 @@ public record TextFieldData(object Value, object Extracted, object Error, object /// LargeMetadata /// Vectors /// QuestionAnswers -public record TextFieldExtractedData(object Text, object Metadata, object LargeMetadata, object Vectors, object QuestionAnswers); +public record TextFieldExtractedData(ExtractedText? Text, FieldComputedMetadata? Metadata, LargeComputedMetadata? LargeMetadata, VectorObject? Vectors, FieldQuestionAnswers? QuestionAnswers); /// TextPosition /// PageNumber @@ -1311,7 +1312,7 @@ public record TextFieldExtractedData(object Text, object Metadata, object LargeM /// End /// StartSeconds /// EndSeconds -public record TextPosition(object PageNumber, int Index, int Start, int End, object StartSeconds, object EndSeconds); +public record TextPosition(int? PageNumber, int Index, int Start, int End, List? StartSeconds, List? EndSeconds); /// TokensDetail /// Input @@ -1342,17 +1343,17 @@ public record UserMetadata(List Classifications, ListStartParagraph /// EndParagraph /// VectorValue -public record Vector(object Start, object End, object StartParagraph, object EndParagraph, object VectorValue); +public record Vector(int? Start, int? End, int? StartParagraph, int? EndParagraph, List? VectorValue); /// VectorObject /// Vectors /// SplitVectors /// DeletedSplits -public record VectorObject(object Vectors, object SplitVectors, object DeletedSplits); +public record VectorObject(Vectors? Vectors, object? SplitVectors, List? DeletedSplits); /// Vectors /// VectorsValue -public record Vectors(object VectorsValue); +public record Vectors(List? VectorsValue); /// NucliadbModelsCommonParagraph /// Start @@ -1366,25 +1367,25 @@ public record Vectors(object VectorsValue); /// Page /// Representation /// Relations -public record NucliadbModelsCommonParagraph(object Start, object End, object StartSeconds, object EndSeconds, object Kind, object Classifications, object Sentences, object Key, object Page, object Representation, object Relations); +public record NucliadbModelsCommonParagraph(int? Start, int? End, List? StartSeconds, List? EndSeconds, string? Kind, List? Classifications, List? Sentences, string? Key, PageInformation? Page, Representation? Representation, ParagraphRelations? Relations); /// NucliadbModelsCommonSentence /// Start /// End /// Key -public record NucliadbModelsCommonSentence(object Start, object End, object Key); +public record NucliadbModelsCommonSentence(int? Start, int? End, string? Key); /// Matches if the field was generated by the given source /// Prop /// Generator for this field. Currently, only data-augmentation is supported /// Matches field generated by an specific DA task, given its prefix -public record NucliadbModelsFiltersGenerated(string Prop, string By, object DaTask); +public record NucliadbModelsFiltersGenerated(string Prop, string By, string? DaTask); /// Matches if the relation was generated by the given source /// Prop /// By /// Matches relations generated by an specific DA task, given its prefix -public record NucliadbModelsGraphRequestsGenerated(string Prop, string By, object DaTask); +public record NucliadbModelsGraphRequestsGenerated(string Prop, string By, string? DaTask); /// NucliadbModelsSearchParagraph /// Score @@ -1397,7 +1398,7 @@ public record NucliadbModelsGraphRequestsGenerated(string Prop, string By, objec /// EndSeconds /// Position /// FuzzyResult -public record NucliadbModelsSearchParagraph(float Score, string Rid, string FieldType, string Field, string Text, List Labels, object StartSeconds, object EndSeconds, object Position, bool FuzzyResult); +public record NucliadbModelsSearchParagraph(float Score, string Rid, string FieldType, string Field, string Text, List Labels, List? StartSeconds, List? EndSeconds, TextPosition? Position, bool FuzzyResult); /// NucliadbModelsSearchSentence /// Score @@ -1407,11 +1408,11 @@ public record NucliadbModelsSearchParagraph(float Score, string Rid, string Fiel /// Field /// Index /// Position -public record NucliadbModelsSearchSentence(float Score, string Rid, string Text, string FieldType, string Field, object Index, object Position); +public record NucliadbModelsSearchSentence(float Score, string Rid, string Text, string FieldType, string Field, string? Index, TextPosition? Position); /// AITables /// Llm -public record AITables(object Llm); +public record AITables(LLMConfig? Llm); /// AnthropicKey /// Key @@ -1462,7 +1463,7 @@ public record AnthropicKey(string Key); /// Whether to generate an answer using the generative model. If set to false, the response will only contain the retrieval results. /// Reasoning options for the generative model. Set to True to enable default reasoning, False to disable, or provide a Reasoning object for custom options. /// Query -public record AskConfig(object AuditMetadata, int TopK, object FilterExpression, List Fields, object Filters, object KeywordFilters, object Vectorset, object MinScore, List Features, object RangeCreationStart, object RangeCreationEnd, object RangeModificationStart, object RangeModificationEnd, List Show, List FieldTypeFilter, List Extracted, object Context, object ChatHistory, object ExtraContext, object ExtraContextImages, object QueryImage, bool Autofilter, bool Highlight, List ResourceFilters, object Prompt, object RankFusion, object Reranker, bool Citations, object CitationThreshold, object Security, bool ShowHidden, List RagStrategies, List RagImagesStrategies, bool Debug, object GenerativeModel, object GenerativeModelSeed, object MaxTokens, bool Rephrase, object ChatHistoryRelevanceThreshold, bool PreferMarkdown, object AnswerJsonSchema, bool GenerateAnswer, object Reasoning, object Query); +public record AskConfig(object? AuditMetadata, int TopK, FilterExpression? FilterExpression, List Fields, List? Filters, List? KeywordFilters, string? Vectorset, float? MinScore, List Features, string? RangeCreationStart, string? RangeCreationEnd, string? RangeModificationStart, string? RangeModificationEnd, List Show, List FieldTypeFilter, List Extracted, List? Context, List? ChatHistory, List? ExtraContext, List? ExtraContextImages, Image? QueryImage, bool Autofilter, bool Highlight, List ResourceFilters, string? Prompt, string? RankFusion, string? Reranker, bool Citations, float? CitationThreshold, RequestSecurity? Security, bool ShowHidden, List RagStrategies, List RagImagesStrategies, bool Debug, string? GenerativeModel, int? GenerativeModelSeed, int? MaxTokens, bool Rephrase, float? ChatHistoryRelevanceThreshold, bool PreferMarkdown, object? AnswerJsonSchema, bool GenerateAnswer, Reasoning? Reasoning, string? Query); /// AskSearchConfiguration /// Kind @@ -1486,7 +1487,7 @@ public record AzureOpenAIKey(string Key, string Url, string Deployment, string M /// Entities /// Title /// Color -public record CreateEntitiesGroupPayload(string Group, object Entities, object Title, object Color); +public record CreateEntitiesGroupPayload(string Group, object Entities, string? Title, string? Color); /// CreateExportResponse /// ExportId @@ -1514,7 +1515,7 @@ public record CreateImportResponse(string ImportId); /// Dictionary of conversation fields to be added to the resource. The keys correspond to the field id, and must comply with the regex: ^[a-zA-Z0-9:_-]+$ /// Options for processing the resource. If not set, the default options will be used. /// Security metadata for the resource. It can be used to have fine-grained control over who can access the resource. -public record CreateResourcePayload(object Title, object Summary, object Slug, object Icon, object Thumbnail, object Metadata, object Usermetadata, object Fieldmetadata, object Origin, object Extra, object Hidden, object Files, object Links, object Texts, object Conversations, object ProcessingOptions, object Security); +public record CreateResourcePayload(string? Title, string? Summary, string? Slug, string? Icon, string? Thumbnail, InputMetadata? Metadata, UserMetadata? Usermetadata, List? Fieldmetadata, InputOrigin? Origin, Extra? Extra, bool? Hidden, object Files, object Links, object Texts, object Conversations, PushProcessingOptions? ProcessingOptions, ResourceSecurity? Security); /// CustomSplitStrategy @@ -1525,13 +1526,13 @@ public record CustomSplitStrategy(); /// VllmConfig /// AiTables /// Split -public record ExtractConfig(string Name, object VllmConfig, object AiTables, object Split); +public record ExtractConfig(string Name, VLLMExtractionConfig? VllmConfig, AITables? AiTables, SplitConfig? Split); /// FieldRef /// FieldType /// FieldId /// Split -public record FieldRef(string FieldType, string FieldId, object Split); +public record FieldRef(string FieldType, string FieldId, string? Split); /// File /// Filename @@ -1540,7 +1541,7 @@ public record FieldRef(string FieldType, string FieldId, object Split); /// Md5 /// Uri /// ExtraHeaders -public record File(object Filename, string ContentType, object Payload, object Md5, object Uri, object ExtraHeaders); +public record File(string? Filename, string ContentType, string? Payload, string? Md5, string? Uri, object ExtraHeaders); /// FileB64 /// Filename @@ -1555,7 +1556,7 @@ public record FileB64(string Filename, string ContentType, string Payload, strin /// File /// Id of the Nuclia extract strategy to use at processing time. If not set, the default strategy will be used. Extract strategies are defined at the learning configuration api. /// Id of the Nuclia split strategy used at processing time. If not set, the default strategy was used. Split strategies are defined at the learning configuration api. -public record FileField(object Language, object Password, File File, object ExtractStrategy, object SplitStrategy); +public record FileField(string? Language, string? Password, File File, string? ExtractStrategy, string? SplitStrategy); /// FindConfig /// A dictionary containing optional audit-specific metadata, such as user_id, environment, or other contextual information. This metadata can be leveraged for filtering and analyzing activity logs in future operations. Each key-value pair represents a piece of metadata relevant to the user's request. @@ -1591,7 +1592,7 @@ public record FileField(object Language, object Password, File File, object Extr /// Reranker let you specify which method you want to use to rerank your results at the end of retrieval /// List of keyword filter expressions to apply to the retrieval step. The text block search will only be performed on the documents that contain the specified keywords. The filters are case-insensitive, and only alphanumeric characters and spaces are allowed. Filtering examples can be found here: https://docs.nuclia.dev/docs/rag/advanced/search-filters /// The generative model used to rephrase the query. If not provided, the model configured for the Knowledge Box is used. -public record FindConfig(object AuditMetadata, string Query, object FilterExpression, List Fields, object Filters, int TopK, object MinScore, object RangeCreationStart, object RangeCreationEnd, object RangeModificationStart, object RangeModificationEnd, bool Debug, bool Highlight, List Show, List FieldTypeFilter, List Extracted, object Vector, object Vectorset, bool WithDuplicates, bool WithSynonyms, bool Autofilter, List ResourceFilters, object Security, bool ShowHidden, bool Rephrase, object RephrasePrompt, object QueryImage, object GraphQuery, List Features, object RankFusion, object Reranker, object KeywordFilters, object GenerativeModel); +public record FindConfig(object? AuditMetadata, string Query, FilterExpression? FilterExpression, List Fields, List? Filters, int TopK, float? MinScore, string? RangeCreationStart, string? RangeCreationEnd, string? RangeModificationStart, string? RangeModificationEnd, bool Debug, bool Highlight, List Show, List FieldTypeFilter, List Extracted, List? Vector, string? Vectorset, bool WithDuplicates, bool WithSynonyms, bool Autofilter, List ResourceFilters, RequestSecurity? Security, bool ShowHidden, bool Rephrase, string? RephrasePrompt, Image? QueryImage, object? GraphQuery, List Features, string? RankFusion, string? Reranker, List? KeywordFilters, string? GenerativeModel); /// FindSearchConfiguration /// Kind @@ -1603,7 +1604,7 @@ public record FindSearchConfiguration(string Kind, FindConfig Config); /// Match /// Type /// Group -public record GraphNode(object Value, string Match, object Type, object Group); +public record GraphNode(string? Value, string Match, string? Type, string? Group); /// GraphPath /// Prop @@ -1611,12 +1612,12 @@ public record GraphNode(object Value, string Match, object Type, object Group); /// Relation /// Destination /// Undirected -public record GraphPath(string Prop, object Source, object Relation, object Destination, bool Undirected); +public record GraphPath(string Prop, GraphNode? Source, GraphRelation? Relation, GraphNode? Destination, bool Undirected); /// GraphRelation /// Label /// Type -public record GraphRelation(object Label, object Type); +public record GraphRelation(string? Label, string? Type); /// Some models require a specific template (including prefix) to work correctly in each task For example Snowflake's Arctic-embed requires a specific prefix to work correctly. In that case, the query prompt will be ``` passage_prompt: "" query_prompt: "Represent this sentence for searching relevant passages: {}" ```` where {} will be replaced by the actual sentence. `passage_prompt` is empty because the model does not require alterations to the sentence to embed is as a passage. /// Url @@ -1639,7 +1640,7 @@ public record HFLLMKey(string Key, string Url, ModelType Model); /// List of messages in the conversation field. Each message must have a unique ident. /// Id of the Nuclia extract strategy used at processing time. If not set, the default strategy was used. Extract strategies are defined at the learning configuration api. /// Id of the Nuclia split strategy used at processing time. If not set, the default strategy was used. Split strategies are defined at the learning configuration api. -public record InputConversationField(List Messages, object ExtractStrategy, object SplitStrategy); +public record InputConversationField(List Messages, string? ExtractStrategy, string? SplitStrategy); /// InputMessage /// Time at which the message was sent, in ISO 8601 format. @@ -1648,7 +1649,7 @@ public record InputConversationField(List Messages, object Extract /// Content /// Unique identifier for the message. Must be unique within the conversation. /// Type -public record InputMessage(object Timestamp, object Who, List To, InputMessageContent Content, string Ident, object Type); +public record InputMessage(string? Timestamp, string? Who, List To, InputMessageContent Content, string Ident, string? Type); /// InputMessageContent /// Text @@ -1661,7 +1662,7 @@ public record InputMessageContent(string Text, string Format, List Atta /// Metadata /// Language /// Languages -public record InputMetadata(object Metadata, object Language, object Languages); +public record InputMetadata(object Metadata, string? Language, List? Languages); /// InputOrigin /// SourceId @@ -1674,7 +1675,7 @@ public record InputMetadata(object Metadata, object Language, object Languages); /// Filename /// Related /// Path of the original resource. Typically used to store folder structure information of the resource at the origin system. It can be later used for filtering on search endpoints with '/origin.path/{path}' -public record InputOrigin(object SourceId, object Url, object Created, object Modified, object Metadata, List Tags, List Collaborators, object Filename, List Related, object Path); +public record InputOrigin(string? SourceId, string? Url, string? Created, string? Modified, object Metadata, List Tags, List Collaborators, string? Filename, List Related, string? Path); /// KnowledgeBoxConfigInput /// Slug for the Knowledge Box. @@ -1686,7 +1687,7 @@ public record InputOrigin(object SourceId, object Url, object Created, object Mo /// This field is deprecated. Use 'learning_configuration' instead. /// Allow hiding resources /// Hide newly created resources -public record KnowledgeBoxConfigInput(object Slug, object Title, object Description, object LearningConfiguration, object ExternalIndexProvider, object ConfiguredExternalIndexProvider, object Similarity, bool HiddenResourcesEnabled, bool HiddenResourcesHideOnCreation); +public record KnowledgeBoxConfigInput(string? Slug, string? Title, string? Description, object? LearningConfiguration, PineconeIndexProvider? ExternalIndexProvider, object? ConfiguredExternalIndexProvider, string? Similarity, bool HiddenResourcesEnabled, bool HiddenResourcesHideOnCreation); /// KnowledgeBoxConfigOutput /// Slug for the Knowledge Box. @@ -1698,14 +1699,14 @@ public record KnowledgeBoxConfigInput(object Slug, object Title, object Descript /// This field is deprecated. Use 'learning_configuration' instead. /// Allow hiding resources /// Hide newly created resources -public record KnowledgeBoxConfigOutput(object Slug, object Title, object Description, object LearningConfiguration, object ExternalIndexProvider, object ConfiguredExternalIndexProvider, object Similarity, bool HiddenResourcesEnabled, bool HiddenResourcesHideOnCreation); +public record KnowledgeBoxConfigOutput(string? Slug, string? Title, string? Description, object? LearningConfiguration, PineconeIndexProvider? ExternalIndexProvider, object? ConfiguredExternalIndexProvider, string? Similarity, bool HiddenResourcesEnabled, bool HiddenResourcesHideOnCreation); /// The API representation of a Knowledge Box object. /// Slug /// Uuid /// Config /// Model -public record KnowledgeBoxObj(object Slug, string Uuid, object Config, object Model); +public record KnowledgeBoxObj(string? Slug, string Uuid, KnowledgeBoxConfig? Config, SemanticModelMetadata? Model); /// KnowledgeBoxObjID /// Uuid @@ -1720,12 +1721,12 @@ public record KnowledgeBoxSynonyms(object Synonyms); /// GenerativeModel /// GenerativeProvider /// GenerativePromptId -public record LLMConfig(object UserKeys, string GenerativeModel, string GenerativeProvider, string GenerativePromptId); +public record LLMConfig(UserLearningKeys? UserKeys, string GenerativeModel, string GenerativeProvider, string GenerativePromptId); /// LLMSplitConfig /// Rules /// Llm -public record LLMSplitConfig(List Rules, object Llm); +public record LLMSplitConfig(List Rules, LLMConfig? Llm); /// LabelSet /// Title @@ -1733,7 +1734,7 @@ public record LLMSplitConfig(List Rules, object Llm); /// Multiple /// Kind /// Labels -public record LabelSet(object Title, object Color, bool Multiple, List Kind, List Labels); +public record LabelSet(string? Title, string? Color, bool Multiple, List Kind, List Labels); /// LinkField /// Headers @@ -1745,7 +1746,7 @@ public record LabelSet(object Title, object Color, bool Multiple, List K /// Xpath /// Id of the Nuclia extract strategy to use at processing time. If not set, the default strategy will be used. Extract strategies are defined at the learning configuration api. /// Id of the Nuclia split strategy used at processing time. If not set, the default strategy was used. Split strategies are defined at the learning configuration api. -public record LinkField(object Headers, object Cookies, string Uri, object Language, object Localstorage, object CssSelector, object Xpath, object ExtractStrategy, object SplitStrategy); +public record LinkField(object? Headers, object? Cookies, string Uri, string? Language, object? Localstorage, string? CssSelector, string? Xpath, string? ExtractStrategy, string? SplitStrategy); /// ManualSplitConfig /// Splitter @@ -1782,39 +1783,39 @@ public record PineconeIndexProvider(string Type, string ApiKey, string Serverles /// PushProcessingOptions /// MlText -public record PushProcessingOptions(object MlText); +public record PushProcessingOptions(bool? MlText); /// Matches all fields of a resource given its id or slug /// Prop /// UUID of the resource to match /// Slug of the resource to match -public record Resource(string Prop, object Id, object Slug); +public record Resource(string Prop, string? Id, string? Slug); /// ResourceCreated /// Uuid /// Elapsed /// Seqid -public record ResourceCreated(string Uuid, object Elapsed, object Seqid); +public record ResourceCreated(string Uuid, float? Elapsed, int? Seqid); /// ResourceFieldAdded /// Seqid -public record ResourceFieldAdded(object Seqid); +public record ResourceFieldAdded(int? Seqid); /// ResourceFileUploaded /// Seqid /// Uuid /// FieldId -public record ResourceFileUploaded(object Seqid, object Uuid, object FieldId); +public record ResourceFileUploaded(int? Seqid, string? Uuid, string? FieldId); /// ResourceUpdated /// Seqid -public record ResourceUpdated(object Seqid); +public record ResourceUpdated(int? Seqid); /// Metadata of the semantic model associated to the KB /// SimilarityFunction /// Dimension of the indexed vectors/embeddings /// Deprecated -public record SemanticModelMetadata(string SimilarityFunction, object VectorDimension, object DefaultMinScore); +public record SemanticModelMetadata(string SimilarityFunction, int? VectorDimension, float? DefaultMinScore); /// SplitConfig /// MaxParagraph @@ -1826,14 +1827,14 @@ public record SplitConfig(int MaxParagraph); /// CustomSplit /// LlmSplit /// ManualSplit -public record SplitConfiguration(string Name, int MaxParagraph, object CustomSplit, object LlmSplit, object ManualSplit); +public record SplitConfiguration(string Name, int MaxParagraph, CustomSplitStrategy? CustomSplit, LLMSplitConfig? LlmSplit, ManualSplitConfig? ManualSplit); /// TextField /// The text body. The format of the text should be specified in the format field. The sum of all text fields in the request may not exceed 2MB. If you need to store more text, consider using a file field instead or splitting into multiple requests for each text field. /// Format /// Id of the Nuclia extract strategy to use at processing time. If not set, the default strategy will be used. Extract strategies are defined at the learning configuration api. /// Id of the Nuclia split strategy used at processing time. If not set, the default strategy was used. Split strategies are defined at the learning configuration api. -public record TextField(string Body, string Format, object ExtractStrategy, object SplitStrategy); +public record TextField(string Body, string Format, string? ExtractStrategy, string? SplitStrategy); /// TextGenerationKey /// Model @@ -1845,7 +1846,7 @@ public record TextGenerationKey(string Model); /// Add /// Update /// Delete -public record UpdateEntitiesGroupPayload(object Title, object Color, object Add, object Update, List Delete); +public record UpdateEntitiesGroupPayload(string? Title, string? Color, object Add, object Update, List Delete); /// UpdateResourcePayload /// Title @@ -1864,7 +1865,7 @@ public record UpdateEntitiesGroupPayload(object Title, object Color, object Add, /// Options for processing the resource. If not set, the default options will be used. /// Security metadata for the resource. It can be used to have fine-grained control over who can access the resource. /// Modify the hidden status of the resource. If not set, the hidden status will not be modified. -public record UpdateResourcePayload(object Title, object Summary, object Slug, object Thumbnail, object Metadata, object Usermetadata, object Fieldmetadata, object Origin, object Extra, object Files, object Links, object Texts, object Conversations, object ProcessingOptions, object Security, object Hidden); +public record UpdateResourcePayload(string? Title, string? Summary, string? Slug, string? Thumbnail, InputMetadata? Metadata, UserMetadata? Usermetadata, List? Fieldmetadata, InputOrigin? Origin, Extra? Extra, object Files, object Links, object Texts, object Conversations, PushProcessingOptions? ProcessingOptions, ResourceSecurity? Security, bool? Hidden); /// UserLearningKeys /// Openai @@ -1877,12 +1878,12 @@ public record UpdateResourcePayload(object Title, object Summary, object Slug, o /// AzureMistral /// HfLlm /// HfEmbedding -public record UserLearningKeys(object Openai, object AzureOpenai, object Palm, object Anthropic, object Claude3, object TextGeneration, object Mistral, object AzureMistral, object HfLlm, object HfEmbedding); +public record UserLearningKeys(OpenAIKey? Openai, AzureOpenAIKey? AzureOpenai, PalmKey? Palm, AnthropicKey? Anthropic, AnthropicKey? Claude3, TextGenerationKey? TextGeneration, MistralKey? Mistral, AzureMistralKey? AzureMistral, HFLLMKey? HfLlm, HFEmbeddingKey? HfEmbedding); /// VLLMExtractionConfig /// Rules /// Llm -public record VLLMExtractionConfig(List Rules, object Llm); +public record VLLMExtractionConfig(List Rules, LLMConfig? Llm); /// NucliadbModelsEntitiesEntity /// Value @@ -1894,26 +1895,26 @@ public record NucliadbModelsEntitiesEntity(string Value, bool Merged, ListProp /// Type of the entity. e.g: PERSON /// Value of the entity. e.g: Anna. If blank, matches any entity of the given type -public record NucliadbModelsFiltersEntity(string Prop, string Subtype, object Value); +public record NucliadbModelsFiltersEntity(string Prop, string Subtype, string? Value); /// Matches fields/paragraphs with a label (or labelset) /// Prop /// The labelset to match /// The label to match. If blank, matches all labels in the given labelset -public record NucliadbModelsFiltersLabel(string Prop, string Labelset, object Label); +public record NucliadbModelsFiltersLabel(string Prop, string Labelset, string? Label); /// NucliadbModelsGraphRequestsRelation /// Prop /// Label /// Type -public record NucliadbModelsGraphRequestsRelation(string Prop, object Label, object Type); +public record NucliadbModelsGraphRequestsRelation(string Prop, string? Label, string? Type); /// NucliadbModelsLabelsLabel /// Title /// Related /// Text /// Uri -public record NucliadbModelsLabelsLabel(string Title, object Related, object Text, object Uri); +public record NucliadbModelsLabelsLabel(string Title, string? Related, string? Text, string? Uri); /// NucliadbModelsMetadataRelation /// Relation @@ -1921,21 +1922,21 @@ public record NucliadbModelsLabelsLabel(string Title, object Related, object Tex /// Metadata /// From /// To -public record NucliadbModelsMetadataRelation(string Relation, object Label, object Metadata, object From, RelationEntity To); +public record NucliadbModelsMetadataRelation(string Relation, string? Label, RelationMetadata? Metadata, RelationEntity? From, RelationEntity To); /// EntitiesGroup /// Title of the entities group /// Color of the entities group. This is for display purposes only. /// Denotes if it has been created by the user /// Entities -public record EntitiesGroup(object Title, object Color, bool Custom, object Entities); +public record EntitiesGroup(string? Title, string? Color, bool Custom, object Entities); /// EntitiesGroupSummary /// Title of the entities group /// Color of the entities group. This is for display purposes only. /// Denotes if it has been created by the user /// This field is deprecated and will be removed in future versions. It will always be empty. Use the /api/v1/kb/{kbid}/entitiesgroup/{group} endpoint to get the entities of a group. -public record EntitiesGroupSummary(object Title, object Color, bool Custom, object Entities); +public record EntitiesGroupSummary(string? Title, string? Color, bool Custom, object Entities); /// KnowledgeBoxConfig /// Slug for the Knowledge Box. @@ -1947,7 +1948,7 @@ public record EntitiesGroupSummary(object Title, object Color, bool Custom, obje /// This field is deprecated. Use 'learning_configuration' instead. /// Allow hiding resources /// Hide newly created resources -public record KnowledgeBoxConfig(object Slug, object Title, object Description, object LearningConfiguration, object ExternalIndexProvider, object ConfiguredExternalIndexProvider, object Similarity, bool HiddenResourcesEnabled, bool HiddenResourcesHideOnCreation); +public record KnowledgeBoxConfig(string? Slug, string? Title, string? Description, object? LearningConfiguration, PineconeIndexProvider? ExternalIndexProvider, object? ConfiguredExternalIndexProvider, string? Similarity, bool HiddenResourcesEnabled, bool HiddenResourcesHideOnCreation); /// KnowledgeBoxEntities /// Uuid @@ -1971,7 +1972,7 @@ public record KnowledgeBoxLabels(string Uuid, object Labelsets); /// Page /// Representation /// Relations -public record Paragraph(object Start, object End, object StartSeconds, object EndSeconds, object Kind, object Classifications, object Sentences, object Key, object Page, object Representation, object Relations); +public record Paragraph(int? Start, int? End, List? StartSeconds, List? EndSeconds, string? Kind, List? Classifications, List? Sentences, string? Key, PageInformation? Page, Representation? Representation, ParagraphRelations? Relations); /// RequestsResult /// Processing ID of the resource. @@ -1988,12 +1989,12 @@ public record Paragraph(object Start, object End, object StartSeconds, object En /// Number of retries for the resource. /// Estimated time until the resource is scheduled. /// Order of the resource in the schedule queue. -public record RequestsResult(string ProcessingId, string ResourceId, string Kbid, object Title, List Labels, bool Completed, bool Scheduled, string Timestamp, object CompletedAt, object ScheduledAt, bool Failed, int Retries, float ScheduleEta, int ScheduleOrder); +public record RequestsResult(string ProcessingId, string ResourceId, string Kbid, string? Title, List Labels, bool Completed, bool Scheduled, string Timestamp, string? CompletedAt, string? ScheduledAt, bool Failed, int Retries, float ScheduleEta, int ScheduleOrder); /// RequestsResults /// List of results. /// Cursor to use for the next page of results. -public record RequestsResults(List Results, object Cursor); +public record RequestsResults(List Results, string? Cursor); /// ResourceField /// FieldType @@ -2003,7 +2004,7 @@ public record RequestsResults(List Results, object Cursor); /// Error /// Status /// Errors -public record ResourceField(string FieldType, string FieldId, object Value, object Extracted, object Error, object Status, object Errors); +public record ResourceField(string FieldType, string FieldId, object Value, TextFieldExtractedData? Extracted, Error? Error, string? Status, List? Errors); /// ResourceList /// Resources @@ -2020,7 +2021,7 @@ public record ResourcePagination(int Page, int Size, bool Last); /// Start /// End /// Key -public record Sentence(object Start, object End, object Key); +public record Sentence(int? Start, int? End, string? Key); /// StatusResponse /// Status @@ -2033,13 +2034,13 @@ public record StatusResponse(string Status, int Total, int Processed, int Retrie /// Token /// Root /// Type -public record NucliadbModelsExtractedEntity(object Token, object Root, object Type); +public record NucliadbModelsExtractedEntity(string? Token, string? Root, string? Type); /// Matches all fields of a resource given its id or slug /// Prop /// UUID of the resource to match /// Slug of the resource to match -public record NucliadbModelsFiltersResource(string Prop, object Id, object Slug); +public record NucliadbModelsFiltersResource(string Prop, string? Id, string? Slug); /// NucliadbModelsResourceResource /// Id @@ -2063,4 +2064,4 @@ public record NucliadbModelsFiltersResource(string Prop, object Id, object Slug) /// Relations /// Data /// Resource security metadata -public record NucliadbModelsResourceResource(string Id, object Slug, object Title, object Summary, object Icon, object Thumbnail, object Metadata, object Usermetadata, object Fieldmetadata, object Computedmetadata, object Created, object Modified, object LastSeqid, object LastAccountSeq, object Queue, object Hidden, object Origin, object Extra, object Relations, object Data, object Security); \ No newline at end of file +public record NucliadbModelsResourceResource(string Id, string? Slug, string? Title, string? Summary, string? Icon, string? Thumbnail, Metadata? Metadata, UserMetadata? Usermetadata, List? Fieldmetadata, ComputedMetadata? Computedmetadata, string? Created, string? Modified, int? LastSeqid, int? LastAccountSeq, string? Queue, bool? Hidden, Origin? Origin, Extra? Extra, List? Relations, ResourceData? Data, ResourceSecurity? Security); \ No newline at end of file diff --git a/Samples/NucliaDbClient/Generated/NucliaDbMcpTools.g.cs b/Samples/NucliaDbClient/Generated/NucliaDbMcpTools.g.cs index 8bafd7fa..13d059a7 100644 --- a/Samples/NucliaDbClient/Generated/NucliaDbMcpTools.g.cs +++ b/Samples/NucliaDbClient/Generated/NucliaDbMcpTools.g.cs @@ -116,9 +116,9 @@ public static async Task AskKnowledgeboxEndpointKbKbidAsk(HttpClient htt /// Controls which types of metadata are serialized on resources of search results /// HttpClient instance [McpServerTool, Description("List resources of a Knowledge Box --- ## Authorization roles Authenticated user needs to fulfill one of this roles, otherwise the request will be rejected with a `403` response. - `READER`")] - public static async Task CatalogGetKbKbidCatalog(HttpClient httpClient, string kbid, string? query = null, object? filterExpression = null, List? filters = null, List? faceted = null, string? sortField = null, object? sortLimit = null, string sortOrder = "desc", int pageNumber = 0, int pageSize = 20, object? withStatus = null, object? rangeCreationStart = null, object? rangeCreationEnd = null, object? rangeModificationStart = null, object? rangeModificationEnd = null, object? hidden = null, List? show = null) + public static async Task CatalogGetKbKbidCatalog(HttpClient httpClient, string kbid, string? query = null, string? filterExpression = null, List? filters = null, List? faceted = null, string? sortField = null, int? sortLimit = null, string sortOrder = "desc", int pageNumber = 0, int pageSize = 20, string? withStatus = null, string? rangeCreationStart = null, string? rangeCreationEnd = null, string? rangeModificationStart = null, string? rangeModificationEnd = null, bool? hidden = null, List? show = null) { - var result = await httpClient.CatalogGetKbKbidCatalogAsync(kbid, query ?? "", filterExpression, filters, faceted, sortField ?? "", sortLimit, sortOrder, pageNumber, pageSize, withStatus, rangeCreationStart, rangeCreationEnd, rangeModificationStart, rangeModificationEnd, hidden, show, CancellationToken.None); + var result = await httpClient.CatalogGetKbKbidCatalogAsync(kbid, query ?? "", filterExpression ?? "", filters, faceted, sortField ?? "", sortLimit, sortOrder, pageNumber, pageSize, withStatus ?? "", rangeCreationStart ?? "", rangeCreationEnd ?? "", rangeModificationStart ?? "", rangeModificationEnd ?? "", hidden, show, CancellationToken.None); return result switch { @@ -374,9 +374,9 @@ public static async Task SendFeedbackEndpointKbKbidFeedback(HttpClient h /// xForwardedFor /// HttpClient instance [McpServerTool, Description("Find on a Knowledge Box --- ## Authorization roles Authenticated user needs to fulfill one of this roles, otherwise the request will be rejected with a `403` response. - `READER`")] - public static async Task FindKnowledgeboxKbKbidFind(HttpClient httpClient, string kbid, string? query = null, object? filterExpression = null, List? fields = null, List? filters = null, object? topK = null, object? minScore = null, object? minScoreSemantic = null, float minScoreBm25 = 0, object? vectorset = null, object? rangeCreationStart = null, object? rangeCreationEnd = null, object? rangeModificationStart = null, object? rangeModificationEnd = null, List? features = null, bool debug = false, bool highlight = false, List? show = null, List? fieldType = null, List? extracted = null, bool withDuplicates = false, bool withSynonyms = false, bool autofilter = false, List? securityGroups = null, bool showHidden = false, string rankFusion = "rrf", object? reranker = null, object? searchConfiguration = null, string xNdbClient = "api", string? xNucliadbUser = null, string? xForwardedFor = null) + public static async Task FindKnowledgeboxKbKbidFind(HttpClient httpClient, string kbid, string? query = null, string? filterExpression = null, List? fields = null, List? filters = null, int? topK = null, float? minScore = null, float? minScoreSemantic = null, float minScoreBm25 = 0, string? vectorset = null, string? rangeCreationStart = null, string? rangeCreationEnd = null, string? rangeModificationStart = null, string? rangeModificationEnd = null, List? features = null, bool debug = false, bool highlight = false, List? show = null, List? fieldType = null, List? extracted = null, bool withDuplicates = false, bool withSynonyms = false, bool autofilter = false, List? securityGroups = null, bool showHidden = false, string rankFusion = "rrf", string? reranker = null, string? searchConfiguration = null, string xNdbClient = "api", string? xNucliadbUser = null, string? xForwardedFor = null) { - var result = await httpClient.FindKnowledgeboxKbKbidFindAsync(kbid, query ?? "", filterExpression, fields, filters, topK, minScore, minScoreSemantic, minScoreBm25, vectorset, rangeCreationStart, rangeCreationEnd, rangeModificationStart, rangeModificationEnd, features, debug, highlight, show, fieldType, extracted, withDuplicates, withSynonyms, autofilter, securityGroups, showHidden, rankFusion, reranker, searchConfiguration, xNdbClient, xNucliadbUser ?? "", xForwardedFor ?? "", CancellationToken.None); + var result = await httpClient.FindKnowledgeboxKbKbidFindAsync(kbid, query ?? "", filterExpression ?? "", fields, filters, topK, minScore, minScoreSemantic, minScoreBm25, vectorset ?? "", rangeCreationStart ?? "", rangeCreationEnd ?? "", rangeModificationStart ?? "", rangeModificationEnd ?? "", features, debug, highlight, show, fieldType, extracted, withDuplicates, withSynonyms, autofilter, securityGroups, showHidden, rankFusion, reranker ?? "", searchConfiguration ?? "", xNdbClient, xNucliadbUser ?? "", xForwardedFor ?? "", CancellationToken.None); return result switch { @@ -664,9 +664,9 @@ public static async Task ResourceAskEndpointByUuidKbKbidResourceRidAsk(H /// xNdbClient /// HttpClient instance [McpServerTool, Description("Search on a single resource --- ## Authorization roles Authenticated user needs to fulfill one of this roles, otherwise the request will be rejected with a `403` response. - `READER`")] - public static async Task ResourceSearchKbKbidResourceRidSearch(HttpClient httpClient, string kbid, string rid, string query, object? filterExpression = null, List? fields = null, List? filters = null, List? faceted = null, object? sortField = null, string sortOrder = "desc", object? topK = null, object? rangeCreationStart = null, object? rangeCreationEnd = null, object? rangeModificationStart = null, object? rangeModificationEnd = null, bool highlight = false, bool debug = false, string xNdbClient = "api") + public static async Task ResourceSearchKbKbidResourceRidSearch(HttpClient httpClient, string kbid, string rid, string query, string? filterExpression = null, List? fields = null, List? filters = null, List? faceted = null, string? sortField = null, string sortOrder = "desc", int? topK = null, string? rangeCreationStart = null, string? rangeCreationEnd = null, string? rangeModificationStart = null, string? rangeModificationEnd = null, bool highlight = false, bool debug = false, string xNdbClient = "api") { - var result = await httpClient.ResourceSearchKbKbidResourceRidSearchAsync(kbid, rid, query, filterExpression, fields, filters, faceted, sortField, sortOrder, topK, rangeCreationStart, rangeCreationEnd, rangeModificationStart, rangeModificationEnd, highlight, debug, xNdbClient, CancellationToken.None); + var result = await httpClient.ResourceSearchKbKbidResourceRidSearchAsync(kbid, rid, query, filterExpression ?? "", fields, filters, faceted, sortField ?? "", sortOrder, topK, rangeCreationStart ?? "", rangeCreationEnd ?? "", rangeModificationStart ?? "", rangeModificationEnd ?? "", highlight, debug, xNdbClient, CancellationToken.None); return result switch { @@ -719,9 +719,9 @@ public static async Task ResourceSearchKbKbidResourceRidSearch(HttpClien /// xForwardedFor /// HttpClient instance [McpServerTool, Description("Search on a Knowledge Box and retrieve separate results for documents, paragraphs, and sentences. Usually, it is better to use `find` --- ## Authorization roles Authenticated user needs to fulfill one of this roles, otherwise the request will be rejected with a `403` response. - `READER`")] - public static async Task SearchKnowledgeboxKbKbidSearch(HttpClient httpClient, string kbid, string? query = null, object? filterExpression = null, List? fields = null, List? filters = null, List? faceted = null, string? sortField = null, object? sortLimit = null, string sortOrder = "desc", int topK = 20, object? minScore = null, object? minScoreSemantic = null, float minScoreBm25 = 0, object? vectorset = null, object? rangeCreationStart = null, object? rangeCreationEnd = null, object? rangeModificationStart = null, object? rangeModificationEnd = null, List? features = null, bool debug = false, bool highlight = false, List? show = null, List? fieldType = null, List? extracted = null, bool withDuplicates = false, bool withSynonyms = false, bool autofilter = false, List? securityGroups = null, bool showHidden = false, string xNdbClient = "api", string? xNucliadbUser = null, string? xForwardedFor = null) + public static async Task SearchKnowledgeboxKbKbidSearch(HttpClient httpClient, string kbid, string? query = null, string? filterExpression = null, List? fields = null, List? filters = null, List? faceted = null, string? sortField = null, int? sortLimit = null, string sortOrder = "desc", int topK = 20, float? minScore = null, float? minScoreSemantic = null, float minScoreBm25 = 0, string? vectorset = null, string? rangeCreationStart = null, string? rangeCreationEnd = null, string? rangeModificationStart = null, string? rangeModificationEnd = null, List? features = null, bool debug = false, bool highlight = false, List? show = null, List? fieldType = null, List? extracted = null, bool withDuplicates = false, bool withSynonyms = false, bool autofilter = false, List? securityGroups = null, bool showHidden = false, string xNdbClient = "api", string? xNucliadbUser = null, string? xForwardedFor = null) { - var result = await httpClient.SearchKnowledgeboxKbKbidSearchAsync(kbid, query ?? "", filterExpression, fields, filters, faceted, sortField ?? "", sortLimit, sortOrder, topK, minScore, minScoreSemantic, minScoreBm25, vectorset, rangeCreationStart, rangeCreationEnd, rangeModificationStart, rangeModificationEnd, features, debug, highlight, show, fieldType, extracted, withDuplicates, withSynonyms, autofilter, securityGroups, showHidden, xNdbClient, xNucliadbUser ?? "", xForwardedFor ?? "", CancellationToken.None); + var result = await httpClient.SearchKnowledgeboxKbKbidSearchAsync(kbid, query ?? "", filterExpression ?? "", fields, filters, faceted, sortField ?? "", sortLimit, sortOrder, topK, minScore, minScoreSemantic, minScoreBm25, vectorset ?? "", rangeCreationStart ?? "", rangeCreationEnd ?? "", rangeModificationStart ?? "", rangeModificationEnd ?? "", features, debug, highlight, show, fieldType, extracted, withDuplicates, withSynonyms, autofilter, securityGroups, showHidden, xNdbClient, xNucliadbUser ?? "", xForwardedFor ?? "", CancellationToken.None); return result switch { @@ -819,9 +819,9 @@ public static async Task ResourceAskEndpointBySlugKbKbidSlugSlugAsk(Http /// xForwardedFor /// HttpClient instance [McpServerTool, Description("Suggestions on a knowledge box --- ## Authorization roles Authenticated user needs to fulfill one of this roles, otherwise the request will be rejected with a `403` response. - `READER`")] - public static async Task SuggestKnowledgeboxKbKbidSuggest(HttpClient httpClient, string kbid, string query, List? fields = null, List? filters = null, List? faceted = null, object? rangeCreationStart = null, object? rangeCreationEnd = null, object? rangeModificationStart = null, object? rangeModificationEnd = null, List? features = null, List? show = null, List? fieldType = null, bool debug = false, bool highlight = false, bool showHidden = false, string xNdbClient = "api", string? xNucliadbUser = null, string? xForwardedFor = null) + public static async Task SuggestKnowledgeboxKbKbidSuggest(HttpClient httpClient, string kbid, string query, List? fields = null, List? filters = null, List? faceted = null, string? rangeCreationStart = null, string? rangeCreationEnd = null, string? rangeModificationStart = null, string? rangeModificationEnd = null, List? features = null, List? show = null, List? fieldType = null, bool debug = false, bool highlight = false, bool showHidden = false, string xNdbClient = "api", string? xNucliadbUser = null, string? xForwardedFor = null) { - var result = await httpClient.SuggestKnowledgeboxKbKbidSuggestAsync(kbid, query, fields, filters, faceted, rangeCreationStart, rangeCreationEnd, rangeModificationStart, rangeModificationEnd, features, show, fieldType, debug, highlight, showHidden, xNdbClient, xNucliadbUser ?? "", xForwardedFor ?? "", CancellationToken.None); + var result = await httpClient.SuggestKnowledgeboxKbKbidSuggestAsync(kbid, query, fields, filters, faceted, rangeCreationStart ?? "", rangeCreationEnd ?? "", rangeModificationStart ?? "", rangeModificationEnd ?? "", features, show, fieldType, debug, highlight, showHidden, xNdbClient, xNucliadbUser ?? "", xForwardedFor ?? "", CancellationToken.None); return result switch { @@ -876,9 +876,9 @@ public static async Task SummarizeEndpointKbKbidSummarize(HttpClient htt /// Request body /// HttpClient instance [McpServerTool, Description("Upload a file onto a Knowledge Box, field id will be file and rid will be autogenerated. --- ## Authorization roles Authenticated user needs to fulfill one of this roles, otherwise the request will be rejected with a `403` response. - `WRITER`")] - public static async Task UploadKbKbidUpload(HttpClient httpClient, string kbid, object body, object? xFilename = null, object? xPassword = null, object? xLanguage = null, object? xMd5 = null, object? xExtractStrategy = null, object? xSplitStrategy = null) + public static async Task UploadKbKbidUpload(HttpClient httpClient, string kbid, object body, string? xFilename = null, string? xPassword = null, string? xLanguage = null, string? xMd5 = null, string? xExtractStrategy = null, string? xSplitStrategy = null) { - var result = await httpClient.UploadKbKbidUploadAsync(kbid, body, xFilename, xPassword, xLanguage, xMd5, xExtractStrategy, xSplitStrategy, CancellationToken.None); + var result = await httpClient.UploadKbKbidUploadAsync(kbid, body, xFilename ?? "", xPassword ?? "", xLanguage ?? "", xMd5 ?? "", xExtractStrategy ?? "", xSplitStrategy ?? "", CancellationToken.None); return result switch { diff --git a/Samples/RestClient.OpenApiGenerator.Sample.JSONPlaceholder/Generated/JSONPlaceholderApiModels.g.cs b/Samples/RestClient.OpenApiGenerator.Sample.JSONPlaceholder/Generated/JSONPlaceholderApiModels.g.cs index a23d0b15..5b371cff 100644 --- a/Samples/RestClient.OpenApiGenerator.Sample.JSONPlaceholder/Generated/JSONPlaceholderApiModels.g.cs +++ b/Samples/RestClient.OpenApiGenerator.Sample.JSONPlaceholder/Generated/JSONPlaceholderApiModels.g.cs @@ -1,3 +1,4 @@ +#nullable enable namespace JSONPlaceholder.Generated; /// Todo From dab9013bea0e0656b71b376414e152a7f085eb11 Mon Sep 17 00:00:00 2001 From: Christian Findlay <16697547+MelbourneDeveloper@users.noreply.github.com> Date: Wed, 22 Oct 2025 21:23:29 +1100 Subject: [PATCH 3/4] Add tests --- .../NucliaDbClient.Tests/TypeSafetyTests.cs | 359 ++++++++++++++++++ 1 file changed, 359 insertions(+) create mode 100644 Samples/NucliaDbClient.Tests/TypeSafetyTests.cs diff --git a/Samples/NucliaDbClient.Tests/TypeSafetyTests.cs b/Samples/NucliaDbClient.Tests/TypeSafetyTests.cs new file mode 100644 index 00000000..234ebcee --- /dev/null +++ b/Samples/NucliaDbClient.Tests/TypeSafetyTests.cs @@ -0,0 +1,359 @@ +using Microsoft.Extensions.DependencyInjection; +using NucliaDB.Generated; +using Outcome; +using Xunit; + +#pragma warning disable CS8509 // C# compiler doesn't understand nested discriminated unions - use EXHAUSTION001 instead +#pragma warning disable SA1512 // Single-line comments should not be followed by blank line + +namespace NucliaDbClient.Tests; + +/// +/// Tests to verify that issue #142 is fixed: anyOf types are now properly resolved +/// to their concrete types instead of being generated as 'object'. +/// +[Collection("NucliaDB Tests")] +[TestCaseOrderer("NucliaDbClient.Tests.PriorityOrderer", "NucliaDbClient.Tests")] +public class TypeSafetyTests +{ + #region Setup + private readonly IHttpClientFactory _httpClientFactory; + private static string? _knowledgeBoxId; + + public TypeSafetyTests(NucliaDbFixture fixture) + { + _ = fixture; // Ensure fixture is initialized + var services = new ServiceCollection(); + services.AddHttpClient(); + var serviceProvider = services.BuildServiceProvider(); + _httpClientFactory = serviceProvider.GetRequiredService(); + } + + private HttpClient CreateHttpClient() => _httpClientFactory.CreateClient(); + #endregion + + [Fact] + [TestPriority(-1)] + public async Task CreateKnowledgeBox_ForTypeTests() + { + var payload = new { slug = $"typesafe-kb-{Guid.NewGuid()}", title = "Type Safety Test KB" }; + + var result = await CreateHttpClient() + .CreateKnowledgeBoxKbsAsync(body: payload, xNUCLIADBROLES: "MANAGER"); + + var kb = result switch + { + OkKnowledgeBoxObj(var value) => value, + ErrorKnowledgeBoxObj(HttpError.ExceptionError(var ex)) => + throw new InvalidOperationException("Failed to create knowledge box", ex), + ErrorKnowledgeBoxObj( + HttpError.ErrorResponseError + (var body, var statusCode, _) + ) => throw new InvalidOperationException( + $"Failed to create knowledge box: HTTP {statusCode}: {body}" + ), + }; + + Assert.NotNull(kb); + Assert.NotNull(kb.Uuid); + _knowledgeBoxId = kb.Uuid; + } + + /// + /// Verifies that KnowledgeBoxObj.Config is typed as KnowledgeBoxConfig (not object). + /// This is a compile-time check - if Config were 'object', the property access would fail. + /// + /// Task. + [Fact] + [TestPriority(1)] + public async Task KnowledgeBoxObj_Config_IsTypedAsKnowledgeBoxConfig_NotObject() + { + // Arrange & Act + var result = await CreateHttpClient() + .KbKbKbidGetAsync(kbid: _knowledgeBoxId!, xNUCLIADBROLES: "READER"); + + var kb = result switch + { + OkKnowledgeBoxObjHTTPValidationError(var value) => value, + ErrorKnowledgeBoxObjHTTPValidationError( + HttpError.ExceptionError + (var ex) + ) => throw new InvalidOperationException("API call failed with exception", ex), + ErrorKnowledgeBoxObjHTTPValidationError( + HttpError.ErrorResponseError + (var body, var statusCode, _) + ) => throw new InvalidOperationException($"API call failed: HTTP {statusCode}: {body}"), + }; + + // Assert - These assertions will only compile if Config is KnowledgeBoxConfig (not object) + Assert.NotNull(kb); + + // If Config is object, we can't access these properties without casting + // The fact this compiles proves Config is KnowledgeBoxConfig + if (kb.Config is { } config) + { + // Access Config properties in a type-safe manner + var slug = config.Slug; + var hiddenResourcesEnabled = config.HiddenResourcesEnabled; + var hiddenResourcesHideOnCreation = config.HiddenResourcesHideOnCreation; + + // These properties exist on KnowledgeBoxConfig but not on object + Assert.NotNull(slug); + + // Verify we can access the bool properties (wouldn't work if Config were object) + // The fact that this compiles without casting proves the types are correct + _ = hiddenResourcesEnabled; + _ = hiddenResourcesHideOnCreation; + } + } + + /// + /// Verifies that KnowledgeBoxObj.Model is typed as SemanticModelMetadata (not object). + /// + /// Task. + [Fact] + [TestPriority(2)] + public async Task KnowledgeBoxObj_Model_IsTypedAsSemanticModelMetadata_NotObject() + { + // Arrange & Act + var result = await CreateHttpClient() + .KbKbKbidGetAsync(kbid: _knowledgeBoxId!, xNUCLIADBROLES: "READER"); + + var kb = result switch + { + OkKnowledgeBoxObjHTTPValidationError(var value) => value, + ErrorKnowledgeBoxObjHTTPValidationError( + HttpError.ExceptionError + (var ex) + ) => throw new InvalidOperationException("API call failed with exception", ex), + ErrorKnowledgeBoxObjHTTPValidationError( + HttpError.ErrorResponseError + (var body, var statusCode, _) + ) => throw new InvalidOperationException($"API call failed: HTTP {statusCode}: {body}"), + }; + + // Assert - These assertions will only compile if Model is SemanticModelMetadata (not object) + Assert.NotNull(kb); + + if (kb.Model is { } model) + { + // Access Model properties in a type-safe manner + var similarityFunction = model.SimilarityFunction; + var vectorDimension = model.VectorDimension; + + // These properties exist on SemanticModelMetadata but not on object + Assert.NotNull(similarityFunction); + Assert.NotEmpty(similarityFunction); + + // Vector dimension should be a positive integer if present + if (vectorDimension.HasValue) + { + Assert.True(vectorDimension.Value > 0); + } + } + } + + /// + /// Verifies we can access deeply nested properties in a type-safe manner. + /// This proves the entire type hierarchy is properly resolved. + /// + /// Task. + [Fact] + [TestPriority(3)] + public async Task KnowledgeBoxObj_AllowsDeepPropertyAccess_TypeSafely() + { + // Arrange & Act + var result = await CreateHttpClient() + .KbKbKbidGetAsync(kbid: _knowledgeBoxId!, xNUCLIADBROLES: "READER"); + + var kb = result switch + { + OkKnowledgeBoxObjHTTPValidationError(var value) => value, + ErrorKnowledgeBoxObjHTTPValidationError( + HttpError.ExceptionError + (var ex) + ) => throw new InvalidOperationException("API call failed with exception", ex), + ErrorKnowledgeBoxObjHTTPValidationError( + HttpError.ErrorResponseError + (var body, var statusCode, _) + ) => throw new InvalidOperationException($"API call failed: HTTP {statusCode}: {body}"), + }; + + // Assert - Access multiple levels of properties without casting + Assert.NotNull(kb); + Assert.NotNull(kb.Uuid); + Assert.NotNull(kb.Slug); + + // Access Config properties - the fact that we can do this without casting proves type safety + var configSlug = kb.Config?.Slug; + var configTitle = kb.Config?.Title; + + // The fact that we can access these properties without casting proves type safety + // If Config/Model were 'object', we'd need explicit casts + Assert.NotNull(configSlug); + Assert.NotNull(configTitle); + } + + /// + /// Verifies that we can use pattern matching with the properly typed properties. + /// + /// Task. + [Fact] + [TestPriority(4)] + public async Task KnowledgeBoxObj_SupportsPatternMatching_OnTypedProperties() + { + // Arrange & Act + var result = await CreateHttpClient() + .KbKbKbidGetAsync(kbid: _knowledgeBoxId!, xNUCLIADBROLES: "READER"); + + var kb = result switch + { + OkKnowledgeBoxObjHTTPValidationError(var value) => value, + ErrorKnowledgeBoxObjHTTPValidationError( + HttpError.ExceptionError + (var ex) + ) => throw new InvalidOperationException("API call failed with exception", ex), + ErrorKnowledgeBoxObjHTTPValidationError( + HttpError.ErrorResponseError + (var body, var statusCode, _) + ) => throw new InvalidOperationException($"API call failed: HTTP {statusCode}: {body}"), + }; + + // Assert - Use pattern matching on typed properties + Assert.NotNull(kb); + + // Pattern match on Config (only works if Config is KnowledgeBoxConfig, not object) + var configDescription = kb.Config switch + { + { Description: var desc } when !string.IsNullOrEmpty(desc) => desc, + { Description: _ } => "No description", + null => "Config not available", + }; + + Assert.NotNull(configDescription); + + // Pattern match on Model (only works if Model is SemanticModelMetadata, not object) + var modelDescription = kb.Model switch + { + { SimilarityFunction: var sf, VectorDimension: var vd } + when !string.IsNullOrEmpty(sf) => $"{sf} with dimension {vd}", + { SimilarityFunction: var sf } => sf, + null => "Model not available", + }; + + Assert.NotNull(modelDescription); + } + + /// + /// Verifies that type information is preserved across multiple API calls. + /// + /// Task. + [Fact] + [TestPriority(5)] + public async Task MultipleApiCalls_ReturnConsistentlyTypedObjects() + { + // First call + var result1 = await CreateHttpClient() + .KbKbKbidGetAsync(kbid: _knowledgeBoxId!, xNUCLIADBROLES: "READER"); + + var kb1 = result1 switch + { + OkKnowledgeBoxObjHTTPValidationError(var value) => value, + ErrorKnowledgeBoxObjHTTPValidationError( + HttpError.ExceptionError + (var ex) + ) => throw new InvalidOperationException("API call failed with exception", ex), + ErrorKnowledgeBoxObjHTTPValidationError( + HttpError.ErrorResponseError + (var body, var statusCode, _) + ) => throw new InvalidOperationException($"API call failed: HTTP {statusCode}: {body}"), + }; + + // Second call + var result2 = await CreateHttpClient() + .KbKbKbidGetAsync(kbid: _knowledgeBoxId!, xNUCLIADBROLES: "READER"); + + var kb2 = result2 switch + { + OkKnowledgeBoxObjHTTPValidationError(var value) => value, + ErrorKnowledgeBoxObjHTTPValidationError( + HttpError.ExceptionError + (var ex) + ) => throw new InvalidOperationException("API call failed with exception", ex), + ErrorKnowledgeBoxObjHTTPValidationError( + HttpError.ErrorResponseError + (var body, var statusCode, _) + ) => throw new InvalidOperationException($"API call failed: HTTP {statusCode}: {body}"), + }; + + // Assert - Both objects have properly typed Config and Model + Assert.NotNull(kb1); + Assert.NotNull(kb2); + + // Access Config from both - proves type consistency + var config1Slug = kb1.Config?.Slug; + var config2Slug = kb2.Config?.Slug; + + Assert.Equal(config1Slug, config2Slug); + + // Access Model from both - proves type consistency + var model1Func = kb1.Model?.SimilarityFunction; + var model2Func = kb2.Model?.SimilarityFunction; + + Assert.Equal(model1Func, model2Func); + } + + /// + /// Compile-time type verification test. + /// This method contains code that will ONLY compile if the types are correct. + /// If Config or Model were 'object', this would not compile without casts. + /// + [Fact] + [TestPriority(6)] + public void CompileTimeTypeVerification_ProvesBugIsFix() + { + // This is a compile-time test - if it compiles, the types are correct + + // Create a mock KnowledgeBoxObj + var config = new KnowledgeBoxConfig( + Slug: "test", + Title: "Test", + Description: "Test", + LearningConfiguration: null, + ExternalIndexProvider: null, + ConfiguredExternalIndexProvider: null, + Similarity: null, + HiddenResourcesEnabled: false, + HiddenResourcesHideOnCreation: false + ); + + var model = new SemanticModelMetadata( + SimilarityFunction: "cosine", + VectorDimension: 768, + DefaultMinScore: 0.7f + ); + + var kb = new KnowledgeBoxObj( + Slug: "test-kb", + Uuid: Guid.NewGuid().ToString(), + Config: config, + Model: model + ); + + // These assignments will ONLY compile if the types are correct + var configFromKb = kb.Config; // Would fail if Config were object + var modelFromKb = kb.Model; // Would fail if Model were object + + // Access properties without casting + var slug = configFromKb?.Slug; + var similarityFunction = modelFromKb?.SimilarityFunction; + var vectorDimension = modelFromKb?.VectorDimension; + + // Assert + Assert.NotNull(configFromKb); + Assert.NotNull(modelFromKb); + Assert.Equal("test", slug); + Assert.Equal("cosine", similarityFunction); + Assert.Equal(768, vectorDimension); + } +} From c4e73465d7dbe5763dde83acda4c8ce7cecf3ba8 Mon Sep 17 00:00:00 2001 From: Christian Findlay <16697547+MelbourneDeveloper@users.noreply.github.com> Date: Wed, 22 Oct 2025 21:26:39 +1100 Subject: [PATCH 4/4] format --- .../OpenApiCodeGeneratorTests.cs | 40 +++++++++++++++---- 1 file changed, 32 insertions(+), 8 deletions(-) diff --git a/RestClient.Net.OpenApiGenerator.Tests/OpenApiCodeGeneratorTests.cs b/RestClient.Net.OpenApiGenerator.Tests/OpenApiCodeGeneratorTests.cs index 6860d51e..c303d9d2 100644 --- a/RestClient.Net.OpenApiGenerator.Tests/OpenApiCodeGeneratorTests.cs +++ b/RestClient.Net.OpenApiGenerator.Tests/OpenApiCodeGeneratorTests.cs @@ -604,13 +604,31 @@ public void Generate_HandlesAnyOfSchemasInProperties() // Verify anyOf properties are correctly typed - THIS PROVES BUG #142 IS FIXED Assert.IsTrue(result.ModelsCode.Contains("public record KnowledgeBoxObj(")); - Assert.IsTrue(result.ModelsCode.Contains("string? Slug"), $"Expected 'string? Slug' but got: {result.ModelsCode}"); - Assert.IsTrue(result.ModelsCode.Contains("string Uuid"), $"Expected 'string Uuid' but got: {result.ModelsCode}"); - Assert.IsTrue(result.ModelsCode.Contains("KnowledgeBoxConfig? Config"), $"Expected 'KnowledgeBoxConfig? Config' but got: {result.ModelsCode}"); - Assert.IsTrue(result.ModelsCode.Contains("SemanticModelMetadata? Model"), $"Expected 'SemanticModelMetadata? Model' but got: {result.ModelsCode}"); + Assert.IsTrue( + result.ModelsCode.Contains("string? Slug"), + $"Expected 'string? Slug' but got: {result.ModelsCode}" + ); + Assert.IsTrue( + result.ModelsCode.Contains("string Uuid"), + $"Expected 'string Uuid' but got: {result.ModelsCode}" + ); + Assert.IsTrue( + result.ModelsCode.Contains("KnowledgeBoxConfig? Config"), + $"Expected 'KnowledgeBoxConfig? Config' but got: {result.ModelsCode}" + ); + Assert.IsTrue( + result.ModelsCode.Contains("SemanticModelMetadata? Model"), + $"Expected 'SemanticModelMetadata? Model' but got: {result.ModelsCode}" + ); Assert.IsFalse(result.ModelsCode.Contains("object Slug"), "Should not have 'object Slug'"); - Assert.IsFalse(result.ModelsCode.Contains("object Config"), "Should not have 'object Config'"); - Assert.IsFalse(result.ModelsCode.Contains("object Model"), "Should not have 'object Model'"); + Assert.IsFalse( + result.ModelsCode.Contains("object Config"), + "Should not have 'object Config'" + ); + Assert.IsFalse( + result.ModelsCode.Contains("object Model"), + "Should not have 'object Model'" + ); } [TestMethod] @@ -1707,8 +1725,14 @@ public void Generate_HandlesRequiredHeaderParameters() OpenApiCodeGenerator.Generate(spec, "TestApi", "TestApiExtensions", Path.GetTempPath()) ); - Assert.IsTrue(result.ExtensionMethodsCode.Contains("authorization"), "Should contain 'authorization'"); - Assert.IsTrue(result.ExtensionMethodsCode.Contains("xRequestID"), "Should contain 'xRequestID'"); + Assert.IsTrue( + result.ExtensionMethodsCode.Contains("authorization"), + "Should contain 'authorization'" + ); + Assert.IsTrue( + result.ExtensionMethodsCode.Contains("xRequestID"), + "Should contain 'xRequestID'" + ); } [TestMethod]