From 2e736f4a366d65518a17442a0a17dfb3fd6352c9 Mon Sep 17 00:00:00 2001 From: dpiet-oai <326640584+dpiet-oai@users.noreply.github.com> Date: Tue, 6 Oct 2026 20:51:33 +0000 Subject: [PATCH 1/2] feat(api): add standalone Decisions support Castiron-Internal-PR: https://github.com/openai/openai-java-internal/pull/221 Castiron-Source-SHA: f458c478469c6a691258d1e3edd25bcc69cbc87b Castiron-Public-Base-SHA: 7648554b5e6a250a233cc11e211f436b756ef03b --- .castiron.stats.yml | 14 +- api_reference/openapi.transformed.yml | 795 +- .../kotlin/com/openai/client/OpenAIClient.kt | 5 + .../com/openai/client/OpenAIClientAsync.kt | 5 + .../openai/client/OpenAIClientAsyncImpl.kt | 14 + .../com/openai/client/OpenAIClientImpl.kt | 14 + .../beta/responses/BetaResponseInjectEvent.kt | 2 +- .../BetaResponseInjectFailedEvent.kt | 2 +- .../BetaResponseToolSearchOutputItemParam.kt | 7498 ++++++++++++++++- .../BetaToolSearchOutputNamespaceTool.kt | 1383 +++ .../conversations/ConversationCreateParams.kt | 4 +- .../conversations/items/ItemCreateParams.kt | 4 +- .../com/openai/models/decisions/Decision.kt | 2984 +++++++ .../models/decisions/DecisionChoiceOption.kt | 442 + .../models/decisions/DecisionChoiceValue.kt | 226 + .../models/decisions/DecisionCreateParams.kt | 2308 +++++ .../models/decisions/DecisionInputImage.kt | 408 + .../models/decisions/DecisionInputMessage.kt | 613 ++ .../models/decisions/DecisionInputPart.kt | 232 + .../models/decisions/DecisionInputText.kt | 217 + .../models/live/ResponseItemCreateEvent.kt | 2 +- .../ResponseToolSearchOutputItemParam.kt | 7368 +++++++++++++++- .../ToolSearchOutputNamespaceTool.kt | 1381 +++ .../services/async/DecisionServiceAsync.kt | 75 + .../async/DecisionServiceAsyncImpl.kt | 91 + .../services/blocking/DecisionService.kt | 72 + .../services/blocking/DecisionServiceImpl.kt | 84 + ...taResponseToolSearchOutputItemParamTest.kt | 2 +- .../BetaToolSearchOutputNamespaceToolTest.kt | 100 + .../decisions/DecisionChoiceOptionTest.kt | 36 + .../decisions/DecisionChoiceValueTest.kt | 81 + .../decisions/DecisionCreateParamsTest.kt | 78 + .../decisions/DecisionInputImageTest.kt | 41 + .../decisions/DecisionInputMessageTest.kt | 42 + .../models/decisions/DecisionInputPartTest.kt | 93 + .../models/decisions/DecisionInputTextTest.kt | 32 + .../openai/models/decisions/DecisionTest.kt | 105 + .../ResponseToolSearchOutputItemParamTest.kt | 2 +- .../ToolSearchOutputNamespaceToolTest.kt | 100 + .../async/DecisionServiceAsyncTest.kt | 42 + .../services/blocking/DecisionServiceTest.kt | 41 + 41 files changed, 26958 insertions(+), 80 deletions(-) create mode 100644 openai-java-core/src/main/kotlin/com/openai/models/beta/responses/BetaToolSearchOutputNamespaceTool.kt create mode 100644 openai-java-core/src/main/kotlin/com/openai/models/decisions/Decision.kt create mode 100644 openai-java-core/src/main/kotlin/com/openai/models/decisions/DecisionChoiceOption.kt create mode 100644 openai-java-core/src/main/kotlin/com/openai/models/decisions/DecisionChoiceValue.kt create mode 100644 openai-java-core/src/main/kotlin/com/openai/models/decisions/DecisionCreateParams.kt create mode 100644 openai-java-core/src/main/kotlin/com/openai/models/decisions/DecisionInputImage.kt create mode 100644 openai-java-core/src/main/kotlin/com/openai/models/decisions/DecisionInputMessage.kt create mode 100644 openai-java-core/src/main/kotlin/com/openai/models/decisions/DecisionInputPart.kt create mode 100644 openai-java-core/src/main/kotlin/com/openai/models/decisions/DecisionInputText.kt create mode 100644 openai-java-core/src/main/kotlin/com/openai/models/responses/ToolSearchOutputNamespaceTool.kt create mode 100644 openai-java-core/src/main/kotlin/com/openai/services/async/DecisionServiceAsync.kt create mode 100644 openai-java-core/src/main/kotlin/com/openai/services/async/DecisionServiceAsyncImpl.kt create mode 100644 openai-java-core/src/main/kotlin/com/openai/services/blocking/DecisionService.kt create mode 100644 openai-java-core/src/main/kotlin/com/openai/services/blocking/DecisionServiceImpl.kt create mode 100644 openai-java-core/src/test/kotlin/com/openai/models/beta/responses/BetaToolSearchOutputNamespaceToolTest.kt create mode 100644 openai-java-core/src/test/kotlin/com/openai/models/decisions/DecisionChoiceOptionTest.kt create mode 100644 openai-java-core/src/test/kotlin/com/openai/models/decisions/DecisionChoiceValueTest.kt create mode 100644 openai-java-core/src/test/kotlin/com/openai/models/decisions/DecisionCreateParamsTest.kt create mode 100644 openai-java-core/src/test/kotlin/com/openai/models/decisions/DecisionInputImageTest.kt create mode 100644 openai-java-core/src/test/kotlin/com/openai/models/decisions/DecisionInputMessageTest.kt create mode 100644 openai-java-core/src/test/kotlin/com/openai/models/decisions/DecisionInputPartTest.kt create mode 100644 openai-java-core/src/test/kotlin/com/openai/models/decisions/DecisionInputTextTest.kt create mode 100644 openai-java-core/src/test/kotlin/com/openai/models/decisions/DecisionTest.kt create mode 100644 openai-java-core/src/test/kotlin/com/openai/models/responses/ToolSearchOutputNamespaceToolTest.kt create mode 100644 openai-java-core/src/test/kotlin/com/openai/services/async/DecisionServiceAsyncTest.kt create mode 100644 openai-java-core/src/test/kotlin/com/openai/services/blocking/DecisionServiceTest.kt diff --git a/.castiron.stats.yml b/.castiron.stats.yml index 3aed9677d..f3cdfea8d 100644 --- a/.castiron.stats.yml +++ b/.castiron.stats.yml @@ -1,8 +1,8 @@ schema_version: 1 -generation_id: b5e92b57-640d-4fdf-b97b-b5e824207bf5 -openapi_spec_hash: 0824fadcd64901a2a03bb44fd10bfa80 -openapi_transformed_spec_hash: 794495a7295d5744dbec1d4557949fcd -config_hash: 10ea2c74c82b64939d70ba94d3ed6f57 -codegen_sha: bdad42acfefe450652583d12afe24bf6f44d83bc -codegen_hash: 234c93f7f62b5b847336b7ad8fbe7cf7e5df4d9fffff6acc00abb0bb23e20ed9 -public_codegen_sha: c834768776c04fcd3c11594e9d9be6ae95572fee +generation_id: fd87a332-8b41-4969-82ea-bee78e04c9b0 +openapi_spec_hash: f0ac7c2da11e51bf51fe8f65e5b313b9 +openapi_transformed_spec_hash: 90042e27fae59af49799aee80b3882b0 +config_hash: 3336a08a5a6cf26a723db96a2602e503 +codegen_sha: c76b241333d2b0ecd43eb9f8a4bc308fea1defa1 +codegen_hash: 12b19e5d66cb42739f0d86618cd872d65c9067cfcf395cef3c9fbf2bfd359de1 +public_codegen_sha: 4dd493cf89ad33dd52f93d8e2485f8ed7a4fdede diff --git a/api_reference/openapi.transformed.yml b/api_reference/openapi.transformed.yml index 919d449ba..71612527b 100644 --- a/api_reference/openapi.transformed.yml +++ b/api_reference/openapi.transformed.yml @@ -30099,6 +30099,64 @@ paths: "first_id": "cthr_abc123", "last_id": "cthr_def456" } + /decisions: + post: + operationId: createDecision + summary: Create a decision + description: |- + Evaluate ordered classification and scoring questions against shared input. Answers are returned in question order. + + Supply input as a string or user messages containing text and inline images. Only user messages with `input_text` and `input_image` parts are supported; non-user roles, function calls, files, audio, and item references are not supported. Images require a data URL, not an external URL or file ID. At most 128 images are allowed across the request. + + Each question can return a refusal instead of a scored answer. A refusal has type `refusal` and the corresponding question name, or null if unnamed. + tags: + - Decisions + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/DecisionRequest' + required: true + responses: + '200': + description: The answers and token usage. + content: + application/json: + schema: + $ref: '#/components/schemas/DecisionResponse' + x-oaiMeta: + group: decisions + examples: + request: + curl: | + curl https://api.openai.com/v1/decisions \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer $OPENAI_API_KEY" \ + -d '{ + "model": "gpt-6-luna", + "input": "The package arrived with a broken screen.", + "questions": [ + { + "type": "predicate", + "name": "damaged", + "instructions": "Does the customer report a damaged item?" + } + ] + }' + response: | + { + "model": "gpt-6-luna", + "answers": [ + {"type": "predicate", "name": "damaged", "probability": 0.95} + ], + "usage": { + "input_tokens": 42, + "input_tokens_details": {"cached_tokens": 0, "cache_write_tokens": 0}, + "output_tokens": 0, + "output_tokens_details": {"reasoning_tokens": 0}, + "total_tokens": 42 + } + } /agents/environments/{environment_id}: get: operationId: retrieveAgentEnvironment @@ -68691,6 +68749,28 @@ components: - code_interpreter required: - type + ToolSearchOutputTool: + description: | + A tool definition returned by a tool search output. + discriminator: + propertyName: type + anyOf: + - $ref: '#/components/schemas/FunctionTool' + - $ref: '#/components/schemas/FileSearchTool' + - $ref: '#/components/schemas/ComputerTool' + - $ref: '#/components/schemas/ComputerUsePreviewTool' + - $ref: '#/components/schemas/WebSearchTool' + - $ref: '#/components/schemas/MCPTool' + - $ref: '#/components/schemas/CodeInterpreterTool' + - $ref: '#/components/schemas/ProgrammaticToolCallingParam' + - $ref: '#/components/schemas/ImageGenTool' + - $ref: '#/components/schemas/LocalShellToolParam' + - $ref: '#/components/schemas/FunctionShellToolParam' + - $ref: '#/components/schemas/CustomToolParam' + - $ref: '#/components/schemas/ToolSearchOutputNamespaceToolParam' + - $ref: '#/components/schemas/ToolSearchToolParam' + - $ref: '#/components/schemas/WebSearchPreviewTool' + - $ref: '#/components/schemas/ApplyPatchToolParam' ToolsArray: type: array description: | @@ -75584,6 +75664,94 @@ components: required: - type - arguments + ToolSearchOutputFunctionToolParam: + properties: + name: + type: string + maxLength: 128 + minLength: 1 + pattern: ^(?![\s\S]*[\r\n])[a-zA-Z0-9_.-]+$ + description: The name of the loaded function tool. + description: + anyOf: + - type: string + - type: 'null' + parameters: + anyOf: + - $ref: '#/components/schemas/EmptyModelParam' + - type: 'null' + strict: + anyOf: + - type: boolean + description: Whether to enforce strict parameter validation. If omitted, Responses attempts to use strict validation when the schema is compatible, and falls back to non-strict validation otherwise. + - type: 'null' + type: + type: string + enum: + - function + default: function + x-stainless-const: true + async: + type: boolean + description: Whether the tool response can be returned asynchronously versus immediately returned on next response creation. + output_schema: + anyOf: + - additionalProperties: {} + type: object + description: A JSON Schema describing the JSON value encoded in string outputs for this function tool. This does not describe content-array outputs. + x-oaiTypeLabel: map + - type: 'null' + defer_loading: + type: boolean + description: Whether this function should be deferred and discovered via tool search. + allowed_callers: + anyOf: + - items: + $ref: '#/components/schemas/CallableToolAllowedCaller' + type: array + minItems: 1 + description: The tool invocation context(s). + - type: 'null' + type: object + required: + - name + - type + x-openai-structured-output: function + ToolSearchOutputNamespaceToolParam: + properties: + type: + type: string + enum: + - namespace + description: The type of the tool. Always `namespace`. + default: namespace + x-stainless-const: true + name: + type: string + minLength: 1 + description: The namespace name used in tool calls (for example, `crm`). + description: + type: string + description: A description of the namespace shown to the model. + tools: + items: + discriminator: + propertyName: type + description: A function or custom tool loaded into a namespace by tool search. + anyOf: + - $ref: '#/components/schemas/ToolSearchOutputFunctionToolParam' + - $ref: '#/components/schemas/CustomToolParam' + type: array + minItems: 1 + description: The function/custom tools loaded inside this namespace. + type: object + required: + - type + - name + - description + - tools + title: Namespace + description: Groups function/custom tools under a shared namespace. ToolSearchOutputItemParam: properties: id: @@ -75611,7 +75779,7 @@ components: description: Whether tool search was executed by the server or by the client. tools: items: - $ref: '#/components/schemas/Tool' + $ref: '#/components/schemas/ToolSearchOutputTool' type: array description: The loaded tool definitions returned by the tool search output. status: @@ -80276,6 +80444,511 @@ components: - has_more title: Threads description: A paginated list of ChatKit threads. + DecisionInputText: + type: object + properties: + type: + type: string + enum: + - input_text + default: input_text + x-stainless-const: true + text: + type: string + minLength: 0 + maxLength: 10485760 + required: + - type + - text + additionalProperties: false + ImageDetailParam: + type: string + enum: + - low + - high + - auto + - original + DecisionInputImage: + type: object + properties: + image_url: + type: string + minLength: 0 + maxLength: 1073741824 + pattern: '^data:' + description: A base64-encoded image in a data URL. + detail: + anyOf: + - $ref: '#/components/schemas/ImageDetailParam' + - type: 'null' + description: The image detail level, using the selected model's image profile. Defaults to auto. + default: auto + type: + type: string + enum: + - input_image + default: input_image + x-stainless-const: true + required: + - image_url + - type + additionalProperties: false + description: An inline image. External URLs and file IDs are not supported. + DecisionInputContentParts: + type: array + items: + x-oai-discriminator-values: + - input_text + - input_image + discriminator: + propertyName: type + mapping: + input_text: '#/components/schemas/DecisionInputText' + input_image: '#/components/schemas/DecisionInputImage' + anyOf: + - $ref: '#/components/schemas/DecisionInputText' + - $ref: '#/components/schemas/DecisionInputImage' + minItems: 0 + maxItems: 16384 + DecisionInputContent: + description: Text evidence or an ordered list of text and inline image parts. + anyOf: + - type: string + minLength: 0 + maxLength: 10485760 + - $ref: '#/components/schemas/DecisionInputContentParts' + title: Parts + DecisionInputMessage: + type: object + properties: + role: + type: string + enum: + - user + default: user + x-stainless-const: true + content: + $ref: '#/components/schemas/DecisionInputContent' + type: + type: string + enum: + - message + default: message + x-stainless-const: true + required: + - role + - content + additionalProperties: false + description: A user message containing text or inline images. + DecisionInput: + description: Shared evidence, as a string or an array of user messages containing text and inline images. Non-user roles, function calls, function-call outputs, files, audio, and item references are not supported. At most 128 image parts are allowed across all messages in one request. + anyOf: + - type: string + minLength: 0 + maxLength: 10485760 + - type: array + items: + x-oai-default-discriminator-value: message + discriminator: + propertyName: type + mapping: + message: '#/components/schemas/DecisionInputMessage' + x-oai-discriminator-values: + - message + anyOf: + - $ref: '#/components/schemas/DecisionInputMessage' + minItems: 0 + maxItems: 131072 + QuestionParamPredicate: + type: object + properties: + type: + type: string + enum: + - predicate + default: predicate + x-stainless-const: true + description: The type of the object. Always `predicate`. + name: + type: string + minLength: 0 + maxLength: 1048576 + instructions: + type: string + minLength: 0 + maxLength: 1048576 + required: + - type + - instructions + additionalProperties: false + ChoiceValueParam: + description: 'Choice values are typed: a string and a boolean with the same text are distinct.' + anyOf: + - type: string + minLength: 0 + maxLength: 1048576 + - type: boolean + ChoiceOptionParam: + type: object + properties: + value: + $ref: '#/components/schemas/ChoiceValueParam' + description: + type: string + minLength: 0 + maxLength: 1048576 + required: + - value + additionalProperties: false + QuestionParamChoice: + type: object + properties: + type: + type: string + enum: + - choice + default: choice + x-stainless-const: true + description: The type of the object. Always `choice`. + name: + type: string + minLength: 0 + maxLength: 1048576 + instructions: + type: string + minLength: 0 + maxLength: 1048576 + choices: + type: array + items: + $ref: '#/components/schemas/ChoiceOptionParam' + minItems: 2 + maxItems: 255 + required: + - type + - instructions + - choices + additionalProperties: false + ScoreLevelParam: + type: object + properties: + label: + type: string + minLength: 0 + maxLength: 1048576 + description: + type: string + minLength: 0 + maxLength: 1048576 + required: + - label + additionalProperties: false + QuestionParamScore: + type: object + properties: + type: + type: string + enum: + - score + default: score + x-stainless-const: true + description: The type of the object. Always `score`. + name: + type: string + minLength: 0 + maxLength: 1048576 + instructions: + type: string + minLength: 0 + maxLength: 1048576 + levels: + type: array + items: + $ref: '#/components/schemas/ScoreLevelParam' + minItems: 2 + maxItems: 10 + required: + - type + - instructions + - levels + additionalProperties: false + QuestionParam: + description: A question about the request's input, with an optional correlation name. + discriminator: + propertyName: type + mapping: + predicate: '#/components/schemas/QuestionParamPredicate' + choice: '#/components/schemas/QuestionParamChoice' + score: '#/components/schemas/QuestionParamScore' + x-oai-discriminator-values: + - predicate + - choice + - score + anyOf: + - $ref: '#/components/schemas/QuestionParamPredicate' + - $ref: '#/components/schemas/QuestionParamChoice' + - $ref: '#/components/schemas/QuestionParamScore' + DecisionRequest: + type: object + properties: + model: + type: string + minLength: 0 + maxLength: 1048576 + input: + $ref: '#/components/schemas/DecisionInput' + questions: + type: array + items: + $ref: '#/components/schemas/QuestionParam' + minItems: 1 + maxItems: 200 + safety_identifier: + type: + - string + - 'null' + minLength: 0 + maxLength: 128 + description: Opaque caller-provided end-user identifier, scoped by the verified org. Match Responses' limit; this is never the authenticated user identity. + required: + - model + - input + - questions + additionalProperties: false + AnswerResourcePredicate: + type: object + properties: + type: + type: string + enum: + - predicate + default: predicate + x-stainless-const: true + description: The type of the object. Always `predicate`. + name: + type: + - string + - 'null' + minLength: 0 + probability: + type: number + required: + - type + - name + - probability + additionalProperties: false + ChoiceValueResource: + description: 'Choice values are typed: a string and a boolean with the same text are distinct.' + anyOf: + - type: string + minLength: 0 + - type: boolean + ChoiceProbabilityResource: + type: object + properties: + value: + $ref: '#/components/schemas/ChoiceValueResource' + probability: + type: number + required: + - value + - probability + additionalProperties: false + AnswerResourceChoice: + type: object + properties: + type: + type: string + enum: + - choice + default: choice + x-stainless-const: true + description: The type of the object. Always `choice`. + name: + type: + - string + - 'null' + minLength: 0 + choice: + $ref: '#/components/schemas/ChoiceValueResource' + probabilities: + type: array + items: + $ref: '#/components/schemas/ChoiceProbabilityResource' + minItems: 0 + maxItems: 2000 + confidence: + type: number + required: + - type + - name + - choice + - probabilities + - confidence + additionalProperties: false + ScoreProbabilityResource: + type: object + properties: + value: + type: integer + format: int64 + label: + type: string + minLength: 0 + probability: + type: number + required: + - value + - label + - probability + additionalProperties: false + AnswerResourceScore: + type: object + properties: + type: + type: string + enum: + - score + default: score + x-stainless-const: true + description: The type of the object. Always `score`. + name: + type: + - string + - 'null' + minLength: 0 + score: + type: number + probabilities: + type: array + items: + $ref: '#/components/schemas/ScoreProbabilityResource' + minItems: 0 + maxItems: 2000 + confidence: + type: number + required: + - type + - name + - score + - probabilities + - confidence + additionalProperties: false + AnswerResourceRefusal: + type: object + properties: + type: + type: string + enum: + - refusal + default: refusal + x-stainless-const: true + description: The type of the object. Always `refusal`. + name: + type: + - string + - 'null' + minLength: 0 + required: + - type + - name + additionalProperties: false + description: The host may decline one question without disclosing its refusal score. + AnswerResource: + description: A completed question always includes its name, including null when unnamed. + discriminator: + propertyName: type + mapping: + predicate: '#/components/schemas/AnswerResourcePredicate' + choice: '#/components/schemas/AnswerResourceChoice' + score: '#/components/schemas/AnswerResourceScore' + refusal: '#/components/schemas/AnswerResourceRefusal' + x-oai-discriminator-values: + - predicate + - choice + - score + - refusal + anyOf: + - $ref: '#/components/schemas/AnswerResourcePredicate' + - $ref: '#/components/schemas/AnswerResourceChoice' + - $ref: '#/components/schemas/AnswerResourceScore' + - $ref: '#/components/schemas/AnswerResourceRefusal' + InputTokensDetailsResource: + type: object + properties: + cached_tokens: + type: integer + format: int64 + minimum: -2147483648 + maximum: 2147483647 + cache_write_tokens: + type: integer + format: int64 + minimum: -2147483648 + maximum: 2147483647 + required: + - cached_tokens + - cache_write_tokens + additionalProperties: false + OutputTokensDetailsResource: + type: object + properties: + reasoning_tokens: + type: integer + format: int64 + minimum: -2147483648 + maximum: 2147483647 + required: + - reasoning_tokens + additionalProperties: false + ResponseUsageResource: + type: object + properties: + input_tokens: + type: integer + format: int64 + minimum: -2147483648 + maximum: 2147483647 + input_tokens_details: + $ref: '#/components/schemas/InputTokensDetailsResource' + output_tokens: + type: integer + format: int64 + minimum: -2147483648 + maximum: 2147483647 + output_tokens_details: + $ref: '#/components/schemas/OutputTokensDetailsResource' + total_tokens: + type: integer + format: int64 + minimum: -2147483648 + maximum: 2147483647 + required: + - input_tokens + - input_tokens_details + - output_tokens + - output_tokens_details + - total_tokens + additionalProperties: false + DecisionResponse: + type: object + properties: + model: + type: string + minLength: 0 + answers: + type: array + items: + $ref: '#/components/schemas/AnswerResource' + minItems: 0 + maxItems: 2000 + usage: + $ref: '#/components/schemas/ResponseUsageResource' + required: + - model + - answers + - usage + additionalProperties: false EnvironmentTypeResource: type: string enum: @@ -82240,7 +82913,7 @@ components: - message additionalProperties: false description: A customer-safe error describing why a session request failed. - InputTokensDetailsResource: + InputTokensDetailsResource-2: type: object properties: cached_tokens: @@ -82251,7 +82924,7 @@ components: - cached_tokens additionalProperties: false description: A breakdown of input token usage for a session or turn. - OutputTokensDetailsResource: + OutputTokensDetailsResource-2: type: object properties: reasoning_tokens: @@ -82270,14 +82943,14 @@ components: format: int64 description: The number of input tokens used by the agent. input_tokens_details: - $ref: '#/components/schemas/InputTokensDetailsResource' + $ref: '#/components/schemas/InputTokensDetailsResource-2' description: A breakdown of the agent's input token usage. output_tokens: type: integer format: int64 description: The number of output tokens generated by the agent. output_tokens_details: - $ref: '#/components/schemas/OutputTokensDetailsResource' + $ref: '#/components/schemas/OutputTokensDetailsResource-2' description: A breakdown of the agent's output token usage. total_tokens: type: integer @@ -94686,7 +95359,7 @@ components: description: Whether tool search was executed by the server or by the client. tools: items: - $ref: '#/components/schemas/BetaTool' + $ref: '#/components/schemas/BetaToolSearchOutputTool' type: array description: The loaded tool definitions returned by the tool search output. status: @@ -94704,6 +95377,116 @@ components: - in_progress - completed - incomplete + BetaToolSearchOutputTool: + description: | + A tool definition returned by a tool search output. + discriminator: + propertyName: type + anyOf: + - $ref: '#/components/schemas/BetaFunctionTool' + - $ref: '#/components/schemas/BetaFileSearchTool' + - $ref: '#/components/schemas/BetaComputerTool' + - $ref: '#/components/schemas/BetaComputerUsePreviewTool' + - $ref: '#/components/schemas/BetaWebSearchTool' + - $ref: '#/components/schemas/BetaMCPTool' + - $ref: '#/components/schemas/BetaCodeInterpreterTool' + - $ref: '#/components/schemas/BetaProgrammaticToolCallingParam' + - $ref: '#/components/schemas/BetaImageGenTool' + - $ref: '#/components/schemas/BetaLocalShellToolParam' + - $ref: '#/components/schemas/BetaFunctionShellToolParam' + - $ref: '#/components/schemas/BetaCustomToolParam' + - $ref: '#/components/schemas/BetaToolSearchOutputNamespaceToolParam' + - $ref: '#/components/schemas/BetaToolSearchToolParam' + - $ref: '#/components/schemas/BetaWebSearchPreviewTool' + - $ref: '#/components/schemas/BetaApplyPatchToolParam' + BetaToolSearchOutputNamespaceToolParam: + properties: + type: + type: string + enum: + - namespace + description: The type of the tool. Always `namespace`. + default: namespace + x-stainless-const: true + name: + type: string + minLength: 1 + description: The namespace name used in tool calls (for example, `crm`). + description: + type: string + description: A description of the namespace shown to the model. + tools: + items: + discriminator: + propertyName: type + description: A function or custom tool loaded into a namespace by tool search. + anyOf: + - $ref: '#/components/schemas/BetaToolSearchOutputFunctionToolParam' + - $ref: '#/components/schemas/BetaCustomToolParam' + type: array + minItems: 1 + description: The function/custom tools loaded inside this namespace. + type: object + required: + - type + - name + - description + - tools + title: Namespace + description: Groups function/custom tools under a shared namespace. + BetaToolSearchOutputFunctionToolParam: + properties: + name: + type: string + maxLength: 128 + minLength: 1 + pattern: ^(?![\s\S]*[\r\n])[a-zA-Z0-9_.-]+$ + description: The name of the loaded function tool. + description: + anyOf: + - type: string + - type: 'null' + parameters: + anyOf: + - $ref: '#/components/schemas/BetaEmptyModelParam' + - type: 'null' + strict: + anyOf: + - type: boolean + description: Whether to enforce strict parameter validation. If omitted, Responses attempts to use strict validation when the schema is compatible, and falls back to non-strict validation otherwise. + - type: 'null' + type: + type: string + enum: + - function + default: function + x-stainless-const: true + async: + type: boolean + description: Whether the tool response can be returned asynchronously versus immediately returned on next response creation. + output_schema: + anyOf: + - additionalProperties: {} + type: object + description: A JSON Schema describing the JSON value encoded in string outputs for this function tool. This does not describe content-array outputs. + x-oaiTypeLabel: map + - type: 'null' + defer_loading: + type: boolean + description: Whether this function should be deferred and discovered via tool search. + allowed_callers: + anyOf: + - items: + $ref: '#/components/schemas/BetaCallableToolAllowedCaller' + type: array + minItems: 1 + description: The tool invocation context(s). + - type: 'null' + type: object + required: + - name + - type + x-openai-structured-output: function BetaToolSearchCallItemParam: properties: agent: diff --git a/openai-java-core/src/main/kotlin/com/openai/client/OpenAIClient.kt b/openai-java-core/src/main/kotlin/com/openai/client/OpenAIClient.kt index 4d12a0057..970b6e048 100644 --- a/openai-java-core/src/main/kotlin/com/openai/client/OpenAIClient.kt +++ b/openai-java-core/src/main/kotlin/com/openai/client/OpenAIClient.kt @@ -12,6 +12,7 @@ import com.openai.services.blocking.CompletionService import com.openai.services.blocking.ContainerService import com.openai.services.blocking.ContentProvenanceCheckService import com.openai.services.blocking.ConversationService +import com.openai.services.blocking.DecisionService import com.openai.services.blocking.EmbeddingService import com.openai.services.blocking.EvalService import com.openai.services.blocking.FileService @@ -68,6 +69,8 @@ interface OpenAIClient { */ fun withOptions(modifier: Consumer): OpenAIClient + fun decisions(): DecisionService + /** * Given a prompt, the model will return one or more predicted completions, and can also return * the probabilities of alternative tokens at each position. @@ -163,6 +166,8 @@ interface OpenAIClient { */ fun withOptions(modifier: Consumer): OpenAIClient.WithRawResponse + fun decisions(): DecisionService.WithRawResponse + /** * Given a prompt, the model will return one or more predicted completions, and can also * return the probabilities of alternative tokens at each position. diff --git a/openai-java-core/src/main/kotlin/com/openai/client/OpenAIClientAsync.kt b/openai-java-core/src/main/kotlin/com/openai/client/OpenAIClientAsync.kt index c2d3fc140..40c991dbb 100644 --- a/openai-java-core/src/main/kotlin/com/openai/client/OpenAIClientAsync.kt +++ b/openai-java-core/src/main/kotlin/com/openai/client/OpenAIClientAsync.kt @@ -12,6 +12,7 @@ import com.openai.services.async.CompletionServiceAsync import com.openai.services.async.ContainerServiceAsync import com.openai.services.async.ContentProvenanceCheckServiceAsync import com.openai.services.async.ConversationServiceAsync +import com.openai.services.async.DecisionServiceAsync import com.openai.services.async.EmbeddingServiceAsync import com.openai.services.async.EvalServiceAsync import com.openai.services.async.FileServiceAsync @@ -68,6 +69,8 @@ interface OpenAIClientAsync { */ fun withOptions(modifier: Consumer): OpenAIClientAsync + fun decisions(): DecisionServiceAsync + /** * Given a prompt, the model will return one or more predicted completions, and can also return * the probabilities of alternative tokens at each position. @@ -165,6 +168,8 @@ interface OpenAIClientAsync { modifier: Consumer ): OpenAIClientAsync.WithRawResponse + fun decisions(): DecisionServiceAsync.WithRawResponse + /** * Given a prompt, the model will return one or more predicted completions, and can also * return the probabilities of alternative tokens at each position. diff --git a/openai-java-core/src/main/kotlin/com/openai/client/OpenAIClientAsyncImpl.kt b/openai-java-core/src/main/kotlin/com/openai/client/OpenAIClientAsyncImpl.kt index c11db1051..f20035474 100644 --- a/openai-java-core/src/main/kotlin/com/openai/client/OpenAIClientAsyncImpl.kt +++ b/openai-java-core/src/main/kotlin/com/openai/client/OpenAIClientAsyncImpl.kt @@ -22,6 +22,8 @@ import com.openai.services.async.ContentProvenanceCheckServiceAsync import com.openai.services.async.ContentProvenanceCheckServiceAsyncImpl import com.openai.services.async.ConversationServiceAsync import com.openai.services.async.ConversationServiceAsyncImpl +import com.openai.services.async.DecisionServiceAsync +import com.openai.services.async.DecisionServiceAsyncImpl import com.openai.services.async.EmbeddingServiceAsync import com.openai.services.async.EmbeddingServiceAsyncImpl import com.openai.services.async.EvalServiceAsync @@ -75,6 +77,10 @@ class OpenAIClientAsyncImpl(private val clientOptions: ClientOptions) : OpenAICl WithRawResponseImpl(clientOptions) } + private val decisions: DecisionServiceAsync by lazy { + DecisionServiceAsyncImpl(clientOptionsWithUserAgent) + } + private val completions: CompletionServiceAsync by lazy { CompletionServiceAsyncImpl(clientOptionsWithUserAgent) } @@ -176,6 +182,8 @@ class OpenAIClientAsyncImpl(private val clientOptions: ClientOptions) : OpenAICl override fun withOptions(modifier: Consumer): OpenAIClientAsync = OpenAIClientAsyncImpl(clientOptions.toBuilder().apply(modifier::accept).build()) + override fun decisions(): DecisionServiceAsync = decisions + /** * Given a prompt, the model will return one or more predicted completions, and can also return * the probabilities of alternative tokens at each position. @@ -254,6 +262,10 @@ class OpenAIClientAsyncImpl(private val clientOptions: ClientOptions) : OpenAICl class WithRawResponseImpl internal constructor(private val clientOptions: ClientOptions) : OpenAIClientAsync.WithRawResponse { + private val decisions: DecisionServiceAsync.WithRawResponse by lazy { + DecisionServiceAsyncImpl.WithRawResponseImpl(clientOptions) + } + private val completions: CompletionServiceAsync.WithRawResponse by lazy { CompletionServiceAsyncImpl.WithRawResponseImpl(clientOptions) } @@ -366,6 +378,8 @@ class OpenAIClientAsyncImpl(private val clientOptions: ClientOptions) : OpenAICl clientOptions.toBuilder().apply(modifier::accept).build() ) + override fun decisions(): DecisionServiceAsync.WithRawResponse = decisions + /** * Given a prompt, the model will return one or more predicted completions, and can also * return the probabilities of alternative tokens at each position. diff --git a/openai-java-core/src/main/kotlin/com/openai/client/OpenAIClientImpl.kt b/openai-java-core/src/main/kotlin/com/openai/client/OpenAIClientImpl.kt index 6fad0a56a..6b0c72f6d 100644 --- a/openai-java-core/src/main/kotlin/com/openai/client/OpenAIClientImpl.kt +++ b/openai-java-core/src/main/kotlin/com/openai/client/OpenAIClientImpl.kt @@ -22,6 +22,8 @@ import com.openai.services.blocking.ContentProvenanceCheckService import com.openai.services.blocking.ContentProvenanceCheckServiceImpl import com.openai.services.blocking.ConversationService import com.openai.services.blocking.ConversationServiceImpl +import com.openai.services.blocking.DecisionService +import com.openai.services.blocking.DecisionServiceImpl import com.openai.services.blocking.EmbeddingService import com.openai.services.blocking.EmbeddingServiceImpl import com.openai.services.blocking.EvalService @@ -75,6 +77,10 @@ class OpenAIClientImpl(private val clientOptions: ClientOptions) : OpenAIClient WithRawResponseImpl(clientOptions) } + private val decisions: DecisionService by lazy { + DecisionServiceImpl(clientOptionsWithUserAgent) + } + private val completions: CompletionService by lazy { CompletionServiceImpl(clientOptionsWithUserAgent) } @@ -154,6 +160,8 @@ class OpenAIClientImpl(private val clientOptions: ClientOptions) : OpenAIClient override fun withOptions(modifier: Consumer): OpenAIClient = OpenAIClientImpl(clientOptions.toBuilder().apply(modifier::accept).build()) + override fun decisions(): DecisionService = decisions + /** * Given a prompt, the model will return one or more predicted completions, and can also return * the probabilities of alternative tokens at each position. @@ -231,6 +239,10 @@ class OpenAIClientImpl(private val clientOptions: ClientOptions) : OpenAIClient class WithRawResponseImpl internal constructor(private val clientOptions: ClientOptions) : OpenAIClient.WithRawResponse { + private val decisions: DecisionService.WithRawResponse by lazy { + DecisionServiceImpl.WithRawResponseImpl(clientOptions) + } + private val completions: CompletionService.WithRawResponse by lazy { CompletionServiceImpl.WithRawResponseImpl(clientOptions) } @@ -342,6 +354,8 @@ class OpenAIClientImpl(private val clientOptions: ClientOptions) : OpenAIClient clientOptions.toBuilder().apply(modifier::accept).build() ) + override fun decisions(): DecisionService.WithRawResponse = decisions + /** * Given a prompt, the model will return one or more predicted completions, and can also * return the probabilities of alternative tokens at each position. diff --git a/openai-java-core/src/main/kotlin/com/openai/models/beta/responses/BetaResponseInjectEvent.kt b/openai-java-core/src/main/kotlin/com/openai/models/beta/responses/BetaResponseInjectEvent.kt index 5444da48c..9bf1eec58 100644 --- a/openai-java-core/src/main/kotlin/com/openai/models/beta/responses/BetaResponseInjectEvent.kt +++ b/openai-java-core/src/main/kotlin/com/openai/models/beta/responses/BetaResponseInjectEvent.kt @@ -300,7 +300,7 @@ private constructor( * .build() * ``` */ - fun addToolSearchOutputInput(tools: List) = + fun addToolSearchOutputInput(tools: List) = addInput(BetaResponseToolSearchOutputItemParam.builder().tools(tools).build()) /** diff --git a/openai-java-core/src/main/kotlin/com/openai/models/beta/responses/BetaResponseInjectFailedEvent.kt b/openai-java-core/src/main/kotlin/com/openai/models/beta/responses/BetaResponseInjectFailedEvent.kt index 659ac23b5..d9f727bf0 100644 --- a/openai-java-core/src/main/kotlin/com/openai/models/beta/responses/BetaResponseInjectFailedEvent.kt +++ b/openai-java-core/src/main/kotlin/com/openai/models/beta/responses/BetaResponseInjectFailedEvent.kt @@ -377,7 +377,7 @@ private constructor( * .build() * ``` */ - fun addToolSearchOutputInput(tools: List) = + fun addToolSearchOutputInput(tools: List) = addInput(BetaResponseToolSearchOutputItemParam.builder().tools(tools).build()) /** diff --git a/openai-java-core/src/main/kotlin/com/openai/models/beta/responses/BetaResponseToolSearchOutputItemParam.kt b/openai-java-core/src/main/kotlin/com/openai/models/beta/responses/BetaResponseToolSearchOutputItemParam.kt index 0241cd2b4..748e3f82e 100644 --- a/openai-java-core/src/main/kotlin/com/openai/models/beta/responses/BetaResponseToolSearchOutputItemParam.kt +++ b/openai-java-core/src/main/kotlin/com/openai/models/beta/responses/BetaResponseToolSearchOutputItemParam.kt @@ -6,13 +6,24 @@ import com.fasterxml.jackson.annotation.JsonAnyGetter import com.fasterxml.jackson.annotation.JsonAnySetter import com.fasterxml.jackson.annotation.JsonCreator import com.fasterxml.jackson.annotation.JsonProperty +import com.fasterxml.jackson.core.JsonGenerator +import com.fasterxml.jackson.core.ObjectCodec +import com.fasterxml.jackson.databind.JsonNode +import com.fasterxml.jackson.databind.SerializerProvider +import com.fasterxml.jackson.databind.annotation.JsonDeserialize +import com.fasterxml.jackson.databind.annotation.JsonSerialize +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import com.openai.core.BaseDeserializer +import com.openai.core.BaseSerializer import com.openai.core.Enum import com.openai.core.ExcludeMissing import com.openai.core.JsonField import com.openai.core.JsonMissing import com.openai.core.JsonValue +import com.openai.core.allMaxBy import com.openai.core.checkKnown import com.openai.core.checkRequired +import com.openai.core.getOrThrow import com.openai.core.toImmutable import com.openai.errors.OpenAIInvalidDataException import java.util.Collections @@ -23,7 +34,7 @@ import kotlin.jvm.optionals.getOrNull class BetaResponseToolSearchOutputItemParam @JsonCreator(mode = JsonCreator.Mode.DISABLED) private constructor( - private val tools: JsonField>, + private val tools: JsonField>, private val type: JsonValue, private val id: JsonField, private val agent: JsonField, @@ -35,7 +46,7 @@ private constructor( @JsonCreator private constructor( - @JsonProperty("tools") @ExcludeMissing tools: JsonField> = JsonMissing.of(), + @JsonProperty("tools") @ExcludeMissing tools: JsonField> = JsonMissing.of(), @JsonProperty("type") @ExcludeMissing type: JsonValue = JsonMissing.of(), @JsonProperty("id") @ExcludeMissing id: JsonField = JsonMissing.of(), @JsonProperty("agent") @ExcludeMissing agent: JsonField = JsonMissing.of(), @@ -52,7 +63,7 @@ private constructor( * @throws OpenAIInvalidDataException if the JSON field has an unexpected type or is * unexpectedly missing or null (e.g. if the server responded with an unexpected value). */ - fun tools(): List = tools.getRequired("tools") + fun tools(): List = tools.getRequired("tools") /** * The item type. Always `tool_search_output`. @@ -112,7 +123,7 @@ private constructor( * * Unlike [tools], this method doesn't throw if the JSON field has an unexpected type. */ - @JsonProperty("tools") @ExcludeMissing fun _tools(): JsonField> = tools + @JsonProperty("tools") @ExcludeMissing fun _tools(): JsonField> = tools /** * Returns the raw JSON value of [id]. @@ -178,7 +189,7 @@ private constructor( /** A builder for [BetaResponseToolSearchOutputItemParam]. */ class Builder internal constructor() { - private var tools: JsonField>? = null + private var tools: JsonField>? = null private var type: JsonValue = JsonValue.from("tool_search_output") private var id: JsonField = JsonMissing.of() private var agent: JsonField = JsonMissing.of() @@ -203,34 +214,34 @@ private constructor( } /** The loaded tool definitions returned by the tool search output. */ - fun tools(tools: List) = tools(JsonField.of(tools)) + fun tools(tools: List) = tools(JsonField.of(tools)) /** * Sets [Builder.tools] to an arbitrary JSON value. * - * You should usually call [Builder.tools] with a well-typed `List` value instead. + * You should usually call [Builder.tools] with a well-typed `List` value instead. * This method is primarily for setting the field to an undocumented or not yet supported * value. */ - fun tools(tools: JsonField>) = apply { + fun tools(tools: JsonField>) = apply { this.tools = tools.map { it.toMutableList() } } /** - * Adds a single [BetaTool] to [tools]. + * Adds a single [Tool] to [tools]. * * @throws IllegalStateException if the field was previously set to a non-list. */ - fun addTool(tool: BetaTool) = apply { + fun addTool(tool: Tool) = apply { tools = (tools ?: JsonField.of(mutableListOf())).also { checkKnown("tools", it).add(tool) } } - /** Alias for calling [addTool] with `BetaTool.ofFunction(function)`. */ - fun addTool(function: BetaFunctionTool) = addTool(BetaTool.ofFunction(function)) + /** Alias for calling [addTool] with `Tool.ofFunction(function)`. */ + fun addTool(function: BetaFunctionTool) = addTool(Tool.ofFunction(function)) - /** Alias for calling [addTool] with `BetaTool.ofFileSearch(fileSearch)`. */ - fun addTool(fileSearch: BetaFileSearchTool) = addTool(BetaTool.ofFileSearch(fileSearch)) + /** Alias for calling [addTool] with `Tool.ofFileSearch(fileSearch)`. */ + fun addTool(fileSearch: BetaFileSearchTool) = addTool(Tool.ofFileSearch(fileSearch)) /** * Alias for calling [addTool] with the following: @@ -243,80 +254,78 @@ private constructor( fun addFileSearchTool(vectorStoreIds: List) = addTool(BetaFileSearchTool.builder().vectorStoreIds(vectorStoreIds).build()) - /** Alias for calling [addTool] with `BetaTool.ofComputer(computer)`. */ - fun addTool(computer: BetaComputerTool) = addTool(BetaTool.ofComputer(computer)) + /** Alias for calling [addTool] with `Tool.ofComputer(computer)`. */ + fun addTool(computer: BetaComputerTool) = addTool(Tool.ofComputer(computer)) - /** Alias for calling [addTool] with `BetaTool.ofComputerUsePreview(computerUsePreview)`. */ + /** Alias for calling [addTool] with `Tool.ofComputerUsePreview(computerUsePreview)`. */ fun addTool(computerUsePreview: BetaComputerUsePreviewTool) = - addTool(BetaTool.ofComputerUsePreview(computerUsePreview)) + addTool(Tool.ofComputerUsePreview(computerUsePreview)) - /** Alias for calling [addTool] with `BetaTool.ofWebSearch(webSearch)`. */ - fun addTool(webSearch: BetaWebSearchTool) = addTool(BetaTool.ofWebSearch(webSearch)) + /** Alias for calling [addTool] with `Tool.ofBetaWebSearch(betaWebSearch)`. */ + fun addTool(betaWebSearch: BetaWebSearchTool) = addTool(Tool.ofBetaWebSearch(betaWebSearch)) - /** Alias for calling [addTool] with `BetaTool.ofMcp(mcp)`. */ - fun addTool(mcp: BetaTool.Mcp) = addTool(BetaTool.ofMcp(mcp)) + /** Alias for calling [addTool] with `Tool.ofMcp(mcp)`. */ + fun addTool(mcp: Tool.Mcp) = addTool(Tool.ofMcp(mcp)) /** * Alias for calling [addTool] with the following: * ```java - * BetaTool.Mcp.builder() + * Tool.Mcp.builder() * .serverLabel(serverLabel) * .build() * ``` */ fun addMcpTool(serverLabel: String) = - addTool(BetaTool.Mcp.builder().serverLabel(serverLabel).build()) + addTool(Tool.Mcp.builder().serverLabel(serverLabel).build()) - /** Alias for calling [addTool] with `BetaTool.ofCodeInterpreter(codeInterpreter)`. */ - fun addTool(codeInterpreter: BetaTool.CodeInterpreter) = - addTool(BetaTool.ofCodeInterpreter(codeInterpreter)) + /** Alias for calling [addTool] with `Tool.ofCodeInterpreter(codeInterpreter)`. */ + fun addTool(codeInterpreter: Tool.CodeInterpreter) = + addTool(Tool.ofCodeInterpreter(codeInterpreter)) /** * Alias for calling [addTool] with the following: * ```java - * BetaTool.CodeInterpreter.builder() + * Tool.CodeInterpreter.builder() * .container(container) * .build() * ``` */ - fun addCodeInterpreterTool(container: BetaTool.CodeInterpreter.Container) = - addTool(BetaTool.CodeInterpreter.builder().container(container).build()) + fun addCodeInterpreterTool(container: Tool.CodeInterpreter.Container) = + addTool(Tool.CodeInterpreter.builder().container(container).build()) /** * Alias for calling [addCodeInterpreterTool] with - * `BetaTool.CodeInterpreter.Container.ofString(string)`. + * `Tool.CodeInterpreter.Container.ofString(string)`. */ fun addCodeInterpreterTool(string: String) = - addCodeInterpreterTool(BetaTool.CodeInterpreter.Container.ofString(string)) + addCodeInterpreterTool(Tool.CodeInterpreter.Container.ofString(string)) /** * Alias for calling [addCodeInterpreterTool] with - * `BetaTool.CodeInterpreter.Container.ofCodeInterpreterToolAuto(codeInterpreterToolAuto)`. + * `Tool.CodeInterpreter.Container.ofCodeInterpreterToolAuto(codeInterpreterToolAuto)`. */ fun addCodeInterpreterTool( - codeInterpreterToolAuto: BetaTool.CodeInterpreter.Container.CodeInterpreterToolAuto + codeInterpreterToolAuto: Tool.CodeInterpreter.Container.CodeInterpreterToolAuto ) = addCodeInterpreterTool( - BetaTool.CodeInterpreter.Container.ofCodeInterpreterToolAuto( - codeInterpreterToolAuto - ) + Tool.CodeInterpreter.Container.ofCodeInterpreterToolAuto(codeInterpreterToolAuto) ) - /** Alias for calling [addTool] with `BetaTool.ofProgrammaticToolCalling()`. */ - fun addToolProgrammaticToolCalling() = addTool(BetaTool.ofProgrammaticToolCalling()) + /** Alias for calling [addTool] with `Tool.ofProgrammaticToolCalling()`. */ + fun addToolProgrammaticToolCalling() = addTool(Tool.ofProgrammaticToolCalling()) - /** Alias for calling [addTool] with `BetaTool.ofImageGeneration(imageGeneration)`. */ - fun addTool(imageGeneration: BetaTool.ImageGeneration) = - addTool(BetaTool.ofImageGeneration(imageGeneration)) + /** Alias for calling [addTool] with `Tool.ofImageGeneration(imageGeneration)`. */ + fun addTool(imageGeneration: Tool.ImageGeneration) = + addTool(Tool.ofImageGeneration(imageGeneration)) - /** Alias for calling [addTool] with `BetaTool.ofLocalShell()`. */ - fun addToolLocalShell() = addTool(BetaTool.ofLocalShell()) + /** Alias for calling [addTool] with `Tool.ofLocalShell()`. */ + fun addToolLocalShell() = addTool(Tool.ofLocalShell()) - /** Alias for calling [addTool] with `BetaTool.ofShell(shell)`. */ - fun addTool(shell: BetaFunctionShellTool) = addTool(BetaTool.ofShell(shell)) + /** Alias for calling [addTool] with `Tool.ofShell(shell)`. */ + fun addTool(shell: BetaFunctionShellTool) = addTool(Tool.ofShell(shell)) - /** Alias for calling [addTool] with `BetaTool.ofCustom(custom)`. */ - fun addTool(custom: BetaCustomTool) = addTool(BetaTool.ofCustom(custom)) + /** Alias for calling [addTool] with `Tool.ofCustom(custom)`. */ + fun addTool(custom: BetaCustomTool) = addTool(Tool.ofCustom(custom)) /** * Alias for calling [addTool] with the following: @@ -328,18 +337,19 @@ private constructor( */ fun addCustomTool(name: String) = addTool(BetaCustomTool.builder().name(name).build()) - /** Alias for calling [addTool] with `BetaTool.ofNamespace(namespace)`. */ - fun addTool(namespace: BetaNamespaceTool) = addTool(BetaTool.ofNamespace(namespace)) + /** Alias for calling [addTool] with `Tool.ofNamespace(namespace)`. */ + fun addTool(namespace: BetaToolSearchOutputNamespaceTool) = + addTool(Tool.ofNamespace(namespace)) - /** Alias for calling [addTool] with `BetaTool.ofToolSearch(toolSearch)`. */ - fun addTool(toolSearch: BetaToolSearchTool) = addTool(BetaTool.ofToolSearch(toolSearch)) + /** Alias for calling [addTool] with `Tool.ofSearch(search)`. */ + fun addTool(search: BetaToolSearchTool) = addTool(Tool.ofSearch(search)) - /** Alias for calling [addTool] with `BetaTool.ofWebSearchPreview(webSearchPreview)`. */ - fun addTool(webSearchPreview: BetaWebSearchPreviewTool) = - addTool(BetaTool.ofWebSearchPreview(webSearchPreview)) + /** Alias for calling [addTool] with `Tool.ofBetaWebSearchPreview(betaWebSearchPreview)`. */ + fun addTool(betaWebSearchPreview: BetaWebSearchPreviewTool) = + addTool(Tool.ofBetaWebSearchPreview(betaWebSearchPreview)) - /** Alias for calling [addTool] with `BetaTool.ofApplyPatch(applyPatch)`. */ - fun addTool(applyPatch: BetaApplyPatchTool) = addTool(BetaTool.ofApplyPatch(applyPatch)) + /** Alias for calling [addTool] with `Tool.ofApplyPatch(applyPatch)`. */ + fun addTool(applyPatch: BetaApplyPatchTool) = addTool(Tool.ofApplyPatch(applyPatch)) /** * Sets the field to an arbitrary JSON value. @@ -519,6 +529,7380 @@ private constructor( (execution.asKnown().getOrNull()?.validity() ?: 0) + (status.asKnown().getOrNull()?.validity() ?: 0) + /** A tool definition returned by a tool search output. */ + @JsonDeserialize(using = Tool.Deserializer::class) + @JsonSerialize(using = Tool.Serializer::class) + class Tool + private constructor( + private val function: BetaFunctionTool? = null, + private val fileSearch: BetaFileSearchTool? = null, + private val computer: BetaComputerTool? = null, + private val computerUsePreview: BetaComputerUsePreviewTool? = null, + private val betaWebSearch: BetaWebSearchTool? = null, + private val mcp: Mcp? = null, + private val codeInterpreter: CodeInterpreter? = null, + private val programmaticToolCalling: JsonValue? = null, + private val imageGeneration: ImageGeneration? = null, + private val localShell: JsonValue? = null, + private val shell: BetaFunctionShellTool? = null, + private val custom: BetaCustomTool? = null, + private val namespace: BetaToolSearchOutputNamespaceTool? = null, + private val search: BetaToolSearchTool? = null, + private val betaWebSearchPreview: BetaWebSearchPreviewTool? = null, + private val applyPatch: BetaApplyPatchTool? = null, + private val _json: JsonValue? = null, + ) { + + /** + * Defines a function in your own code the model can choose to call. Learn more about + * [function calling](https://developers.openai.com/api/docs/guides/function-calling). + */ + fun function(): Optional = Optional.ofNullable(function) + + /** + * A tool that searches for relevant content from uploaded files. Learn more about the + * [file search tool](https://developers.openai.com/api/docs/guides/tools-file-search). + */ + fun fileSearch(): Optional = Optional.ofNullable(fileSearch) + + /** + * A tool that controls a virtual computer. Learn more about the + * [computer tool](https://developers.openai.com/api/docs/guides/tools-computer-use). + */ + fun computer(): Optional = Optional.ofNullable(computer) + + /** + * A tool that controls a virtual computer. Learn more about the + * [computer tool](https://developers.openai.com/api/docs/guides/tools-computer-use). + */ + fun computerUsePreview(): Optional = + Optional.ofNullable(computerUsePreview) + + /** + * Search the Internet for sources related to the prompt. Learn more about the + * [web search tool](https://developers.openai.com/api/docs/guides/tools-web-search). + */ + fun betaWebSearch(): Optional = Optional.ofNullable(betaWebSearch) + + /** + * Give the model access to additional tools via remote Model Context Protocol (MCP) + * servers. + * [Learn more about MCP](https://developers.openai.com/api/docs/guides/tools-connectors-mcp). + */ + fun mcp(): Optional = Optional.ofNullable(mcp) + + /** A tool that runs Python code to help generate a response to a prompt. */ + fun codeInterpreter(): Optional = Optional.ofNullable(codeInterpreter) + + fun programmaticToolCalling(): Optional = + Optional.ofNullable(programmaticToolCalling) + + /** A tool that generates images using the GPT image models. */ + fun imageGeneration(): Optional = Optional.ofNullable(imageGeneration) + + /** A tool that allows the model to execute shell commands in a local environment. */ + fun localShell(): Optional = Optional.ofNullable(localShell) + + /** A tool that allows the model to execute shell commands. */ + fun shell(): Optional = Optional.ofNullable(shell) + + /** + * A custom tool that processes input using a specified format. Learn more about + * [custom tools](https://developers.openai.com/api/docs/guides/function-calling#custom-tools) + */ + fun custom(): Optional = Optional.ofNullable(custom) + + /** Groups function/custom tools under a shared namespace. */ + fun namespace(): Optional = + Optional.ofNullable(namespace) + + /** Hosted or BYOT tool search configuration for deferred tools. */ + fun search(): Optional = Optional.ofNullable(search) + + /** + * This tool searches the web for relevant results to use in a response. Learn more about + * the [web search tool](https://developers.openai.com/api/docs/guides/tools-web-search). + */ + fun betaWebSearchPreview(): Optional = + Optional.ofNullable(betaWebSearchPreview) + + /** Allows the assistant to create, delete, or update files using unified diffs. */ + fun applyPatch(): Optional = Optional.ofNullable(applyPatch) + + fun isFunction(): Boolean = function != null + + fun isFileSearch(): Boolean = fileSearch != null + + fun isComputer(): Boolean = computer != null + + fun isComputerUsePreview(): Boolean = computerUsePreview != null + + fun isBetaWebSearch(): Boolean = betaWebSearch != null + + fun isMcp(): Boolean = mcp != null + + fun isCodeInterpreter(): Boolean = codeInterpreter != null + + fun isProgrammaticToolCalling(): Boolean = programmaticToolCalling != null + + fun isImageGeneration(): Boolean = imageGeneration != null + + fun isLocalShell(): Boolean = localShell != null + + fun isShell(): Boolean = shell != null + + fun isCustom(): Boolean = custom != null + + fun isNamespace(): Boolean = namespace != null + + fun isSearch(): Boolean = search != null + + fun isBetaWebSearchPreview(): Boolean = betaWebSearchPreview != null + + fun isApplyPatch(): Boolean = applyPatch != null + + /** + * Defines a function in your own code the model can choose to call. Learn more about + * [function calling](https://developers.openai.com/api/docs/guides/function-calling). + */ + fun asFunction(): BetaFunctionTool = function.getOrThrow("function") + + /** + * A tool that searches for relevant content from uploaded files. Learn more about the + * [file search tool](https://developers.openai.com/api/docs/guides/tools-file-search). + */ + fun asFileSearch(): BetaFileSearchTool = fileSearch.getOrThrow("fileSearch") + + /** + * A tool that controls a virtual computer. Learn more about the + * [computer tool](https://developers.openai.com/api/docs/guides/tools-computer-use). + */ + fun asComputer(): BetaComputerTool = computer.getOrThrow("computer") + + /** + * A tool that controls a virtual computer. Learn more about the + * [computer tool](https://developers.openai.com/api/docs/guides/tools-computer-use). + */ + fun asComputerUsePreview(): BetaComputerUsePreviewTool = + computerUsePreview.getOrThrow("computerUsePreview") + + /** + * Search the Internet for sources related to the prompt. Learn more about the + * [web search tool](https://developers.openai.com/api/docs/guides/tools-web-search). + */ + fun asBetaWebSearch(): BetaWebSearchTool = betaWebSearch.getOrThrow("betaWebSearch") + + /** + * Give the model access to additional tools via remote Model Context Protocol (MCP) + * servers. + * [Learn more about MCP](https://developers.openai.com/api/docs/guides/tools-connectors-mcp). + */ + fun asMcp(): Mcp = mcp.getOrThrow("mcp") + + /** A tool that runs Python code to help generate a response to a prompt. */ + fun asCodeInterpreter(): CodeInterpreter = codeInterpreter.getOrThrow("codeInterpreter") + + fun asProgrammaticToolCalling(): JsonValue = + programmaticToolCalling.getOrThrow("programmaticToolCalling") + + /** A tool that generates images using the GPT image models. */ + fun asImageGeneration(): ImageGeneration = imageGeneration.getOrThrow("imageGeneration") + + /** A tool that allows the model to execute shell commands in a local environment. */ + fun asLocalShell(): JsonValue = localShell.getOrThrow("localShell") + + /** A tool that allows the model to execute shell commands. */ + fun asShell(): BetaFunctionShellTool = shell.getOrThrow("shell") + + /** + * A custom tool that processes input using a specified format. Learn more about + * [custom tools](https://developers.openai.com/api/docs/guides/function-calling#custom-tools) + */ + fun asCustom(): BetaCustomTool = custom.getOrThrow("custom") + + /** Groups function/custom tools under a shared namespace. */ + fun asNamespace(): BetaToolSearchOutputNamespaceTool = namespace.getOrThrow("namespace") + + /** Hosted or BYOT tool search configuration for deferred tools. */ + fun asSearch(): BetaToolSearchTool = search.getOrThrow("search") + + /** + * This tool searches the web for relevant results to use in a response. Learn more about + * the [web search tool](https://developers.openai.com/api/docs/guides/tools-web-search). + */ + fun asBetaWebSearchPreview(): BetaWebSearchPreviewTool = + betaWebSearchPreview.getOrThrow("betaWebSearchPreview") + + /** Allows the assistant to create, delete, or update files using unified diffs. */ + fun asApplyPatch(): BetaApplyPatchTool = applyPatch.getOrThrow("applyPatch") + + fun _json(): Optional = Optional.ofNullable(_json) + + /** + * Maps this instance's current variant to a value of type [T] using the given [visitor]. + * + * Note that this method is _not_ forwards compatible with new variants from the API, unless + * [visitor] overrides [Visitor.unknown]. To handle variants not known to this version of + * the SDK gracefully, consider overriding [Visitor.unknown]: + * ```java + * import com.openai.core.JsonValue; + * import java.util.Optional; + * + * Optional result = tool.accept(new Tool.Visitor>() { + * @Override + * public Optional visitFunction(BetaFunctionTool function) { + * return Optional.of(function.toString()); + * } + * + * // ... + * + * @Override + * public Optional unknown(JsonValue json) { + * // Or inspect the `json`. + * return Optional.empty(); + * } + * }); + * ``` + * + * @throws OpenAIInvalidDataException if [Visitor.unknown] is not overridden in [visitor] + * and the current variant is unknown. + */ + fun accept(visitor: Visitor): T = + when { + function != null -> visitor.visitFunction(function) + fileSearch != null -> visitor.visitFileSearch(fileSearch) + computer != null -> visitor.visitComputer(computer) + computerUsePreview != null -> visitor.visitComputerUsePreview(computerUsePreview) + betaWebSearch != null -> visitor.visitBetaWebSearch(betaWebSearch) + mcp != null -> visitor.visitMcp(mcp) + codeInterpreter != null -> visitor.visitCodeInterpreter(codeInterpreter) + programmaticToolCalling != null -> + visitor.visitProgrammaticToolCalling(programmaticToolCalling) + imageGeneration != null -> visitor.visitImageGeneration(imageGeneration) + localShell != null -> visitor.visitLocalShell(localShell) + shell != null -> visitor.visitShell(shell) + custom != null -> visitor.visitCustom(custom) + namespace != null -> visitor.visitNamespace(namespace) + search != null -> visitor.visitSearch(search) + betaWebSearchPreview != null -> + visitor.visitBetaWebSearchPreview(betaWebSearchPreview) + applyPatch != null -> visitor.visitApplyPatch(applyPatch) + else -> visitor.unknown(_json) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws OpenAIInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): Tool = apply { + if (validated) { + return@apply + } + + accept( + object : Visitor { + override fun visitFunction(function: BetaFunctionTool) { + function.validate() + } + + override fun visitFileSearch(fileSearch: BetaFileSearchTool) { + fileSearch.validate() + } + + override fun visitComputer(computer: BetaComputerTool) { + computer.validate() + } + + override fun visitComputerUsePreview( + computerUsePreview: BetaComputerUsePreviewTool + ) { + computerUsePreview.validate() + } + + override fun visitBetaWebSearch(betaWebSearch: BetaWebSearchTool) { + betaWebSearch.validate() + } + + override fun visitMcp(mcp: Mcp) { + mcp.validate() + } + + override fun visitCodeInterpreter(codeInterpreter: CodeInterpreter) { + codeInterpreter.validate() + } + + override fun visitProgrammaticToolCalling(programmaticToolCalling: JsonValue) { + programmaticToolCalling.let { + if ( + it != JsonValue.from(mapOf("type" to "programmatic_tool_calling")) + ) { + throw OpenAIInvalidDataException( + "'programmaticToolCalling' is invalid, received $it" + ) + } + } + } + + override fun visitImageGeneration(imageGeneration: ImageGeneration) { + imageGeneration.validate() + } + + override fun visitLocalShell(localShell: JsonValue) { + localShell.let { + if (it != JsonValue.from(mapOf("type" to "local_shell"))) { + throw OpenAIInvalidDataException( + "'localShell' is invalid, received $it" + ) + } + } + } + + override fun visitShell(shell: BetaFunctionShellTool) { + shell.validate() + } + + override fun visitCustom(custom: BetaCustomTool) { + custom.validate() + } + + override fun visitNamespace(namespace: BetaToolSearchOutputNamespaceTool) { + namespace.validate() + } + + override fun visitSearch(search: BetaToolSearchTool) { + search.validate() + } + + override fun visitBetaWebSearchPreview( + betaWebSearchPreview: BetaWebSearchPreviewTool + ) { + betaWebSearchPreview.validate() + } + + override fun visitApplyPatch(applyPatch: BetaApplyPatchTool) { + applyPatch.validate() + } + } + ) + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: OpenAIInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + accept( + object : Visitor { + override fun visitFunction(function: BetaFunctionTool) = function.validity() + + override fun visitFileSearch(fileSearch: BetaFileSearchTool) = + fileSearch.validity() + + override fun visitComputer(computer: BetaComputerTool) = computer.validity() + + override fun visitComputerUsePreview( + computerUsePreview: BetaComputerUsePreviewTool + ) = computerUsePreview.validity() + + override fun visitBetaWebSearch(betaWebSearch: BetaWebSearchTool) = + betaWebSearch.validity() + + override fun visitMcp(mcp: Mcp) = mcp.validity() + + override fun visitCodeInterpreter(codeInterpreter: CodeInterpreter) = + codeInterpreter.validity() + + override fun visitProgrammaticToolCalling(programmaticToolCalling: JsonValue) = + programmaticToolCalling.let { + if (it == JsonValue.from(mapOf("type" to "programmatic_tool_calling"))) + 1 + else 0 + } + + override fun visitImageGeneration(imageGeneration: ImageGeneration) = + imageGeneration.validity() + + override fun visitLocalShell(localShell: JsonValue) = + localShell.let { + if (it == JsonValue.from(mapOf("type" to "local_shell"))) 1 else 0 + } + + override fun visitShell(shell: BetaFunctionShellTool) = shell.validity() + + override fun visitCustom(custom: BetaCustomTool) = custom.validity() + + override fun visitNamespace(namespace: BetaToolSearchOutputNamespaceTool) = + namespace.validity() + + override fun visitSearch(search: BetaToolSearchTool) = search.validity() + + override fun visitBetaWebSearchPreview( + betaWebSearchPreview: BetaWebSearchPreviewTool + ) = betaWebSearchPreview.validity() + + override fun visitApplyPatch(applyPatch: BetaApplyPatchTool) = + applyPatch.validity() + + override fun unknown(json: JsonValue?) = 0 + } + ) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Tool && + function == other.function && + fileSearch == other.fileSearch && + computer == other.computer && + computerUsePreview == other.computerUsePreview && + betaWebSearch == other.betaWebSearch && + mcp == other.mcp && + codeInterpreter == other.codeInterpreter && + programmaticToolCalling == other.programmaticToolCalling && + imageGeneration == other.imageGeneration && + localShell == other.localShell && + shell == other.shell && + custom == other.custom && + namespace == other.namespace && + search == other.search && + betaWebSearchPreview == other.betaWebSearchPreview && + applyPatch == other.applyPatch + } + + override fun hashCode(): Int = + Objects.hash( + function, + fileSearch, + computer, + computerUsePreview, + betaWebSearch, + mcp, + codeInterpreter, + programmaticToolCalling, + imageGeneration, + localShell, + shell, + custom, + namespace, + search, + betaWebSearchPreview, + applyPatch, + ) + + override fun toString(): String = + when { + function != null -> "Tool{function=$function}" + fileSearch != null -> "Tool{fileSearch=$fileSearch}" + computer != null -> "Tool{computer=$computer}" + computerUsePreview != null -> "Tool{computerUsePreview=$computerUsePreview}" + betaWebSearch != null -> "Tool{betaWebSearch=$betaWebSearch}" + mcp != null -> "Tool{mcp=$mcp}" + codeInterpreter != null -> "Tool{codeInterpreter=$codeInterpreter}" + programmaticToolCalling != null -> + "Tool{programmaticToolCalling=$programmaticToolCalling}" + imageGeneration != null -> "Tool{imageGeneration=$imageGeneration}" + localShell != null -> "Tool{localShell=$localShell}" + shell != null -> "Tool{shell=$shell}" + custom != null -> "Tool{custom=$custom}" + namespace != null -> "Tool{namespace=$namespace}" + search != null -> "Tool{search=$search}" + betaWebSearchPreview != null -> "Tool{betaWebSearchPreview=$betaWebSearchPreview}" + applyPatch != null -> "Tool{applyPatch=$applyPatch}" + _json != null -> "Tool{_unknown=$_json}" + else -> throw IllegalStateException("Invalid Tool") + } + + companion object { + + /** + * Defines a function in your own code the model can choose to call. Learn more about + * [function calling](https://developers.openai.com/api/docs/guides/function-calling). + */ + @JvmStatic fun ofFunction(function: BetaFunctionTool) = Tool(function = function) + + /** + * A tool that searches for relevant content from uploaded files. Learn more about the + * [file search tool](https://developers.openai.com/api/docs/guides/tools-file-search). + */ + @JvmStatic + fun ofFileSearch(fileSearch: BetaFileSearchTool) = Tool(fileSearch = fileSearch) + + /** + * A tool that controls a virtual computer. Learn more about the + * [computer tool](https://developers.openai.com/api/docs/guides/tools-computer-use). + */ + @JvmStatic fun ofComputer(computer: BetaComputerTool) = Tool(computer = computer) + + /** + * A tool that controls a virtual computer. Learn more about the + * [computer tool](https://developers.openai.com/api/docs/guides/tools-computer-use). + */ + @JvmStatic + fun ofComputerUsePreview(computerUsePreview: BetaComputerUsePreviewTool) = + Tool(computerUsePreview = computerUsePreview) + + /** + * Search the Internet for sources related to the prompt. Learn more about the + * [web search tool](https://developers.openai.com/api/docs/guides/tools-web-search). + */ + @JvmStatic + fun ofBetaWebSearch(betaWebSearch: BetaWebSearchTool) = + Tool(betaWebSearch = betaWebSearch) + + /** + * Give the model access to additional tools via remote Model Context Protocol (MCP) + * servers. + * [Learn more about MCP](https://developers.openai.com/api/docs/guides/tools-connectors-mcp). + */ + @JvmStatic fun ofMcp(mcp: Mcp) = Tool(mcp = mcp) + + /** A tool that runs Python code to help generate a response to a prompt. */ + @JvmStatic + fun ofCodeInterpreter(codeInterpreter: CodeInterpreter) = + Tool(codeInterpreter = codeInterpreter) + + @JvmStatic + fun ofProgrammaticToolCalling() = + Tool( + programmaticToolCalling = + JsonValue.from(mapOf("type" to "programmatic_tool_calling")) + ) + + /** A tool that generates images using the GPT image models. */ + @JvmStatic + fun ofImageGeneration(imageGeneration: ImageGeneration) = + Tool(imageGeneration = imageGeneration) + + /** A tool that allows the model to execute shell commands in a local environment. */ + @JvmStatic + fun ofLocalShell() = Tool(localShell = JsonValue.from(mapOf("type" to "local_shell"))) + + /** A tool that allows the model to execute shell commands. */ + @JvmStatic fun ofShell(shell: BetaFunctionShellTool) = Tool(shell = shell) + + /** + * A custom tool that processes input using a specified format. Learn more about + * [custom tools](https://developers.openai.com/api/docs/guides/function-calling#custom-tools) + */ + @JvmStatic fun ofCustom(custom: BetaCustomTool) = Tool(custom = custom) + + /** Groups function/custom tools under a shared namespace. */ + @JvmStatic + fun ofNamespace(namespace: BetaToolSearchOutputNamespaceTool) = + Tool(namespace = namespace) + + /** Hosted or BYOT tool search configuration for deferred tools. */ + @JvmStatic fun ofSearch(search: BetaToolSearchTool) = Tool(search = search) + + /** + * This tool searches the web for relevant results to use in a response. Learn more + * about the + * [web search tool](https://developers.openai.com/api/docs/guides/tools-web-search). + */ + @JvmStatic + fun ofBetaWebSearchPreview(betaWebSearchPreview: BetaWebSearchPreviewTool) = + Tool(betaWebSearchPreview = betaWebSearchPreview) + + /** Allows the assistant to create, delete, or update files using unified diffs. */ + @JvmStatic + fun ofApplyPatch(applyPatch: BetaApplyPatchTool) = Tool(applyPatch = applyPatch) + } + + /** An interface that defines how to map each variant of [Tool] to a value of type [T]. */ + interface Visitor { + + /** + * Defines a function in your own code the model can choose to call. Learn more about + * [function calling](https://developers.openai.com/api/docs/guides/function-calling). + */ + fun visitFunction(function: BetaFunctionTool): T + + /** + * A tool that searches for relevant content from uploaded files. Learn more about the + * [file search tool](https://developers.openai.com/api/docs/guides/tools-file-search). + */ + fun visitFileSearch(fileSearch: BetaFileSearchTool): T + + /** + * A tool that controls a virtual computer. Learn more about the + * [computer tool](https://developers.openai.com/api/docs/guides/tools-computer-use). + */ + fun visitComputer(computer: BetaComputerTool): T + + /** + * A tool that controls a virtual computer. Learn more about the + * [computer tool](https://developers.openai.com/api/docs/guides/tools-computer-use). + */ + fun visitComputerUsePreview(computerUsePreview: BetaComputerUsePreviewTool): T + + /** + * Search the Internet for sources related to the prompt. Learn more about the + * [web search tool](https://developers.openai.com/api/docs/guides/tools-web-search). + */ + fun visitBetaWebSearch(betaWebSearch: BetaWebSearchTool): T + + /** + * Give the model access to additional tools via remote Model Context Protocol (MCP) + * servers. + * [Learn more about MCP](https://developers.openai.com/api/docs/guides/tools-connectors-mcp). + */ + fun visitMcp(mcp: Mcp): T + + /** A tool that runs Python code to help generate a response to a prompt. */ + fun visitCodeInterpreter(codeInterpreter: CodeInterpreter): T + + fun visitProgrammaticToolCalling(programmaticToolCalling: JsonValue): T + + /** A tool that generates images using the GPT image models. */ + fun visitImageGeneration(imageGeneration: ImageGeneration): T + + /** A tool that allows the model to execute shell commands in a local environment. */ + fun visitLocalShell(localShell: JsonValue): T + + /** A tool that allows the model to execute shell commands. */ + fun visitShell(shell: BetaFunctionShellTool): T + + /** + * A custom tool that processes input using a specified format. Learn more about + * [custom tools](https://developers.openai.com/api/docs/guides/function-calling#custom-tools) + */ + fun visitCustom(custom: BetaCustomTool): T + + /** Groups function/custom tools under a shared namespace. */ + fun visitNamespace(namespace: BetaToolSearchOutputNamespaceTool): T + + /** Hosted or BYOT tool search configuration for deferred tools. */ + fun visitSearch(search: BetaToolSearchTool): T + + /** + * This tool searches the web for relevant results to use in a response. Learn more + * about the + * [web search tool](https://developers.openai.com/api/docs/guides/tools-web-search). + */ + fun visitBetaWebSearchPreview(betaWebSearchPreview: BetaWebSearchPreviewTool): T + + /** Allows the assistant to create, delete, or update files using unified diffs. */ + fun visitApplyPatch(applyPatch: BetaApplyPatchTool): T + + /** + * Maps an unknown variant of [Tool] to a value of type [T]. + * + * An instance of [Tool] can contain an unknown variant if it was deserialized from data + * that doesn't match any known variant. For example, if the SDK is on an older version + * than the API, then the API may respond with new variants that the SDK is unaware of. + * + * @throws OpenAIInvalidDataException in the default implementation. + */ + fun unknown(json: JsonValue?): T { + throw OpenAIInvalidDataException("Unknown Tool") + } + } + + internal class Deserializer : BaseDeserializer(Tool::class) { + + override fun ObjectCodec.deserialize(node: JsonNode): Tool { + val json = JsonValue.fromJsonNode(node) + val type = json.asObject().getOrNull()?.get("type")?.asString()?.getOrNull() + + when (type) { + "function" -> { + return tryDeserialize(node, jacksonTypeRef())?.let { + Tool(function = it, _json = json) + } ?: Tool(_json = json) + } + "file_search" -> { + return tryDeserialize(node, jacksonTypeRef())?.let { + Tool(fileSearch = it, _json = json) + } ?: Tool(_json = json) + } + "computer" -> { + return tryDeserialize(node, jacksonTypeRef())?.let { + Tool(computer = it, _json = json) + } ?: Tool(_json = json) + } + "computer_use_preview" -> { + return tryDeserialize(node, jacksonTypeRef()) + ?.let { Tool(computerUsePreview = it, _json = json) } + ?: Tool(_json = json) + } + "mcp" -> { + return tryDeserialize(node, jacksonTypeRef())?.let { + Tool(mcp = it, _json = json) + } ?: Tool(_json = json) + } + "code_interpreter" -> { + return tryDeserialize(node, jacksonTypeRef())?.let { + Tool(codeInterpreter = it, _json = json) + } ?: Tool(_json = json) + } + "programmatic_tool_calling" -> { + return tryDeserialize(node, jacksonTypeRef()) + ?.let { Tool(programmaticToolCalling = it, _json = json) } + ?.takeIf { it.isValid() } ?: Tool(_json = json) + } + "image_generation" -> { + return tryDeserialize(node, jacksonTypeRef())?.let { + Tool(imageGeneration = it, _json = json) + } ?: Tool(_json = json) + } + "local_shell" -> { + return tryDeserialize(node, jacksonTypeRef()) + ?.let { Tool(localShell = it, _json = json) } + ?.takeIf { it.isValid() } ?: Tool(_json = json) + } + "shell" -> { + return tryDeserialize(node, jacksonTypeRef())?.let { + Tool(shell = it, _json = json) + } ?: Tool(_json = json) + } + "custom" -> { + return tryDeserialize(node, jacksonTypeRef())?.let { + Tool(custom = it, _json = json) + } ?: Tool(_json = json) + } + "namespace" -> { + return tryDeserialize( + node, + jacksonTypeRef(), + ) + ?.let { Tool(namespace = it, _json = json) } ?: Tool(_json = json) + } + "tool_search" -> { + return tryDeserialize(node, jacksonTypeRef())?.let { + Tool(search = it, _json = json) + } ?: Tool(_json = json) + } + "apply_patch" -> { + return tryDeserialize(node, jacksonTypeRef())?.let { + Tool(applyPatch = it, _json = json) + } ?: Tool(_json = json) + } + } + + val bestMatches = + sequenceOf( + tryDeserialize(node, jacksonTypeRef())?.let { + Tool(betaWebSearch = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef())?.let { + Tool(betaWebSearchPreview = it, _json = json) + }, + ) + .filterNotNull() + .allMaxBy { it.validity() } + .toList() + return when (bestMatches.size) { + // This can happen if what we're deserializing is completely incompatible with + // all the possible variants (e.g. deserializing from boolean). + 0 -> Tool(_json = json) + 1 -> bestMatches.single() + // If there's more than one match with the highest validity, then use the first + // completely valid match, or simply the first match if none are completely + // valid. + else -> bestMatches.firstOrNull { it.isValid() } ?: bestMatches.first() + } + } + } + + internal class Serializer : BaseSerializer(Tool::class) { + + override fun serialize( + value: Tool, + generator: JsonGenerator, + provider: SerializerProvider, + ) { + when { + value.function != null -> generator.writeObject(value.function) + value.fileSearch != null -> generator.writeObject(value.fileSearch) + value.computer != null -> generator.writeObject(value.computer) + value.computerUsePreview != null -> + generator.writeObject(value.computerUsePreview) + value.betaWebSearch != null -> generator.writeObject(value.betaWebSearch) + value.mcp != null -> generator.writeObject(value.mcp) + value.codeInterpreter != null -> generator.writeObject(value.codeInterpreter) + value.programmaticToolCalling != null -> + generator.writeObject(value.programmaticToolCalling) + value.imageGeneration != null -> generator.writeObject(value.imageGeneration) + value.localShell != null -> generator.writeObject(value.localShell) + value.shell != null -> generator.writeObject(value.shell) + value.custom != null -> generator.writeObject(value.custom) + value.namespace != null -> generator.writeObject(value.namespace) + value.search != null -> generator.writeObject(value.search) + value.betaWebSearchPreview != null -> + generator.writeObject(value.betaWebSearchPreview) + value.applyPatch != null -> generator.writeObject(value.applyPatch) + value._json != null -> generator.writeObject(value._json) + else -> throw IllegalStateException("Invalid Tool") + } + } + } + + /** + * Give the model access to additional tools via remote Model Context Protocol (MCP) + * servers. + * [Learn more about MCP](https://developers.openai.com/api/docs/guides/tools-connectors-mcp). + */ + class Mcp + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val serverLabel: JsonField, + private val type: JsonValue, + private val allowedCallers: JsonField>, + private val allowedTools: JsonField, + private val authorization: JsonField, + private val connectorId: JsonField, + private val deferLoading: JsonField, + private val headers: JsonField, + private val requireApproval: JsonField, + private val serverDescription: JsonField, + private val serverUrl: JsonField, + private val tunnelId: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("server_label") + @ExcludeMissing + serverLabel: JsonField = JsonMissing.of(), + @JsonProperty("type") @ExcludeMissing type: JsonValue = JsonMissing.of(), + @JsonProperty("allowed_callers") + @ExcludeMissing + allowedCallers: JsonField> = JsonMissing.of(), + @JsonProperty("allowed_tools") + @ExcludeMissing + allowedTools: JsonField = JsonMissing.of(), + @JsonProperty("authorization") + @ExcludeMissing + authorization: JsonField = JsonMissing.of(), + @JsonProperty("connector_id") + @ExcludeMissing + connectorId: JsonField = JsonMissing.of(), + @JsonProperty("defer_loading") + @ExcludeMissing + deferLoading: JsonField = JsonMissing.of(), + @JsonProperty("headers") + @ExcludeMissing + headers: JsonField = JsonMissing.of(), + @JsonProperty("require_approval") + @ExcludeMissing + requireApproval: JsonField = JsonMissing.of(), + @JsonProperty("server_description") + @ExcludeMissing + serverDescription: JsonField = JsonMissing.of(), + @JsonProperty("server_url") + @ExcludeMissing + serverUrl: JsonField = JsonMissing.of(), + @JsonProperty("tunnel_id") + @ExcludeMissing + tunnelId: JsonField = JsonMissing.of(), + ) : this( + serverLabel, + type, + allowedCallers, + allowedTools, + authorization, + connectorId, + deferLoading, + headers, + requireApproval, + serverDescription, + serverUrl, + tunnelId, + mutableMapOf(), + ) + + /** + * A label for this MCP server, used to identify it in tool calls. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected + * value). + */ + fun serverLabel(): String = serverLabel.getRequired("server_label") + + /** + * The type of the MCP tool. Always `mcp`. + * + * Expected to always return the following: + * ```java + * JsonValue.from("mcp") + * ``` + * + * However, this method can be useful for debugging and logging (e.g. if the server + * responded with an unexpected value). + */ + @JsonProperty("type") @ExcludeMissing fun _type(): JsonValue = type + + /** + * The tool invocation context(s). + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun allowedCallers(): Optional> = + allowedCallers.getOptional("allowed_callers") + + /** + * List of allowed tool names or a filter object. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun allowedTools(): Optional = allowedTools.getOptional("allowed_tools") + + /** + * An OAuth access token that can be used with a remote MCP server, either with a custom + * MCP server URL or a service connector. Your application must handle the OAuth + * authorization flow and provide the token here. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun authorization(): Optional = authorization.getOptional("authorization") + + /** + * Identifier for service connectors, like those available in ChatGPT. One of + * `server_url`, `connector_id`, or `tunnel_id` must be provided. Learn more about + * service connectors + * [here](https://developers.openai.com/api/docs/guides/tools-connectors-mcp#connectors). + * + * This field is deprecated for models released after September 1, 2026. Use + * `server_url` to connect to a remote MCP server, or `tunnel_id` to connect through a + * Secure MCP Tunnel. + * + * Currently supported `connector_id` values are: + * - Dropbox: `connector_dropbox` + * - Gmail: `connector_gmail` + * - Google Calendar: `connector_googlecalendar` + * - Google Drive: `connector_googledrive` + * - Microsoft Teams: `connector_microsoftteams` + * - Outlook Calendar: `connector_outlookcalendar` + * - Outlook Email: `connector_outlookemail` + * - SharePoint: `connector_sharepoint` + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + @Deprecated("deprecated") + fun connectorId(): Optional = connectorId.getOptional("connector_id") + + /** + * Whether this MCP tool is deferred and discovered via tool search. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun deferLoading(): Optional = deferLoading.getOptional("defer_loading") + + /** + * Optional HTTP headers to send to the MCP server. Use for authentication or other + * purposes. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun headers(): Optional = headers.getOptional("headers") + + /** + * Specify which of the MCP server's tools require approval. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun requireApproval(): Optional = + requireApproval.getOptional("require_approval") + + /** + * Optional description of the MCP server, used to provide more context. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun serverDescription(): Optional = + serverDescription.getOptional("server_description") + + /** + * The URL for the MCP server. One of `server_url`, `connector_id`, or `tunnel_id` must + * be provided. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun serverUrl(): Optional = serverUrl.getOptional("server_url") + + /** + * The Secure MCP Tunnel ID to use instead of a direct server URL. One of `server_url`, + * `connector_id`, or `tunnel_id` must be provided. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun tunnelId(): Optional = tunnelId.getOptional("tunnel_id") + + /** + * Returns the raw JSON value of [serverLabel]. + * + * Unlike [serverLabel], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("server_label") + @ExcludeMissing + fun _serverLabel(): JsonField = serverLabel + + /** + * Returns the raw JSON value of [allowedCallers]. + * + * Unlike [allowedCallers], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("allowed_callers") + @ExcludeMissing + fun _allowedCallers(): JsonField> = allowedCallers + + /** + * Returns the raw JSON value of [allowedTools]. + * + * Unlike [allowedTools], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("allowed_tools") + @ExcludeMissing + fun _allowedTools(): JsonField = allowedTools + + /** + * Returns the raw JSON value of [authorization]. + * + * Unlike [authorization], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("authorization") + @ExcludeMissing + fun _authorization(): JsonField = authorization + + /** + * Returns the raw JSON value of [connectorId]. + * + * Unlike [connectorId], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @Deprecated("deprecated") + @JsonProperty("connector_id") + @ExcludeMissing + fun _connectorId(): JsonField = connectorId + + /** + * Returns the raw JSON value of [deferLoading]. + * + * Unlike [deferLoading], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("defer_loading") + @ExcludeMissing + fun _deferLoading(): JsonField = deferLoading + + /** + * Returns the raw JSON value of [headers]. + * + * Unlike [headers], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("headers") @ExcludeMissing fun _headers(): JsonField = headers + + /** + * Returns the raw JSON value of [requireApproval]. + * + * Unlike [requireApproval], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("require_approval") + @ExcludeMissing + fun _requireApproval(): JsonField = requireApproval + + /** + * Returns the raw JSON value of [serverDescription]. + * + * Unlike [serverDescription], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("server_description") + @ExcludeMissing + fun _serverDescription(): JsonField = serverDescription + + /** + * Returns the raw JSON value of [serverUrl]. + * + * Unlike [serverUrl], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("server_url") + @ExcludeMissing + fun _serverUrl(): JsonField = serverUrl + + /** + * Returns the raw JSON value of [tunnelId]. + * + * Unlike [tunnelId], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("tunnel_id") @ExcludeMissing fun _tunnelId(): JsonField = tunnelId + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [Mcp]. + * + * The following fields are required: + * ```java + * .serverLabel() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Mcp]. */ + class Builder internal constructor() { + + private var serverLabel: JsonField? = null + private var type: JsonValue = JsonValue.from("mcp") + private var allowedCallers: JsonField>? = null + private var allowedTools: JsonField = JsonMissing.of() + private var authorization: JsonField = JsonMissing.of() + private var connectorId: JsonField = JsonMissing.of() + private var deferLoading: JsonField = JsonMissing.of() + private var headers: JsonField = JsonMissing.of() + private var requireApproval: JsonField = JsonMissing.of() + private var serverDescription: JsonField = JsonMissing.of() + private var serverUrl: JsonField = JsonMissing.of() + private var tunnelId: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(mcp: Mcp) = apply { + serverLabel = mcp.serverLabel + type = mcp.type + allowedCallers = mcp.allowedCallers.map { it.toMutableList() } + allowedTools = mcp.allowedTools + authorization = mcp.authorization + connectorId = mcp.connectorId + deferLoading = mcp.deferLoading + headers = mcp.headers + requireApproval = mcp.requireApproval + serverDescription = mcp.serverDescription + serverUrl = mcp.serverUrl + tunnelId = mcp.tunnelId + additionalProperties = mcp.additionalProperties.toMutableMap() + } + + /** A label for this MCP server, used to identify it in tool calls. */ + fun serverLabel(serverLabel: String) = serverLabel(JsonField.of(serverLabel)) + + /** + * Sets [Builder.serverLabel] to an arbitrary JSON value. + * + * You should usually call [Builder.serverLabel] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun serverLabel(serverLabel: JsonField) = apply { + this.serverLabel = serverLabel + } + + /** + * Sets the field to an arbitrary JSON value. + * + * It is usually unnecessary to call this method because the field defaults to the + * following: + * ```java + * JsonValue.from("mcp") + * ``` + * + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun type(type: JsonValue) = apply { this.type = type } + + /** The tool invocation context(s). */ + fun allowedCallers(allowedCallers: List?) = + allowedCallers(JsonField.ofNullable(allowedCallers)) + + /** + * Alias for calling [Builder.allowedCallers] with `allowedCallers.orElse(null)`. + */ + fun allowedCallers(allowedCallers: Optional>) = + allowedCallers(allowedCallers.getOrNull()) + + /** + * Sets [Builder.allowedCallers] to an arbitrary JSON value. + * + * You should usually call [Builder.allowedCallers] with a well-typed + * `List` value instead. This method is primarily for setting the + * field to an undocumented or not yet supported value. + */ + fun allowedCallers(allowedCallers: JsonField>) = apply { + this.allowedCallers = allowedCallers.map { it.toMutableList() } + } + + /** + * Adds a single [AllowedCaller] to [allowedCallers]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addAllowedCaller(allowedCaller: AllowedCaller) = apply { + allowedCallers = + (allowedCallers ?: JsonField.of(mutableListOf())).also { + checkKnown("allowedCallers", it).add(allowedCaller) + } + } + + /** List of allowed tool names or a filter object. */ + fun allowedTools(allowedTools: AllowedTools?) = + allowedTools(JsonField.ofNullable(allowedTools)) + + /** Alias for calling [Builder.allowedTools] with `allowedTools.orElse(null)`. */ + fun allowedTools(allowedTools: Optional) = + allowedTools(allowedTools.getOrNull()) + + /** + * Sets [Builder.allowedTools] to an arbitrary JSON value. + * + * You should usually call [Builder.allowedTools] with a well-typed [AllowedTools] + * value instead. This method is primarily for setting the field to an undocumented + * or not yet supported value. + */ + fun allowedTools(allowedTools: JsonField) = apply { + this.allowedTools = allowedTools + } + + /** Alias for calling [allowedTools] with `AllowedTools.ofMcp(mcp)`. */ + fun allowedToolsOfMcp(mcp: List) = allowedTools(AllowedTools.ofMcp(mcp)) + + /** + * Alias for calling [allowedTools] with + * `AllowedTools.ofMcpToolFilter(mcpToolFilter)`. + */ + fun allowedTools(mcpToolFilter: AllowedTools.McpToolFilter) = + allowedTools(AllowedTools.ofMcpToolFilter(mcpToolFilter)) + + /** + * An OAuth access token that can be used with a remote MCP server, either with a + * custom MCP server URL or a service connector. Your application must handle the + * OAuth authorization flow and provide the token here. + */ + fun authorization(authorization: String) = + authorization(JsonField.of(authorization)) + + /** + * Sets [Builder.authorization] to an arbitrary JSON value. + * + * You should usually call [Builder.authorization] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun authorization(authorization: JsonField) = apply { + this.authorization = authorization + } + + /** + * Identifier for service connectors, like those available in ChatGPT. One of + * `server_url`, `connector_id`, or `tunnel_id` must be provided. Learn more about + * service connectors + * [here](https://developers.openai.com/api/docs/guides/tools-connectors-mcp#connectors). + * + * This field is deprecated for models released after September 1, 2026. Use + * `server_url` to connect to a remote MCP server, or `tunnel_id` to connect through + * a Secure MCP Tunnel. + * + * Currently supported `connector_id` values are: + * - Dropbox: `connector_dropbox` + * - Gmail: `connector_gmail` + * - Google Calendar: `connector_googlecalendar` + * - Google Drive: `connector_googledrive` + * - Microsoft Teams: `connector_microsoftteams` + * - Outlook Calendar: `connector_outlookcalendar` + * - Outlook Email: `connector_outlookemail` + * - SharePoint: `connector_sharepoint` + */ + @Deprecated("deprecated") + fun connectorId(connectorId: ConnectorId) = connectorId(JsonField.of(connectorId)) + + /** + * Sets [Builder.connectorId] to an arbitrary JSON value. + * + * You should usually call [Builder.connectorId] with a well-typed [ConnectorId] + * value instead. This method is primarily for setting the field to an undocumented + * or not yet supported value. + */ + @Deprecated("deprecated") + fun connectorId(connectorId: JsonField) = apply { + this.connectorId = connectorId + } + + /** Whether this MCP tool is deferred and discovered via tool search. */ + fun deferLoading(deferLoading: Boolean) = deferLoading(JsonField.of(deferLoading)) + + /** + * Sets [Builder.deferLoading] to an arbitrary JSON value. + * + * You should usually call [Builder.deferLoading] with a well-typed [Boolean] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun deferLoading(deferLoading: JsonField) = apply { + this.deferLoading = deferLoading + } + + /** + * Optional HTTP headers to send to the MCP server. Use for authentication or other + * purposes. + */ + fun headers(headers: Headers?) = headers(JsonField.ofNullable(headers)) + + /** Alias for calling [Builder.headers] with `headers.orElse(null)`. */ + fun headers(headers: Optional) = headers(headers.getOrNull()) + + /** + * Sets [Builder.headers] to an arbitrary JSON value. + * + * You should usually call [Builder.headers] with a well-typed [Headers] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun headers(headers: JsonField) = apply { this.headers = headers } + + /** Specify which of the MCP server's tools require approval. */ + fun requireApproval(requireApproval: RequireApproval?) = + requireApproval(JsonField.ofNullable(requireApproval)) + + /** + * Alias for calling [Builder.requireApproval] with `requireApproval.orElse(null)`. + */ + fun requireApproval(requireApproval: Optional) = + requireApproval(requireApproval.getOrNull()) + + /** + * Sets [Builder.requireApproval] to an arbitrary JSON value. + * + * You should usually call [Builder.requireApproval] with a well-typed + * [RequireApproval] value instead. This method is primarily for setting the field + * to an undocumented or not yet supported value. + */ + fun requireApproval(requireApproval: JsonField) = apply { + this.requireApproval = requireApproval + } + + /** + * Alias for calling [requireApproval] with + * `RequireApproval.ofMcpToolApprovalFilter(mcpToolApprovalFilter)`. + */ + fun requireApproval(mcpToolApprovalFilter: RequireApproval.McpToolApprovalFilter) = + requireApproval(RequireApproval.ofMcpToolApprovalFilter(mcpToolApprovalFilter)) + + /** + * Alias for calling [requireApproval] with + * `RequireApproval.ofMcpToolApprovalSetting(mcpToolApprovalSetting)`. + */ + fun requireApproval( + mcpToolApprovalSetting: RequireApproval.McpToolApprovalSetting + ) = + requireApproval( + RequireApproval.ofMcpToolApprovalSetting(mcpToolApprovalSetting) + ) + + /** Optional description of the MCP server, used to provide more context. */ + fun serverDescription(serverDescription: String) = + serverDescription(JsonField.of(serverDescription)) + + /** + * Sets [Builder.serverDescription] to an arbitrary JSON value. + * + * You should usually call [Builder.serverDescription] with a well-typed [String] + * value instead. This method is primarily for setting the field to an undocumented + * or not yet supported value. + */ + fun serverDescription(serverDescription: JsonField) = apply { + this.serverDescription = serverDescription + } + + /** + * The URL for the MCP server. One of `server_url`, `connector_id`, or `tunnel_id` + * must be provided. + */ + fun serverUrl(serverUrl: String) = serverUrl(JsonField.of(serverUrl)) + + /** + * Sets [Builder.serverUrl] to an arbitrary JSON value. + * + * You should usually call [Builder.serverUrl] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun serverUrl(serverUrl: JsonField) = apply { this.serverUrl = serverUrl } + + /** + * The Secure MCP Tunnel ID to use instead of a direct server URL. One of + * `server_url`, `connector_id`, or `tunnel_id` must be provided. + */ + fun tunnelId(tunnelId: String) = tunnelId(JsonField.of(tunnelId)) + + /** + * Sets [Builder.tunnelId] to an arbitrary JSON value. + * + * You should usually call [Builder.tunnelId] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun tunnelId(tunnelId: JsonField) = apply { this.tunnelId = tunnelId } + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = + apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { + additionalProperties.remove(key) + } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [Mcp]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .serverLabel() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): Mcp = + Mcp( + checkRequired("serverLabel", serverLabel), + type, + (allowedCallers ?: JsonMissing.of()).map { it.toImmutable() }, + allowedTools, + authorization, + connectorId, + deferLoading, + headers, + requireApproval, + serverDescription, + serverUrl, + tunnelId, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws OpenAIInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): Mcp = apply { + if (validated) { + return@apply + } + + serverLabel() + _type().let { + if (it != JsonValue.from("mcp")) { + throw OpenAIInvalidDataException("'type' is invalid, received $it") + } + } + allowedCallers().ifPresent { it.forEach { it.validate() } } + allowedTools().ifPresent { it.validate() } + authorization() + connectorId().ifPresent { it.validate() } + deferLoading() + headers().ifPresent { it.validate() } + requireApproval().ifPresent { it.validate() } + serverDescription() + serverUrl() + tunnelId() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: OpenAIInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + (if (serverLabel.asKnown().isPresent) 1 else 0) + + type.let { if (it == JsonValue.from("mcp")) 1 else 0 } + + (allowedCallers.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + + (allowedTools.asKnown().getOrNull()?.validity() ?: 0) + + (if (authorization.asKnown().isPresent) 1 else 0) + + (connectorId.asKnown().getOrNull()?.validity() ?: 0) + + (if (deferLoading.asKnown().isPresent) 1 else 0) + + (headers.asKnown().getOrNull()?.validity() ?: 0) + + (requireApproval.asKnown().getOrNull()?.validity() ?: 0) + + (if (serverDescription.asKnown().isPresent) 1 else 0) + + (if (serverUrl.asKnown().isPresent) 1 else 0) + + (if (tunnelId.asKnown().isPresent) 1 else 0) + + class AllowedCaller + @JsonCreator + private constructor(private val value: JsonField) : Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that + * doesn't match any known member, and you want to know that value. For example, if + * the SDK is on an older version than the API, then the API may respond with new + * members that the SDK is unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val DIRECT = of("direct") + + @JvmField val PROGRAMMATIC = of("programmatic") + + @JvmStatic fun of(value: String) = AllowedCaller(JsonField.of(value)) + } + + /** An enum containing [AllowedCaller]'s known values. */ + enum class Known { + DIRECT, + PROGRAMMATIC, + } + + /** + * An enum containing [AllowedCaller]'s known values, as well as an [_UNKNOWN] + * member. + * + * An instance of [AllowedCaller] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, + * if the SDK is on an older version than the API, then the API may respond with + * new members that the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + DIRECT, + PROGRAMMATIC, + /** + * An enum member indicating that [AllowedCaller] was instantiated with an + * unknown value. + */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or + * [Value._UNKNOWN] if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if + * you want to throw for the unknown case. + */ + fun value(): Value = + when (this) { + DIRECT -> Value.DIRECT + PROGRAMMATIC -> Value.PROGRAMMATIC + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and + * don't want to throw for the unknown case. + * + * @throws OpenAIInvalidDataException if this class instance's value is a not a + * known member. + */ + fun known(): Known = + when (this) { + DIRECT -> Known.DIRECT + PROGRAMMATIC -> Known.PROGRAMMATIC + else -> throw OpenAIInvalidDataException("Unknown AllowedCaller: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for + * debugging and generally doesn't throw. + * + * @throws OpenAIInvalidDataException if this class instance's value does not have + * the expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { + OpenAIInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws OpenAIInvalidDataException if any value type in this object doesn't match + * its expected type. + */ + fun validate(): AllowedCaller = apply { + if (validated) { + return@apply + } + + known() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: OpenAIInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is AllowedCaller && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + /** List of allowed tool names or a filter object. */ + @JsonDeserialize(using = AllowedTools.Deserializer::class) + @JsonSerialize(using = AllowedTools.Serializer::class) + class AllowedTools + private constructor( + private val mcp: List? = null, + private val mcpToolFilter: McpToolFilter? = null, + private val _json: JsonValue? = null, + ) { + + /** A string array of allowed tool names */ + fun mcp(): Optional> = Optional.ofNullable(mcp) + + /** A filter object to specify which tools are allowed. */ + fun mcpToolFilter(): Optional = Optional.ofNullable(mcpToolFilter) + + fun isMcp(): Boolean = mcp != null + + fun isMcpToolFilter(): Boolean = mcpToolFilter != null + + /** A string array of allowed tool names */ + fun asMcp(): List = mcp.getOrThrow("mcp") + + /** A filter object to specify which tools are allowed. */ + fun asMcpToolFilter(): McpToolFilter = mcpToolFilter.getOrThrow("mcpToolFilter") + + fun _json(): Optional = Optional.ofNullable(_json) + + /** + * Maps this instance's current variant to a value of type [T] using the given + * [visitor]. + * + * Note that this method is _not_ forwards compatible with new variants from the + * API, unless [visitor] overrides [Visitor.unknown]. To handle variants not known + * to this version of the SDK gracefully, consider overriding [Visitor.unknown]: + * ```java + * import com.openai.core.JsonValue; + * import java.util.Optional; + * + * Optional result = allowedTools.accept(new AllowedTools.Visitor>() { + * @Override + * public Optional visitMcp(List mcp) { + * return Optional.of(mcp.toString()); + * } + * + * // ... + * + * @Override + * public Optional unknown(JsonValue json) { + * // Or inspect the `json`. + * return Optional.empty(); + * } + * }); + * ``` + * + * @throws OpenAIInvalidDataException if [Visitor.unknown] is not overridden in + * [visitor] and the current variant is unknown. + */ + fun accept(visitor: Visitor): T = + when { + mcp != null -> visitor.visitMcp(mcp) + mcpToolFilter != null -> visitor.visitMcpToolFilter(mcpToolFilter) + else -> visitor.unknown(_json) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws OpenAIInvalidDataException if any value type in this object doesn't match + * its expected type. + */ + fun validate(): AllowedTools = apply { + if (validated) { + return@apply + } + + accept( + object : Visitor { + override fun visitMcp(mcp: List) {} + + override fun visitMcpToolFilter(mcpToolFilter: McpToolFilter) { + mcpToolFilter.validate() + } + } + ) + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: OpenAIInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + accept( + object : Visitor { + override fun visitMcp(mcp: List) = mcp.size + + override fun visitMcpToolFilter(mcpToolFilter: McpToolFilter) = + mcpToolFilter.validity() + + override fun unknown(json: JsonValue?) = 0 + } + ) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is AllowedTools && + mcp == other.mcp && + mcpToolFilter == other.mcpToolFilter + } + + override fun hashCode(): Int = Objects.hash(mcp, mcpToolFilter) + + override fun toString(): String = + when { + mcp != null -> "AllowedTools{mcp=$mcp}" + mcpToolFilter != null -> "AllowedTools{mcpToolFilter=$mcpToolFilter}" + _json != null -> "AllowedTools{_unknown=$_json}" + else -> throw IllegalStateException("Invalid AllowedTools") + } + + companion object { + + /** A string array of allowed tool names */ + @JvmStatic fun ofMcp(mcp: List) = AllowedTools(mcp = mcp.toImmutable()) + + /** A filter object to specify which tools are allowed. */ + @JvmStatic + fun ofMcpToolFilter(mcpToolFilter: McpToolFilter) = + AllowedTools(mcpToolFilter = mcpToolFilter) + } + + /** + * An interface that defines how to map each variant of [AllowedTools] to a value of + * type [T]. + */ + interface Visitor { + + /** A string array of allowed tool names */ + fun visitMcp(mcp: List): T + + /** A filter object to specify which tools are allowed. */ + fun visitMcpToolFilter(mcpToolFilter: McpToolFilter): T + + /** + * Maps an unknown variant of [AllowedTools] to a value of type [T]. + * + * An instance of [AllowedTools] can contain an unknown variant if it was + * deserialized from data that doesn't match any known variant. For example, if + * the SDK is on an older version than the API, then the API may respond with + * new variants that the SDK is unaware of. + * + * @throws OpenAIInvalidDataException in the default implementation. + */ + fun unknown(json: JsonValue?): T { + throw OpenAIInvalidDataException("Unknown AllowedTools") + } + } + + internal class Deserializer : BaseDeserializer(AllowedTools::class) { + + override fun ObjectCodec.deserialize(node: JsonNode): AllowedTools { + val json = JsonValue.fromJsonNode(node) + + val bestMatches = + sequenceOf( + tryDeserialize(node, jacksonTypeRef())?.let { + AllowedTools(mcpToolFilter = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef>())?.let { + AllowedTools(mcp = it, _json = json) + }, + ) + .filterNotNull() + .allMaxBy { it.validity() } + .toList() + return when (bestMatches.size) { + // This can happen if what we're deserializing is completely + // incompatible with all the possible variants (e.g. deserializing from + // boolean). + 0 -> AllowedTools(_json = json) + 1 -> bestMatches.single() + // If there's more than one match with the highest validity, then use + // the first completely valid match, or simply the first match if none + // are completely valid. + else -> bestMatches.firstOrNull { it.isValid() } ?: bestMatches.first() + } + } + } + + internal class Serializer : BaseSerializer(AllowedTools::class) { + + override fun serialize( + value: AllowedTools, + generator: JsonGenerator, + provider: SerializerProvider, + ) { + when { + value.mcp != null -> generator.writeObject(value.mcp) + value.mcpToolFilter != null -> + generator.writeObject(value.mcpToolFilter) + value._json != null -> generator.writeObject(value._json) + else -> throw IllegalStateException("Invalid AllowedTools") + } + } + } + + /** A filter object to specify which tools are allowed. */ + class McpToolFilter + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val readOnly: JsonField, + private val toolNames: JsonField>, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("read_only") + @ExcludeMissing + readOnly: JsonField = JsonMissing.of(), + @JsonProperty("tool_names") + @ExcludeMissing + toolNames: JsonField> = JsonMissing.of(), + ) : this(readOnly, toolNames, mutableMapOf()) + + /** + * Indicates whether or not a tool modifies data or is read-only. If an MCP + * server is + * [annotated with `readOnlyHint`](https://modelcontextprotocol.io/specification/2025-06-18/schema#toolannotations-readonlyhint), + * it will match this filter. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun readOnly(): Optional = readOnly.getOptional("read_only") + + /** + * List of allowed tool names. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun toolNames(): Optional> = toolNames.getOptional("tool_names") + + /** + * Returns the raw JSON value of [readOnly]. + * + * Unlike [readOnly], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("read_only") + @ExcludeMissing + fun _readOnly(): JsonField = readOnly + + /** + * Returns the raw JSON value of [toolNames]. + * + * Unlike [toolNames], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("tool_names") + @ExcludeMissing + fun _toolNames(): JsonField> = toolNames + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of + * [McpToolFilter]. + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [McpToolFilter]. */ + class Builder internal constructor() { + + private var readOnly: JsonField = JsonMissing.of() + private var toolNames: JsonField>? = null + private var additionalProperties: MutableMap = + mutableMapOf() + + @JvmSynthetic + internal fun from(mcpToolFilter: McpToolFilter) = apply { + readOnly = mcpToolFilter.readOnly + toolNames = mcpToolFilter.toolNames.map { it.toMutableList() } + additionalProperties = mcpToolFilter.additionalProperties.toMutableMap() + } + + /** + * Indicates whether or not a tool modifies data or is read-only. If an MCP + * server is + * [annotated with `readOnlyHint`](https://modelcontextprotocol.io/specification/2025-06-18/schema#toolannotations-readonlyhint), + * it will match this filter. + */ + fun readOnly(readOnly: Boolean) = readOnly(JsonField.of(readOnly)) + + /** + * Sets [Builder.readOnly] to an arbitrary JSON value. + * + * You should usually call [Builder.readOnly] with a well-typed [Boolean] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun readOnly(readOnly: JsonField) = apply { + this.readOnly = readOnly + } + + /** List of allowed tool names. */ + fun toolNames(toolNames: List) = toolNames(JsonField.of(toolNames)) + + /** + * Sets [Builder.toolNames] to an arbitrary JSON value. + * + * You should usually call [Builder.toolNames] with a well-typed + * `List` value instead. This method is primarily for setting the + * field to an undocumented or not yet supported value. + */ + fun toolNames(toolNames: JsonField>) = apply { + this.toolNames = toolNames.map { it.toMutableList() } + } + + /** + * Adds a single [String] to [toolNames]. + * + * @throws IllegalStateException if the field was previously set to a + * non-list. + */ + fun addToolName(toolName: String) = apply { + toolNames = + (toolNames ?: JsonField.of(mutableListOf())).also { + checkKnown("toolNames", it).add(toolName) + } + } + + fun additionalProperties(additionalProperties: Map) = + apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties( + additionalProperties: Map + ) = apply { this.additionalProperties.putAll(additionalProperties) } + + fun removeAdditionalProperty(key: String) = apply { + additionalProperties.remove(key) + } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [McpToolFilter]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): McpToolFilter = + McpToolFilter( + readOnly, + (toolNames ?: JsonMissing.of()).map { it.toImmutable() }, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected + * types recursively. + * + * This method is _not_ forwards compatible with new types from the API for + * existing fields. + * + * @throws OpenAIInvalidDataException if any value type in this object doesn't + * match its expected type. + */ + fun validate(): McpToolFilter = apply { + if (validated) { + return@apply + } + + readOnly() + toolNames() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: OpenAIInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + (if (readOnly.asKnown().isPresent) 1 else 0) + + (toolNames.asKnown().getOrNull()?.size ?: 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is McpToolFilter && + readOnly == other.readOnly && + toolNames == other.toolNames && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(readOnly, toolNames, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "McpToolFilter{readOnly=$readOnly, toolNames=$toolNames, additionalProperties=$additionalProperties}" + } + } + + /** + * Identifier for service connectors, like those available in ChatGPT. One of + * `server_url`, `connector_id`, or `tunnel_id` must be provided. Learn more about + * service connectors + * [here](https://developers.openai.com/api/docs/guides/tools-connectors-mcp#connectors). + * + * This field is deprecated for models released after September 1, 2026. Use + * `server_url` to connect to a remote MCP server, or `tunnel_id` to connect through a + * Secure MCP Tunnel. + * + * Currently supported `connector_id` values are: + * - Dropbox: `connector_dropbox` + * - Gmail: `connector_gmail` + * - Google Calendar: `connector_googlecalendar` + * - Google Drive: `connector_googledrive` + * - Microsoft Teams: `connector_microsoftteams` + * - Outlook Calendar: `connector_outlookcalendar` + * - Outlook Email: `connector_outlookemail` + * - SharePoint: `connector_sharepoint` + */ + @Deprecated("deprecated") + class ConnectorId + @JsonCreator + private constructor(private val value: JsonField) : Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that + * doesn't match any known member, and you want to know that value. For example, if + * the SDK is on an older version than the API, then the API may respond with new + * members that the SDK is unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val CONNECTOR_DROPBOX = of("connector_dropbox") + + @JvmField val CONNECTOR_GMAIL = of("connector_gmail") + + @JvmField val CONNECTOR_GOOGLECALENDAR = of("connector_googlecalendar") + + @JvmField val CONNECTOR_GOOGLEDRIVE = of("connector_googledrive") + + @JvmField val CONNECTOR_MICROSOFTTEAMS = of("connector_microsoftteams") + + @JvmField val CONNECTOR_OUTLOOKCALENDAR = of("connector_outlookcalendar") + + @JvmField val CONNECTOR_OUTLOOKEMAIL = of("connector_outlookemail") + + @JvmField val CONNECTOR_SHAREPOINT = of("connector_sharepoint") + + @JvmStatic fun of(value: String) = ConnectorId(JsonField.of(value)) + } + + /** An enum containing [ConnectorId]'s known values. */ + enum class Known { + CONNECTOR_DROPBOX, + CONNECTOR_GMAIL, + CONNECTOR_GOOGLECALENDAR, + CONNECTOR_GOOGLEDRIVE, + CONNECTOR_MICROSOFTTEAMS, + CONNECTOR_OUTLOOKCALENDAR, + CONNECTOR_OUTLOOKEMAIL, + CONNECTOR_SHAREPOINT, + } + + /** + * An enum containing [ConnectorId]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [ConnectorId] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, + * if the SDK is on an older version than the API, then the API may respond with + * new members that the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + CONNECTOR_DROPBOX, + CONNECTOR_GMAIL, + CONNECTOR_GOOGLECALENDAR, + CONNECTOR_GOOGLEDRIVE, + CONNECTOR_MICROSOFTTEAMS, + CONNECTOR_OUTLOOKCALENDAR, + CONNECTOR_OUTLOOKEMAIL, + CONNECTOR_SHAREPOINT, + /** + * An enum member indicating that [ConnectorId] was instantiated with an unknown + * value. + */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or + * [Value._UNKNOWN] if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if + * you want to throw for the unknown case. + */ + fun value(): Value = + when (this) { + CONNECTOR_DROPBOX -> Value.CONNECTOR_DROPBOX + CONNECTOR_GMAIL -> Value.CONNECTOR_GMAIL + CONNECTOR_GOOGLECALENDAR -> Value.CONNECTOR_GOOGLECALENDAR + CONNECTOR_GOOGLEDRIVE -> Value.CONNECTOR_GOOGLEDRIVE + CONNECTOR_MICROSOFTTEAMS -> Value.CONNECTOR_MICROSOFTTEAMS + CONNECTOR_OUTLOOKCALENDAR -> Value.CONNECTOR_OUTLOOKCALENDAR + CONNECTOR_OUTLOOKEMAIL -> Value.CONNECTOR_OUTLOOKEMAIL + CONNECTOR_SHAREPOINT -> Value.CONNECTOR_SHAREPOINT + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and + * don't want to throw for the unknown case. + * + * @throws OpenAIInvalidDataException if this class instance's value is a not a + * known member. + */ + fun known(): Known = + when (this) { + CONNECTOR_DROPBOX -> Known.CONNECTOR_DROPBOX + CONNECTOR_GMAIL -> Known.CONNECTOR_GMAIL + CONNECTOR_GOOGLECALENDAR -> Known.CONNECTOR_GOOGLECALENDAR + CONNECTOR_GOOGLEDRIVE -> Known.CONNECTOR_GOOGLEDRIVE + CONNECTOR_MICROSOFTTEAMS -> Known.CONNECTOR_MICROSOFTTEAMS + CONNECTOR_OUTLOOKCALENDAR -> Known.CONNECTOR_OUTLOOKCALENDAR + CONNECTOR_OUTLOOKEMAIL -> Known.CONNECTOR_OUTLOOKEMAIL + CONNECTOR_SHAREPOINT -> Known.CONNECTOR_SHAREPOINT + else -> throw OpenAIInvalidDataException("Unknown ConnectorId: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for + * debugging and generally doesn't throw. + * + * @throws OpenAIInvalidDataException if this class instance's value does not have + * the expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { + OpenAIInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws OpenAIInvalidDataException if any value type in this object doesn't match + * its expected type. + */ + fun validate(): ConnectorId = apply { + if (validated) { + return@apply + } + + known() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: OpenAIInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is ConnectorId && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + /** + * Optional HTTP headers to send to the MCP server. Use for authentication or other + * purposes. + */ + class Headers + @JsonCreator + private constructor( + @com.fasterxml.jackson.annotation.JsonValue + private val additionalProperties: Map + ) { + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = additionalProperties + + fun toBuilder() = Builder().from(this) + + companion object { + + /** Returns a mutable builder for constructing an instance of [Headers]. */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Headers]. */ + class Builder internal constructor() { + + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(headers: Headers) = apply { + additionalProperties = headers.additionalProperties.toMutableMap() + } + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + /** Adds a string-valued property. */ + fun putProperty(key: String, value: String) = apply { + putAdditionalProperty(key, JsonValue.from(value)) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = + apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { + additionalProperties.remove(key) + } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [Headers]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): Headers = Headers(additionalProperties.toImmutable()) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws OpenAIInvalidDataException if any value type in this object doesn't match + * its expected type. + */ + fun validate(): Headers = apply { + if (validated) { + return@apply + } + + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: OpenAIInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + additionalProperties.count { (_, value) -> + !value.isNull() && !value.isMissing() + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Headers && additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(additionalProperties) } + + override fun hashCode(): Int = hashCode + + override fun toString() = "Headers{additionalProperties=$additionalProperties}" + } + + /** Specify which of the MCP server's tools require approval. */ + @JsonDeserialize(using = RequireApproval.Deserializer::class) + @JsonSerialize(using = RequireApproval.Serializer::class) + class RequireApproval + private constructor( + private val mcpToolApprovalFilter: McpToolApprovalFilter? = null, + private val mcpToolApprovalSetting: McpToolApprovalSetting? = null, + private val _json: JsonValue? = null, + ) { + + /** + * Specify which of the MCP server's tools require approval. Can be `always`, + * `never`, or a filter object associated with tools that require approval. + */ + fun mcpToolApprovalFilter(): Optional = + Optional.ofNullable(mcpToolApprovalFilter) + + /** + * Specify a single approval policy for all tools. One of `always` or `never`. When + * set to `always`, all tools will require approval. When set to `never`, all tools + * will not require approval. + */ + fun mcpToolApprovalSetting(): Optional = + Optional.ofNullable(mcpToolApprovalSetting) + + fun isMcpToolApprovalFilter(): Boolean = mcpToolApprovalFilter != null + + fun isMcpToolApprovalSetting(): Boolean = mcpToolApprovalSetting != null + + /** + * Specify which of the MCP server's tools require approval. Can be `always`, + * `never`, or a filter object associated with tools that require approval. + */ + fun asMcpToolApprovalFilter(): McpToolApprovalFilter = + mcpToolApprovalFilter.getOrThrow("mcpToolApprovalFilter") + + /** + * Specify a single approval policy for all tools. One of `always` or `never`. When + * set to `always`, all tools will require approval. When set to `never`, all tools + * will not require approval. + */ + fun asMcpToolApprovalSetting(): McpToolApprovalSetting = + mcpToolApprovalSetting.getOrThrow("mcpToolApprovalSetting") + + fun _json(): Optional = Optional.ofNullable(_json) + + /** + * Maps this instance's current variant to a value of type [T] using the given + * [visitor]. + * + * Note that this method is _not_ forwards compatible with new variants from the + * API, unless [visitor] overrides [Visitor.unknown]. To handle variants not known + * to this version of the SDK gracefully, consider overriding [Visitor.unknown]: + * ```java + * import com.openai.core.JsonValue; + * import java.util.Optional; + * + * Optional result = requireApproval.accept(new RequireApproval.Visitor>() { + * @Override + * public Optional visitMcpToolApprovalFilter(McpToolApprovalFilter mcpToolApprovalFilter) { + * return Optional.of(mcpToolApprovalFilter.toString()); + * } + * + * // ... + * + * @Override + * public Optional unknown(JsonValue json) { + * // Or inspect the `json`. + * return Optional.empty(); + * } + * }); + * ``` + * + * @throws OpenAIInvalidDataException if [Visitor.unknown] is not overridden in + * [visitor] and the current variant is unknown. + */ + fun accept(visitor: Visitor): T = + when { + mcpToolApprovalFilter != null -> + visitor.visitMcpToolApprovalFilter(mcpToolApprovalFilter) + mcpToolApprovalSetting != null -> + visitor.visitMcpToolApprovalSetting(mcpToolApprovalSetting) + else -> visitor.unknown(_json) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws OpenAIInvalidDataException if any value type in this object doesn't match + * its expected type. + */ + fun validate(): RequireApproval = apply { + if (validated) { + return@apply + } + + accept( + object : Visitor { + override fun visitMcpToolApprovalFilter( + mcpToolApprovalFilter: McpToolApprovalFilter + ) { + mcpToolApprovalFilter.validate() + } + + override fun visitMcpToolApprovalSetting( + mcpToolApprovalSetting: McpToolApprovalSetting + ) { + mcpToolApprovalSetting.validate() + } + } + ) + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: OpenAIInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + accept( + object : Visitor { + override fun visitMcpToolApprovalFilter( + mcpToolApprovalFilter: McpToolApprovalFilter + ) = mcpToolApprovalFilter.validity() + + override fun visitMcpToolApprovalSetting( + mcpToolApprovalSetting: McpToolApprovalSetting + ) = mcpToolApprovalSetting.validity() + + override fun unknown(json: JsonValue?) = 0 + } + ) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is RequireApproval && + mcpToolApprovalFilter == other.mcpToolApprovalFilter && + mcpToolApprovalSetting == other.mcpToolApprovalSetting + } + + override fun hashCode(): Int = + Objects.hash(mcpToolApprovalFilter, mcpToolApprovalSetting) + + override fun toString(): String = + when { + mcpToolApprovalFilter != null -> + "RequireApproval{mcpToolApprovalFilter=$mcpToolApprovalFilter}" + mcpToolApprovalSetting != null -> + "RequireApproval{mcpToolApprovalSetting=$mcpToolApprovalSetting}" + _json != null -> "RequireApproval{_unknown=$_json}" + else -> throw IllegalStateException("Invalid RequireApproval") + } + + companion object { + + /** + * Specify which of the MCP server's tools require approval. Can be `always`, + * `never`, or a filter object associated with tools that require approval. + */ + @JvmStatic + fun ofMcpToolApprovalFilter(mcpToolApprovalFilter: McpToolApprovalFilter) = + RequireApproval(mcpToolApprovalFilter = mcpToolApprovalFilter) + + /** + * Specify a single approval policy for all tools. One of `always` or `never`. + * When set to `always`, all tools will require approval. When set to `never`, + * all tools will not require approval. + */ + @JvmStatic + fun ofMcpToolApprovalSetting(mcpToolApprovalSetting: McpToolApprovalSetting) = + RequireApproval(mcpToolApprovalSetting = mcpToolApprovalSetting) + } + + /** + * An interface that defines how to map each variant of [RequireApproval] to a value + * of type [T]. + */ + interface Visitor { + + /** + * Specify which of the MCP server's tools require approval. Can be `always`, + * `never`, or a filter object associated with tools that require approval. + */ + fun visitMcpToolApprovalFilter(mcpToolApprovalFilter: McpToolApprovalFilter): T + + /** + * Specify a single approval policy for all tools. One of `always` or `never`. + * When set to `always`, all tools will require approval. When set to `never`, + * all tools will not require approval. + */ + fun visitMcpToolApprovalSetting( + mcpToolApprovalSetting: McpToolApprovalSetting + ): T + + /** + * Maps an unknown variant of [RequireApproval] to a value of type [T]. + * + * An instance of [RequireApproval] can contain an unknown variant if it was + * deserialized from data that doesn't match any known variant. For example, if + * the SDK is on an older version than the API, then the API may respond with + * new variants that the SDK is unaware of. + * + * @throws OpenAIInvalidDataException in the default implementation. + */ + fun unknown(json: JsonValue?): T { + throw OpenAIInvalidDataException("Unknown RequireApproval") + } + } + + internal class Deserializer : + BaseDeserializer(RequireApproval::class) { + + override fun ObjectCodec.deserialize(node: JsonNode): RequireApproval { + val json = JsonValue.fromJsonNode(node) + + val bestMatches = + sequenceOf( + tryDeserialize(node, jacksonTypeRef()) + ?.let { + RequireApproval( + mcpToolApprovalFilter = it, + _json = json, + ) + }, + tryDeserialize(node, jacksonTypeRef()) + ?.let { + RequireApproval( + mcpToolApprovalSetting = it, + _json = json, + ) + }, + ) + .filterNotNull() + .allMaxBy { it.validity() } + .toList() + return when (bestMatches.size) { + // This can happen if what we're deserializing is completely + // incompatible with all the possible variants (e.g. deserializing from + // boolean). + 0 -> RequireApproval(_json = json) + 1 -> bestMatches.single() + // If there's more than one match with the highest validity, then use + // the first completely valid match, or simply the first match if none + // are completely valid. + else -> bestMatches.firstOrNull { it.isValid() } ?: bestMatches.first() + } + } + } + + internal class Serializer : + BaseSerializer(RequireApproval::class) { + + override fun serialize( + value: RequireApproval, + generator: JsonGenerator, + provider: SerializerProvider, + ) { + when { + value.mcpToolApprovalFilter != null -> + generator.writeObject(value.mcpToolApprovalFilter) + value.mcpToolApprovalSetting != null -> + generator.writeObject(value.mcpToolApprovalSetting) + value._json != null -> generator.writeObject(value._json) + else -> throw IllegalStateException("Invalid RequireApproval") + } + } + } + + /** + * Specify which of the MCP server's tools require approval. Can be `always`, + * `never`, or a filter object associated with tools that require approval. + */ + class McpToolApprovalFilter + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val always: JsonField, + private val never: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("always") + @ExcludeMissing + always: JsonField = JsonMissing.of(), + @JsonProperty("never") + @ExcludeMissing + never: JsonField = JsonMissing.of(), + ) : this(always, never, mutableMapOf()) + + /** + * A filter object to specify which tools are allowed. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun always(): Optional = always.getOptional("always") + + /** + * A filter object to specify which tools are allowed. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun never(): Optional = never.getOptional("never") + + /** + * Returns the raw JSON value of [always]. + * + * Unlike [always], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("always") + @ExcludeMissing + fun _always(): JsonField = always + + /** + * Returns the raw JSON value of [never]. + * + * Unlike [never], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("never") @ExcludeMissing fun _never(): JsonField = never + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of + * [McpToolApprovalFilter]. + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [McpToolApprovalFilter]. */ + class Builder internal constructor() { + + private var always: JsonField = JsonMissing.of() + private var never: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = + mutableMapOf() + + @JvmSynthetic + internal fun from(mcpToolApprovalFilter: McpToolApprovalFilter) = apply { + always = mcpToolApprovalFilter.always + never = mcpToolApprovalFilter.never + additionalProperties = + mcpToolApprovalFilter.additionalProperties.toMutableMap() + } + + /** A filter object to specify which tools are allowed. */ + fun always(always: Always) = always(JsonField.of(always)) + + /** + * Sets [Builder.always] to an arbitrary JSON value. + * + * You should usually call [Builder.always] with a well-typed [Always] value + * instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun always(always: JsonField) = apply { this.always = always } + + /** A filter object to specify which tools are allowed. */ + fun never(never: Never) = never(JsonField.of(never)) + + /** + * Sets [Builder.never] to an arbitrary JSON value. + * + * You should usually call [Builder.never] with a well-typed [Never] value + * instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun never(never: JsonField) = apply { this.never = never } + + fun additionalProperties(additionalProperties: Map) = + apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties( + additionalProperties: Map + ) = apply { this.additionalProperties.putAll(additionalProperties) } + + fun removeAdditionalProperty(key: String) = apply { + additionalProperties.remove(key) + } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [McpToolApprovalFilter]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): McpToolApprovalFilter = + McpToolApprovalFilter( + always, + never, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected + * types recursively. + * + * This method is _not_ forwards compatible with new types from the API for + * existing fields. + * + * @throws OpenAIInvalidDataException if any value type in this object doesn't + * match its expected type. + */ + fun validate(): McpToolApprovalFilter = apply { + if (validated) { + return@apply + } + + always().ifPresent { it.validate() } + never().ifPresent { it.validate() } + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: OpenAIInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + (always.asKnown().getOrNull()?.validity() ?: 0) + + (never.asKnown().getOrNull()?.validity() ?: 0) + + /** A filter object to specify which tools are allowed. */ + class Always + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val readOnly: JsonField, + private val toolNames: JsonField>, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("read_only") + @ExcludeMissing + readOnly: JsonField = JsonMissing.of(), + @JsonProperty("tool_names") + @ExcludeMissing + toolNames: JsonField> = JsonMissing.of(), + ) : this(readOnly, toolNames, mutableMapOf()) + + /** + * Indicates whether or not a tool modifies data or is read-only. If an MCP + * server is + * [annotated with `readOnlyHint`](https://modelcontextprotocol.io/specification/2025-06-18/schema#toolannotations-readonlyhint), + * it will match this filter. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun readOnly(): Optional = readOnly.getOptional("read_only") + + /** + * List of allowed tool names. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun toolNames(): Optional> = + toolNames.getOptional("tool_names") + + /** + * Returns the raw JSON value of [readOnly]. + * + * Unlike [readOnly], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("read_only") + @ExcludeMissing + fun _readOnly(): JsonField = readOnly + + /** + * Returns the raw JSON value of [toolNames]. + * + * Unlike [toolNames], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("tool_names") + @ExcludeMissing + fun _toolNames(): JsonField> = toolNames + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [Always]. + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Always]. */ + class Builder internal constructor() { + + private var readOnly: JsonField = JsonMissing.of() + private var toolNames: JsonField>? = null + private var additionalProperties: MutableMap = + mutableMapOf() + + @JvmSynthetic + internal fun from(always: Always) = apply { + readOnly = always.readOnly + toolNames = always.toolNames.map { it.toMutableList() } + additionalProperties = always.additionalProperties.toMutableMap() + } + + /** + * Indicates whether or not a tool modifies data or is read-only. If an + * MCP server is + * [annotated with `readOnlyHint`](https://modelcontextprotocol.io/specification/2025-06-18/schema#toolannotations-readonlyhint), + * it will match this filter. + */ + fun readOnly(readOnly: Boolean) = readOnly(JsonField.of(readOnly)) + + /** + * Sets [Builder.readOnly] to an arbitrary JSON value. + * + * You should usually call [Builder.readOnly] with a well-typed + * [Boolean] value instead. This method is primarily for setting the + * field to an undocumented or not yet supported value. + */ + fun readOnly(readOnly: JsonField) = apply { + this.readOnly = readOnly + } + + /** List of allowed tool names. */ + fun toolNames(toolNames: List) = + toolNames(JsonField.of(toolNames)) + + /** + * Sets [Builder.toolNames] to an arbitrary JSON value. + * + * You should usually call [Builder.toolNames] with a well-typed + * `List` value instead. This method is primarily for setting + * the field to an undocumented or not yet supported value. + */ + fun toolNames(toolNames: JsonField>) = apply { + this.toolNames = toolNames.map { it.toMutableList() } + } + + /** + * Adds a single [String] to [toolNames]. + * + * @throws IllegalStateException if the field was previously set to a + * non-list. + */ + fun addToolName(toolName: String) = apply { + toolNames = + (toolNames ?: JsonField.of(mutableListOf())).also { + checkKnown("toolNames", it).add(toolName) + } + } + + fun additionalProperties(additionalProperties: Map) = + apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties( + additionalProperties: Map + ) = apply { this.additionalProperties.putAll(additionalProperties) } + + fun removeAdditionalProperty(key: String) = apply { + additionalProperties.remove(key) + } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [Always]. + * + * Further updates to this [Builder] will not mutate the returned + * instance. + */ + fun build(): Always = + Always( + readOnly, + (toolNames ?: JsonMissing.of()).map { it.toImmutable() }, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their + * expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for + * existing fields. + * + * @throws OpenAIInvalidDataException if any value type in this object + * doesn't match its expected type. + */ + fun validate(): Always = apply { + if (validated) { + return@apply + } + + readOnly() + toolNames() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: OpenAIInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this + * object recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + (if (readOnly.asKnown().isPresent) 1 else 0) + + (toolNames.asKnown().getOrNull()?.size ?: 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Always && + readOnly == other.readOnly && + toolNames == other.toolNames && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(readOnly, toolNames, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Always{readOnly=$readOnly, toolNames=$toolNames, additionalProperties=$additionalProperties}" + } + + /** A filter object to specify which tools are allowed. */ + class Never + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val readOnly: JsonField, + private val toolNames: JsonField>, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("read_only") + @ExcludeMissing + readOnly: JsonField = JsonMissing.of(), + @JsonProperty("tool_names") + @ExcludeMissing + toolNames: JsonField> = JsonMissing.of(), + ) : this(readOnly, toolNames, mutableMapOf()) + + /** + * Indicates whether or not a tool modifies data or is read-only. If an MCP + * server is + * [annotated with `readOnlyHint`](https://modelcontextprotocol.io/specification/2025-06-18/schema#toolannotations-readonlyhint), + * it will match this filter. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun readOnly(): Optional = readOnly.getOptional("read_only") + + /** + * List of allowed tool names. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun toolNames(): Optional> = + toolNames.getOptional("tool_names") + + /** + * Returns the raw JSON value of [readOnly]. + * + * Unlike [readOnly], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("read_only") + @ExcludeMissing + fun _readOnly(): JsonField = readOnly + + /** + * Returns the raw JSON value of [toolNames]. + * + * Unlike [toolNames], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("tool_names") + @ExcludeMissing + fun _toolNames(): JsonField> = toolNames + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [Never]. + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Never]. */ + class Builder internal constructor() { + + private var readOnly: JsonField = JsonMissing.of() + private var toolNames: JsonField>? = null + private var additionalProperties: MutableMap = + mutableMapOf() + + @JvmSynthetic + internal fun from(never: Never) = apply { + readOnly = never.readOnly + toolNames = never.toolNames.map { it.toMutableList() } + additionalProperties = never.additionalProperties.toMutableMap() + } + + /** + * Indicates whether or not a tool modifies data or is read-only. If an + * MCP server is + * [annotated with `readOnlyHint`](https://modelcontextprotocol.io/specification/2025-06-18/schema#toolannotations-readonlyhint), + * it will match this filter. + */ + fun readOnly(readOnly: Boolean) = readOnly(JsonField.of(readOnly)) + + /** + * Sets [Builder.readOnly] to an arbitrary JSON value. + * + * You should usually call [Builder.readOnly] with a well-typed + * [Boolean] value instead. This method is primarily for setting the + * field to an undocumented or not yet supported value. + */ + fun readOnly(readOnly: JsonField) = apply { + this.readOnly = readOnly + } + + /** List of allowed tool names. */ + fun toolNames(toolNames: List) = + toolNames(JsonField.of(toolNames)) + + /** + * Sets [Builder.toolNames] to an arbitrary JSON value. + * + * You should usually call [Builder.toolNames] with a well-typed + * `List` value instead. This method is primarily for setting + * the field to an undocumented or not yet supported value. + */ + fun toolNames(toolNames: JsonField>) = apply { + this.toolNames = toolNames.map { it.toMutableList() } + } + + /** + * Adds a single [String] to [toolNames]. + * + * @throws IllegalStateException if the field was previously set to a + * non-list. + */ + fun addToolName(toolName: String) = apply { + toolNames = + (toolNames ?: JsonField.of(mutableListOf())).also { + checkKnown("toolNames", it).add(toolName) + } + } + + fun additionalProperties(additionalProperties: Map) = + apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties( + additionalProperties: Map + ) = apply { this.additionalProperties.putAll(additionalProperties) } + + fun removeAdditionalProperty(key: String) = apply { + additionalProperties.remove(key) + } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [Never]. + * + * Further updates to this [Builder] will not mutate the returned + * instance. + */ + fun build(): Never = + Never( + readOnly, + (toolNames ?: JsonMissing.of()).map { it.toImmutable() }, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their + * expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for + * existing fields. + * + * @throws OpenAIInvalidDataException if any value type in this object + * doesn't match its expected type. + */ + fun validate(): Never = apply { + if (validated) { + return@apply + } + + readOnly() + toolNames() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: OpenAIInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this + * object recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + (if (readOnly.asKnown().isPresent) 1 else 0) + + (toolNames.asKnown().getOrNull()?.size ?: 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Never && + readOnly == other.readOnly && + toolNames == other.toolNames && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(readOnly, toolNames, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Never{readOnly=$readOnly, toolNames=$toolNames, additionalProperties=$additionalProperties}" + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is McpToolApprovalFilter && + always == other.always && + never == other.never && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(always, never, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "McpToolApprovalFilter{always=$always, never=$never, additionalProperties=$additionalProperties}" + } + + /** + * Specify a single approval policy for all tools. One of `always` or `never`. When + * set to `always`, all tools will require approval. When set to `never`, all tools + * will not require approval. + */ + class McpToolApprovalSetting + @JsonCreator + private constructor(private val value: JsonField) : Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that + * doesn't match any known member, and you want to know that value. For example, + * if the SDK is on an older version than the API, then the API may respond with + * new members that the SDK is unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue + fun _value(): JsonField = value + + companion object { + + @JvmField val ALWAYS = of("always") + + @JvmField val NEVER = of("never") + + @JvmStatic + fun of(value: String) = McpToolApprovalSetting(JsonField.of(value)) + } + + /** An enum containing [McpToolApprovalSetting]'s known values. */ + enum class Known { + ALWAYS, + NEVER, + } + + /** + * An enum containing [McpToolApprovalSetting]'s known values, as well as an + * [_UNKNOWN] member. + * + * An instance of [McpToolApprovalSetting] can contain an unknown value in a + * couple of cases: + * - It was deserialized from data that doesn't match any known member. For + * example, if the SDK is on an older version than the API, then the API may + * respond with new members that the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + ALWAYS, + NEVER, + /** + * An enum member indicating that [McpToolApprovalSetting] was instantiated + * with an unknown value. + */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or + * [Value._UNKNOWN] if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or + * if you want to throw for the unknown case. + */ + fun value(): Value = + when (this) { + ALWAYS -> Value.ALWAYS + NEVER -> Value.NEVER + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known + * and don't want to throw for the unknown case. + * + * @throws OpenAIInvalidDataException if this class instance's value is a not a + * known member. + */ + fun known(): Known = + when (this) { + ALWAYS -> Known.ALWAYS + NEVER -> Known.NEVER + else -> + throw OpenAIInvalidDataException( + "Unknown McpToolApprovalSetting: $value" + ) + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for + * debugging and generally doesn't throw. + * + * @throws OpenAIInvalidDataException if this class instance's value does not + * have the expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { + OpenAIInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected + * types recursively. + * + * This method is _not_ forwards compatible with new types from the API for + * existing fields. + * + * @throws OpenAIInvalidDataException if any value type in this object doesn't + * match its expected type. + */ + fun validate(): McpToolApprovalSetting = apply { + if (validated) { + return@apply + } + + known() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: OpenAIInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is McpToolApprovalSetting && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Mcp && + serverLabel == other.serverLabel && + type == other.type && + allowedCallers == other.allowedCallers && + allowedTools == other.allowedTools && + authorization == other.authorization && + connectorId == other.connectorId && + deferLoading == other.deferLoading && + headers == other.headers && + requireApproval == other.requireApproval && + serverDescription == other.serverDescription && + serverUrl == other.serverUrl && + tunnelId == other.tunnelId && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash( + serverLabel, + type, + allowedCallers, + allowedTools, + authorization, + connectorId, + deferLoading, + headers, + requireApproval, + serverDescription, + serverUrl, + tunnelId, + additionalProperties, + ) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Mcp{serverLabel=$serverLabel, type=$type, allowedCallers=$allowedCallers, allowedTools=$allowedTools, authorization=$authorization, connectorId=$connectorId, deferLoading=$deferLoading, headers=$headers, requireApproval=$requireApproval, serverDescription=$serverDescription, serverUrl=$serverUrl, tunnelId=$tunnelId, additionalProperties=$additionalProperties}" + } + + /** A tool that runs Python code to help generate a response to a prompt. */ + class CodeInterpreter + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val container: JsonField, + private val type: JsonValue, + private val allowedCallers: JsonField>, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("container") + @ExcludeMissing + container: JsonField = JsonMissing.of(), + @JsonProperty("type") @ExcludeMissing type: JsonValue = JsonMissing.of(), + @JsonProperty("allowed_callers") + @ExcludeMissing + allowedCallers: JsonField> = JsonMissing.of(), + ) : this(container, type, allowedCallers, mutableMapOf()) + + /** + * The code interpreter container. Can be a container ID or an object that specifies + * uploaded file IDs to make available to your code, along with an optional + * `memory_limit` setting. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected + * value). + */ + fun container(): Container = container.getRequired("container") + + /** + * The type of the code interpreter tool. Always `code_interpreter`. + * + * Expected to always return the following: + * ```java + * JsonValue.from("code_interpreter") + * ``` + * + * However, this method can be useful for debugging and logging (e.g. if the server + * responded with an unexpected value). + */ + @JsonProperty("type") @ExcludeMissing fun _type(): JsonValue = type + + /** + * The tool invocation context(s). + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun allowedCallers(): Optional> = + allowedCallers.getOptional("allowed_callers") + + /** + * Returns the raw JSON value of [container]. + * + * Unlike [container], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("container") + @ExcludeMissing + fun _container(): JsonField = container + + /** + * Returns the raw JSON value of [allowedCallers]. + * + * Unlike [allowedCallers], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("allowed_callers") + @ExcludeMissing + fun _allowedCallers(): JsonField> = allowedCallers + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [CodeInterpreter]. + * + * The following fields are required: + * ```java + * .container() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [CodeInterpreter]. */ + class Builder internal constructor() { + + private var container: JsonField? = null + private var type: JsonValue = JsonValue.from("code_interpreter") + private var allowedCallers: JsonField>? = null + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(codeInterpreter: CodeInterpreter) = apply { + container = codeInterpreter.container + type = codeInterpreter.type + allowedCallers = codeInterpreter.allowedCallers.map { it.toMutableList() } + additionalProperties = codeInterpreter.additionalProperties.toMutableMap() + } + + /** + * The code interpreter container. Can be a container ID or an object that specifies + * uploaded file IDs to make available to your code, along with an optional + * `memory_limit` setting. + */ + fun container(container: Container) = container(JsonField.of(container)) + + /** + * Sets [Builder.container] to an arbitrary JSON value. + * + * You should usually call [Builder.container] with a well-typed [Container] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun container(container: JsonField) = apply { + this.container = container + } + + /** Alias for calling [container] with `Container.ofString(string)`. */ + fun container(string: String) = container(Container.ofString(string)) + + /** + * Alias for calling [container] with + * `Container.ofCodeInterpreterToolAuto(codeInterpreterToolAuto)`. + */ + fun container(codeInterpreterToolAuto: Container.CodeInterpreterToolAuto) = + container(Container.ofCodeInterpreterToolAuto(codeInterpreterToolAuto)) + + /** + * Sets the field to an arbitrary JSON value. + * + * It is usually unnecessary to call this method because the field defaults to the + * following: + * ```java + * JsonValue.from("code_interpreter") + * ``` + * + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun type(type: JsonValue) = apply { this.type = type } + + /** The tool invocation context(s). */ + fun allowedCallers(allowedCallers: List?) = + allowedCallers(JsonField.ofNullable(allowedCallers)) + + /** + * Alias for calling [Builder.allowedCallers] with `allowedCallers.orElse(null)`. + */ + fun allowedCallers(allowedCallers: Optional>) = + allowedCallers(allowedCallers.getOrNull()) + + /** + * Sets [Builder.allowedCallers] to an arbitrary JSON value. + * + * You should usually call [Builder.allowedCallers] with a well-typed + * `List` value instead. This method is primarily for setting the + * field to an undocumented or not yet supported value. + */ + fun allowedCallers(allowedCallers: JsonField>) = apply { + this.allowedCallers = allowedCallers.map { it.toMutableList() } + } + + /** + * Adds a single [AllowedCaller] to [allowedCallers]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addAllowedCaller(allowedCaller: AllowedCaller) = apply { + allowedCallers = + (allowedCallers ?: JsonField.of(mutableListOf())).also { + checkKnown("allowedCallers", it).add(allowedCaller) + } + } + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = + apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { + additionalProperties.remove(key) + } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [CodeInterpreter]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .container() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): CodeInterpreter = + CodeInterpreter( + checkRequired("container", container), + type, + (allowedCallers ?: JsonMissing.of()).map { it.toImmutable() }, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws OpenAIInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): CodeInterpreter = apply { + if (validated) { + return@apply + } + + container().validate() + _type().let { + if (it != JsonValue.from("code_interpreter")) { + throw OpenAIInvalidDataException("'type' is invalid, received $it") + } + } + allowedCallers().ifPresent { it.forEach { it.validate() } } + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: OpenAIInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + (container.asKnown().getOrNull()?.validity() ?: 0) + + type.let { if (it == JsonValue.from("code_interpreter")) 1 else 0 } + + (allowedCallers.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + + /** + * The code interpreter container. Can be a container ID or an object that specifies + * uploaded file IDs to make available to your code, along with an optional + * `memory_limit` setting. + */ + @JsonDeserialize(using = Container.Deserializer::class) + @JsonSerialize(using = Container.Serializer::class) + class Container + private constructor( + private val string: String? = null, + private val codeInterpreterToolAuto: CodeInterpreterToolAuto? = null, + private val _json: JsonValue? = null, + ) { + + /** The container ID. */ + fun string(): Optional = Optional.ofNullable(string) + + /** + * Configuration for a code interpreter container. Optionally specify the IDs of the + * files to run the code on. + */ + fun codeInterpreterToolAuto(): Optional = + Optional.ofNullable(codeInterpreterToolAuto) + + fun isString(): Boolean = string != null + + fun isCodeInterpreterToolAuto(): Boolean = codeInterpreterToolAuto != null + + /** The container ID. */ + fun asString(): String = string.getOrThrow("string") + + /** + * Configuration for a code interpreter container. Optionally specify the IDs of the + * files to run the code on. + */ + fun asCodeInterpreterToolAuto(): CodeInterpreterToolAuto = + codeInterpreterToolAuto.getOrThrow("codeInterpreterToolAuto") + + fun _json(): Optional = Optional.ofNullable(_json) + + /** + * Maps this instance's current variant to a value of type [T] using the given + * [visitor]. + * + * Note that this method is _not_ forwards compatible with new variants from the + * API, unless [visitor] overrides [Visitor.unknown]. To handle variants not known + * to this version of the SDK gracefully, consider overriding [Visitor.unknown]: + * ```java + * import com.openai.core.JsonValue; + * import java.util.Optional; + * + * Optional result = container.accept(new Container.Visitor>() { + * @Override + * public Optional visitString(String string) { + * return Optional.of(string.toString()); + * } + * + * // ... + * + * @Override + * public Optional unknown(JsonValue json) { + * // Or inspect the `json`. + * return Optional.empty(); + * } + * }); + * ``` + * + * @throws OpenAIInvalidDataException if [Visitor.unknown] is not overridden in + * [visitor] and the current variant is unknown. + */ + fun accept(visitor: Visitor): T = + when { + string != null -> visitor.visitString(string) + codeInterpreterToolAuto != null -> + visitor.visitCodeInterpreterToolAuto(codeInterpreterToolAuto) + else -> visitor.unknown(_json) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws OpenAIInvalidDataException if any value type in this object doesn't match + * its expected type. + */ + fun validate(): Container = apply { + if (validated) { + return@apply + } + + accept( + object : Visitor { + override fun visitString(string: String) {} + + override fun visitCodeInterpreterToolAuto( + codeInterpreterToolAuto: CodeInterpreterToolAuto + ) { + codeInterpreterToolAuto.validate() + } + } + ) + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: OpenAIInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + accept( + object : Visitor { + override fun visitString(string: String) = 1 + + override fun visitCodeInterpreterToolAuto( + codeInterpreterToolAuto: CodeInterpreterToolAuto + ) = codeInterpreterToolAuto.validity() + + override fun unknown(json: JsonValue?) = 0 + } + ) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Container && + string == other.string && + codeInterpreterToolAuto == other.codeInterpreterToolAuto + } + + override fun hashCode(): Int = Objects.hash(string, codeInterpreterToolAuto) + + override fun toString(): String = + when { + string != null -> "Container{string=$string}" + codeInterpreterToolAuto != null -> + "Container{codeInterpreterToolAuto=$codeInterpreterToolAuto}" + _json != null -> "Container{_unknown=$_json}" + else -> throw IllegalStateException("Invalid Container") + } + + companion object { + + /** The container ID. */ + @JvmStatic fun ofString(string: String) = Container(string = string) + + /** + * Configuration for a code interpreter container. Optionally specify the IDs of + * the files to run the code on. + */ + @JvmStatic + fun ofCodeInterpreterToolAuto( + codeInterpreterToolAuto: CodeInterpreterToolAuto + ) = Container(codeInterpreterToolAuto = codeInterpreterToolAuto) + } + + /** + * An interface that defines how to map each variant of [Container] to a value of + * type [T]. + */ + interface Visitor { + + /** The container ID. */ + fun visitString(string: String): T + + /** + * Configuration for a code interpreter container. Optionally specify the IDs of + * the files to run the code on. + */ + fun visitCodeInterpreterToolAuto( + codeInterpreterToolAuto: CodeInterpreterToolAuto + ): T + + /** + * Maps an unknown variant of [Container] to a value of type [T]. + * + * An instance of [Container] can contain an unknown variant if it was + * deserialized from data that doesn't match any known variant. For example, if + * the SDK is on an older version than the API, then the API may respond with + * new variants that the SDK is unaware of. + * + * @throws OpenAIInvalidDataException in the default implementation. + */ + fun unknown(json: JsonValue?): T { + throw OpenAIInvalidDataException("Unknown Container") + } + } + + internal class Deserializer : BaseDeserializer(Container::class) { + + override fun ObjectCodec.deserialize(node: JsonNode): Container { + val json = JsonValue.fromJsonNode(node) + + val bestMatches = + sequenceOf( + tryDeserialize(node, jacksonTypeRef()) + ?.let { + Container(codeInterpreterToolAuto = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef())?.let { + Container(string = it, _json = json) + }, + ) + .filterNotNull() + .allMaxBy { it.validity() } + .toList() + return when (bestMatches.size) { + // This can happen if what we're deserializing is completely + // incompatible with all the possible variants (e.g. deserializing from + // boolean). + 0 -> Container(_json = json) + 1 -> bestMatches.single() + // If there's more than one match with the highest validity, then use + // the first completely valid match, or simply the first match if none + // are completely valid. + else -> bestMatches.firstOrNull { it.isValid() } ?: bestMatches.first() + } + } + } + + internal class Serializer : BaseSerializer(Container::class) { + + override fun serialize( + value: Container, + generator: JsonGenerator, + provider: SerializerProvider, + ) { + when { + value.string != null -> generator.writeObject(value.string) + value.codeInterpreterToolAuto != null -> + generator.writeObject(value.codeInterpreterToolAuto) + value._json != null -> generator.writeObject(value._json) + else -> throw IllegalStateException("Invalid Container") + } + } + } + + /** + * Configuration for a code interpreter container. Optionally specify the IDs of the + * files to run the code on. + */ + class CodeInterpreterToolAuto + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val type: JsonValue, + private val fileIds: JsonField>, + private val memoryLimit: JsonField, + private val networkPolicy: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("type") @ExcludeMissing type: JsonValue = JsonMissing.of(), + @JsonProperty("file_ids") + @ExcludeMissing + fileIds: JsonField> = JsonMissing.of(), + @JsonProperty("memory_limit") + @ExcludeMissing + memoryLimit: JsonField = JsonMissing.of(), + @JsonProperty("network_policy") + @ExcludeMissing + networkPolicy: JsonField = JsonMissing.of(), + ) : this(type, fileIds, memoryLimit, networkPolicy, mutableMapOf()) + + /** + * Always `auto`. + * + * Expected to always return the following: + * ```java + * JsonValue.from("auto") + * ``` + * + * However, this method can be useful for debugging and logging (e.g. if the + * server responded with an unexpected value). + */ + @JsonProperty("type") @ExcludeMissing fun _type(): JsonValue = type + + /** + * An optional list of uploaded files to make available to your code. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun fileIds(): Optional> = fileIds.getOptional("file_ids") + + /** + * The memory limit for the code interpreter container. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun memoryLimit(): Optional = + memoryLimit.getOptional("memory_limit") + + /** + * Network access policy for the container. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun networkPolicy(): Optional = + networkPolicy.getOptional("network_policy") + + /** + * Returns the raw JSON value of [fileIds]. + * + * Unlike [fileIds], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("file_ids") + @ExcludeMissing + fun _fileIds(): JsonField> = fileIds + + /** + * Returns the raw JSON value of [memoryLimit]. + * + * Unlike [memoryLimit], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("memory_limit") + @ExcludeMissing + fun _memoryLimit(): JsonField = memoryLimit + + /** + * Returns the raw JSON value of [networkPolicy]. + * + * Unlike [networkPolicy], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("network_policy") + @ExcludeMissing + fun _networkPolicy(): JsonField = networkPolicy + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of + * [CodeInterpreterToolAuto]. + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [CodeInterpreterToolAuto]. */ + class Builder internal constructor() { + + private var type: JsonValue = JsonValue.from("auto") + private var fileIds: JsonField>? = null + private var memoryLimit: JsonField = JsonMissing.of() + private var networkPolicy: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = + mutableMapOf() + + @JvmSynthetic + internal fun from(codeInterpreterToolAuto: CodeInterpreterToolAuto) = + apply { + type = codeInterpreterToolAuto.type + fileIds = codeInterpreterToolAuto.fileIds.map { it.toMutableList() } + memoryLimit = codeInterpreterToolAuto.memoryLimit + networkPolicy = codeInterpreterToolAuto.networkPolicy + additionalProperties = + codeInterpreterToolAuto.additionalProperties.toMutableMap() + } + + /** + * Sets the field to an arbitrary JSON value. + * + * It is usually unnecessary to call this method because the field defaults + * to the following: + * ```java + * JsonValue.from("auto") + * ``` + * + * This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun type(type: JsonValue) = apply { this.type = type } + + /** An optional list of uploaded files to make available to your code. */ + fun fileIds(fileIds: List) = fileIds(JsonField.of(fileIds)) + + /** + * Sets [Builder.fileIds] to an arbitrary JSON value. + * + * You should usually call [Builder.fileIds] with a well-typed + * `List` value instead. This method is primarily for setting the + * field to an undocumented or not yet supported value. + */ + fun fileIds(fileIds: JsonField>) = apply { + this.fileIds = fileIds.map { it.toMutableList() } + } + + /** + * Adds a single [String] to [fileIds]. + * + * @throws IllegalStateException if the field was previously set to a + * non-list. + */ + fun addFileId(fileId: String) = apply { + fileIds = + (fileIds ?: JsonField.of(mutableListOf())).also { + checkKnown("fileIds", it).add(fileId) + } + } + + /** The memory limit for the code interpreter container. */ + fun memoryLimit(memoryLimit: MemoryLimit?) = + memoryLimit(JsonField.ofNullable(memoryLimit)) + + /** + * Alias for calling [Builder.memoryLimit] with `memoryLimit.orElse(null)`. + */ + fun memoryLimit(memoryLimit: Optional) = + memoryLimit(memoryLimit.getOrNull()) + + /** + * Sets [Builder.memoryLimit] to an arbitrary JSON value. + * + * You should usually call [Builder.memoryLimit] with a well-typed + * [MemoryLimit] value instead. This method is primarily for setting the + * field to an undocumented or not yet supported value. + */ + fun memoryLimit(memoryLimit: JsonField) = apply { + this.memoryLimit = memoryLimit + } + + /** Network access policy for the container. */ + fun networkPolicy(networkPolicy: NetworkPolicy) = + networkPolicy(JsonField.of(networkPolicy)) + + /** + * Sets [Builder.networkPolicy] to an arbitrary JSON value. + * + * You should usually call [Builder.networkPolicy] with a well-typed + * [NetworkPolicy] value instead. This method is primarily for setting the + * field to an undocumented or not yet supported value. + */ + fun networkPolicy(networkPolicy: JsonField) = apply { + this.networkPolicy = networkPolicy + } + + /** + * Alias for calling [networkPolicy] with + * `NetworkPolicy.ofDisabled(disabled)`. + */ + fun networkPolicy(disabled: BetaContainerNetworkPolicyDisabled) = + networkPolicy(NetworkPolicy.ofDisabled(disabled)) + + /** + * Alias for calling [networkPolicy] with + * `NetworkPolicy.ofAllowlist(allowlist)`. + */ + fun networkPolicy(allowlist: BetaContainerNetworkPolicyAllowlist) = + networkPolicy(NetworkPolicy.ofAllowlist(allowlist)) + + /** + * Alias for calling [networkPolicy] with the following: + * ```java + * BetaContainerNetworkPolicyAllowlist.builder() + * .allowedDomains(allowedDomains) + * .build() + * ``` + */ + fun allowlistNetworkPolicy(allowedDomains: List) = + networkPolicy( + BetaContainerNetworkPolicyAllowlist.builder() + .allowedDomains(allowedDomains) + .build() + ) + + fun additionalProperties(additionalProperties: Map) = + apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties( + additionalProperties: Map + ) = apply { this.additionalProperties.putAll(additionalProperties) } + + fun removeAdditionalProperty(key: String) = apply { + additionalProperties.remove(key) + } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [CodeInterpreterToolAuto]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): CodeInterpreterToolAuto = + CodeInterpreterToolAuto( + type, + (fileIds ?: JsonMissing.of()).map { it.toImmutable() }, + memoryLimit, + networkPolicy, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected + * types recursively. + * + * This method is _not_ forwards compatible with new types from the API for + * existing fields. + * + * @throws OpenAIInvalidDataException if any value type in this object doesn't + * match its expected type. + */ + fun validate(): CodeInterpreterToolAuto = apply { + if (validated) { + return@apply + } + + _type().let { + if (it != JsonValue.from("auto")) { + throw OpenAIInvalidDataException("'type' is invalid, received $it") + } + } + fileIds() + memoryLimit().ifPresent { it.validate() } + networkPolicy().ifPresent { it.validate() } + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: OpenAIInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + type.let { if (it == JsonValue.from("auto")) 1 else 0 } + + (fileIds.asKnown().getOrNull()?.size ?: 0) + + (memoryLimit.asKnown().getOrNull()?.validity() ?: 0) + + (networkPolicy.asKnown().getOrNull()?.validity() ?: 0) + + /** The memory limit for the code interpreter container. */ + class MemoryLimit + @JsonCreator + private constructor(private val value: JsonField) : Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data + * that doesn't match any known member, and you want to know that value. For + * example, if the SDK is on an older version than the API, then the API may + * respond with new members that the SDK is unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue + fun _value(): JsonField = value + + companion object { + + @JvmField val _1G = of("1g") + + @JvmField val _4G = of("4g") + + @JvmField val _16G = of("16g") + + @JvmField val _64G = of("64g") + + @JvmStatic fun of(value: String) = MemoryLimit(JsonField.of(value)) + } + + /** An enum containing [MemoryLimit]'s known values. */ + enum class Known { + _1G, + _4G, + _16G, + _64G, + } + + /** + * An enum containing [MemoryLimit]'s known values, as well as an [_UNKNOWN] + * member. + * + * An instance of [MemoryLimit] can contain an unknown value in a couple of + * cases: + * - It was deserialized from data that doesn't match any known member. For + * example, if the SDK is on an older version than the API, then the API + * may respond with new members that the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + _1G, + _4G, + _16G, + _64G, + /** + * An enum member indicating that [MemoryLimit] was instantiated with an + * unknown value. + */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or + * [Value._UNKNOWN] if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always + * known or if you want to throw for the unknown case. + */ + fun value(): Value = + when (this) { + _1G -> Value._1G + _4G -> Value._4G + _16G -> Value._16G + _64G -> Value._64G + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always + * known and don't want to throw for the unknown case. + * + * @throws OpenAIInvalidDataException if this class instance's value is a + * not a known member. + */ + fun known(): Known = + when (this) { + _1G -> Known._1G + _4G -> Known._4G + _16G -> Known._16G + _64G -> Known._64G + else -> + throw OpenAIInvalidDataException("Unknown MemoryLimit: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily + * for debugging and generally doesn't throw. + * + * @throws OpenAIInvalidDataException if this class instance's value does + * not have the expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { + OpenAIInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their + * expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for + * existing fields. + * + * @throws OpenAIInvalidDataException if any value type in this object + * doesn't match its expected type. + */ + fun validate(): MemoryLimit = apply { + if (validated) { + return@apply + } + + known() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: OpenAIInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this + * object recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is MemoryLimit && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + /** Network access policy for the container. */ + @JsonDeserialize(using = NetworkPolicy.Deserializer::class) + @JsonSerialize(using = NetworkPolicy.Serializer::class) + class NetworkPolicy + private constructor( + private val disabled: BetaContainerNetworkPolicyDisabled? = null, + private val allowlist: BetaContainerNetworkPolicyAllowlist? = null, + private val _json: JsonValue? = null, + ) { + + fun disabled(): Optional = + Optional.ofNullable(disabled) + + fun allowlist(): Optional = + Optional.ofNullable(allowlist) + + fun isDisabled(): Boolean = disabled != null + + fun isAllowlist(): Boolean = allowlist != null + + fun asDisabled(): BetaContainerNetworkPolicyDisabled = + disabled.getOrThrow("disabled") + + fun asAllowlist(): BetaContainerNetworkPolicyAllowlist = + allowlist.getOrThrow("allowlist") + + fun _json(): Optional = Optional.ofNullable(_json) + + /** + * Maps this instance's current variant to a value of type [T] using the + * given [visitor]. + * + * Note that this method is _not_ forwards compatible with new variants from + * the API, unless [visitor] overrides [Visitor.unknown]. To handle variants + * not known to this version of the SDK gracefully, consider overriding + * [Visitor.unknown]: + * ```java + * import com.openai.core.JsonValue; + * import java.util.Optional; + * + * Optional result = networkPolicy.accept(new NetworkPolicy.Visitor>() { + * @Override + * public Optional visitDisabled(BetaContainerNetworkPolicyDisabled disabled) { + * return Optional.of(disabled.toString()); + * } + * + * // ... + * + * @Override + * public Optional unknown(JsonValue json) { + * // Or inspect the `json`. + * return Optional.empty(); + * } + * }); + * ``` + * + * @throws OpenAIInvalidDataException if [Visitor.unknown] is not overridden + * in [visitor] and the current variant is unknown. + */ + fun accept(visitor: Visitor): T = + when { + disabled != null -> visitor.visitDisabled(disabled) + allowlist != null -> visitor.visitAllowlist(allowlist) + else -> visitor.unknown(_json) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their + * expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for + * existing fields. + * + * @throws OpenAIInvalidDataException if any value type in this object + * doesn't match its expected type. + */ + fun validate(): NetworkPolicy = apply { + if (validated) { + return@apply + } + + accept( + object : Visitor { + override fun visitDisabled( + disabled: BetaContainerNetworkPolicyDisabled + ) { + disabled.validate() + } + + override fun visitAllowlist( + allowlist: BetaContainerNetworkPolicyAllowlist + ) { + allowlist.validate() + } + } + ) + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: OpenAIInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this + * object recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + accept( + object : Visitor { + override fun visitDisabled( + disabled: BetaContainerNetworkPolicyDisabled + ) = disabled.validity() + + override fun visitAllowlist( + allowlist: BetaContainerNetworkPolicyAllowlist + ) = allowlist.validity() + + override fun unknown(json: JsonValue?) = 0 + } + ) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is NetworkPolicy && + disabled == other.disabled && + allowlist == other.allowlist + } + + override fun hashCode(): Int = Objects.hash(disabled, allowlist) + + override fun toString(): String = + when { + disabled != null -> "NetworkPolicy{disabled=$disabled}" + allowlist != null -> "NetworkPolicy{allowlist=$allowlist}" + _json != null -> "NetworkPolicy{_unknown=$_json}" + else -> throw IllegalStateException("Invalid NetworkPolicy") + } + + companion object { + + @JvmStatic + fun ofDisabled(disabled: BetaContainerNetworkPolicyDisabled) = + NetworkPolicy(disabled = disabled) + + @JvmStatic + fun ofAllowlist(allowlist: BetaContainerNetworkPolicyAllowlist) = + NetworkPolicy(allowlist = allowlist) + } + + /** + * An interface that defines how to map each variant of [NetworkPolicy] to a + * value of type [T]. + */ + interface Visitor { + + fun visitDisabled(disabled: BetaContainerNetworkPolicyDisabled): T + + fun visitAllowlist(allowlist: BetaContainerNetworkPolicyAllowlist): T + + /** + * Maps an unknown variant of [NetworkPolicy] to a value of type [T]. + * + * An instance of [NetworkPolicy] can contain an unknown variant if it + * was deserialized from data that doesn't match any known variant. For + * example, if the SDK is on an older version than the API, then the API + * may respond with new variants that the SDK is unaware of. + * + * @throws OpenAIInvalidDataException in the default implementation. + */ + fun unknown(json: JsonValue?): T { + throw OpenAIInvalidDataException("Unknown NetworkPolicy") + } + } + + internal class Deserializer : + BaseDeserializer(NetworkPolicy::class) { + + override fun ObjectCodec.deserialize(node: JsonNode): NetworkPolicy { + val json = JsonValue.fromJsonNode(node) + val type = + json + .asObject() + .getOrNull() + ?.get("type") + ?.asString() + ?.getOrNull() + + when (type) { + "disabled" -> { + return tryDeserialize( + node, + jacksonTypeRef(), + ) + ?.let { NetworkPolicy(disabled = it, _json = json) } + ?: NetworkPolicy(_json = json) + } + "allowlist" -> { + return tryDeserialize( + node, + jacksonTypeRef< + BetaContainerNetworkPolicyAllowlist + >(), + ) + ?.let { NetworkPolicy(allowlist = it, _json = json) } + ?: NetworkPolicy(_json = json) + } + } + + return NetworkPolicy(_json = json) + } + } + + internal class Serializer : + BaseSerializer(NetworkPolicy::class) { + + override fun serialize( + value: NetworkPolicy, + generator: JsonGenerator, + provider: SerializerProvider, + ) { + when { + value.disabled != null -> generator.writeObject(value.disabled) + value.allowlist != null -> + generator.writeObject(value.allowlist) + value._json != null -> generator.writeObject(value._json) + else -> throw IllegalStateException("Invalid NetworkPolicy") + } + } + } + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is CodeInterpreterToolAuto && + type == other.type && + fileIds == other.fileIds && + memoryLimit == other.memoryLimit && + networkPolicy == other.networkPolicy && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash( + type, + fileIds, + memoryLimit, + networkPolicy, + additionalProperties, + ) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "CodeInterpreterToolAuto{type=$type, fileIds=$fileIds, memoryLimit=$memoryLimit, networkPolicy=$networkPolicy, additionalProperties=$additionalProperties}" + } + } + + class AllowedCaller + @JsonCreator + private constructor(private val value: JsonField) : Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that + * doesn't match any known member, and you want to know that value. For example, if + * the SDK is on an older version than the API, then the API may respond with new + * members that the SDK is unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val DIRECT = of("direct") + + @JvmField val PROGRAMMATIC = of("programmatic") + + @JvmStatic fun of(value: String) = AllowedCaller(JsonField.of(value)) + } + + /** An enum containing [AllowedCaller]'s known values. */ + enum class Known { + DIRECT, + PROGRAMMATIC, + } + + /** + * An enum containing [AllowedCaller]'s known values, as well as an [_UNKNOWN] + * member. + * + * An instance of [AllowedCaller] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, + * if the SDK is on an older version than the API, then the API may respond with + * new members that the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + DIRECT, + PROGRAMMATIC, + /** + * An enum member indicating that [AllowedCaller] was instantiated with an + * unknown value. + */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or + * [Value._UNKNOWN] if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if + * you want to throw for the unknown case. + */ + fun value(): Value = + when (this) { + DIRECT -> Value.DIRECT + PROGRAMMATIC -> Value.PROGRAMMATIC + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and + * don't want to throw for the unknown case. + * + * @throws OpenAIInvalidDataException if this class instance's value is a not a + * known member. + */ + fun known(): Known = + when (this) { + DIRECT -> Known.DIRECT + PROGRAMMATIC -> Known.PROGRAMMATIC + else -> throw OpenAIInvalidDataException("Unknown AllowedCaller: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for + * debugging and generally doesn't throw. + * + * @throws OpenAIInvalidDataException if this class instance's value does not have + * the expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { + OpenAIInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws OpenAIInvalidDataException if any value type in this object doesn't match + * its expected type. + */ + fun validate(): AllowedCaller = apply { + if (validated) { + return@apply + } + + known() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: OpenAIInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is AllowedCaller && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is CodeInterpreter && + container == other.container && + type == other.type && + allowedCallers == other.allowedCallers && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(container, type, allowedCallers, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "CodeInterpreter{container=$container, type=$type, allowedCallers=$allowedCallers, additionalProperties=$additionalProperties}" + } + + /** A tool that generates images using the GPT image models. */ + class ImageGeneration + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val type: JsonValue, + private val action: JsonField, + private val background: JsonField, + private val inputFidelity: JsonField, + private val inputImageMask: JsonField, + private val model: JsonField, + private val moderation: JsonField, + private val outputCompression: JsonField, + private val outputFormat: JsonField, + private val partialImages: JsonField, + private val quality: JsonField, + private val size: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("type") @ExcludeMissing type: JsonValue = JsonMissing.of(), + @JsonProperty("action") + @ExcludeMissing + action: JsonField = JsonMissing.of(), + @JsonProperty("background") + @ExcludeMissing + background: JsonField = JsonMissing.of(), + @JsonProperty("input_fidelity") + @ExcludeMissing + inputFidelity: JsonField = JsonMissing.of(), + @JsonProperty("input_image_mask") + @ExcludeMissing + inputImageMask: JsonField = JsonMissing.of(), + @JsonProperty("model") @ExcludeMissing model: JsonField = JsonMissing.of(), + @JsonProperty("moderation") + @ExcludeMissing + moderation: JsonField = JsonMissing.of(), + @JsonProperty("output_compression") + @ExcludeMissing + outputCompression: JsonField = JsonMissing.of(), + @JsonProperty("output_format") + @ExcludeMissing + outputFormat: JsonField = JsonMissing.of(), + @JsonProperty("partial_images") + @ExcludeMissing + partialImages: JsonField = JsonMissing.of(), + @JsonProperty("quality") + @ExcludeMissing + quality: JsonField = JsonMissing.of(), + @JsonProperty("size") @ExcludeMissing size: JsonField = JsonMissing.of(), + ) : this( + type, + action, + background, + inputFidelity, + inputImageMask, + model, + moderation, + outputCompression, + outputFormat, + partialImages, + quality, + size, + mutableMapOf(), + ) + + /** + * The type of the image generation tool. Always `image_generation`. + * + * Expected to always return the following: + * ```java + * JsonValue.from("image_generation") + * ``` + * + * However, this method can be useful for debugging and logging (e.g. if the server + * responded with an unexpected value). + */ + @JsonProperty("type") @ExcludeMissing fun _type(): JsonValue = type + + /** + * Whether to generate a new image or edit an existing image. Default: `auto`. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun action(): Optional = action.getOptional("action") + + /** + * Allows to set transparency for the background of the generated image(s). Must be one + * of `transparent`, `opaque`, or `auto` (default value). When `auto` is used, the model + * will automatically determine the best background for the image. + * + * `gpt-image-2.5-sunburst` and `gpt-image-2.5-flare`, including their `2026-09-08` + * snapshots, support `opaque` and `transparent` backgrounds. Transparent backgrounds + * are available for supported GPT Image models. For `gpt-image-2` and + * `gpt-image-2-2026-04-21`, this support is in preview. When using `transparent`, set + * the output format to `png` or `webp`. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun background(): Optional = background.getOptional("background") + + /** + * Control how much effort the model will exert to match the style and features, + * especially facial features, of input images. Supports `high` and `low` on + * `gpt-image-1` and `gpt-image-1.5`; `gpt-image-1-mini` supports only `low`. For + * `gpt-image-2`, omit this parameter. Defaults to `low` on supported models. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun inputFidelity(): Optional = + inputFidelity.getOptional("input_fidelity") + + /** + * Optional mask for inpainting. Contains `image_url` (string, optional) and `file_id` + * (string, optional). + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun inputImageMask(): Optional = + inputImageMask.getOptional("input_image_mask") + + /** + * The image generation model to use. One of `gpt-image-1`, `gpt-image-1-mini`, + * `gpt-image-1.5`, `gpt-image-2`, `gpt-image-2-2026-04-21`, `gpt-image-2.5-sunburst`, + * `gpt-image-2.5-sunburst-2026-09-08`, `gpt-image-2.5-flare`, + * `gpt-image-2.5-flare-2026-09-08`, or `chatgpt-image-latest`. Default: `gpt-image-1`. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun model(): Optional = model.getOptional("model") + + /** + * Moderation level for the generated image. Default: `auto`. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun moderation(): Optional = moderation.getOptional("moderation") + + /** + * Compression level for the output image. Default: 100. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun outputCompression(): Optional = + outputCompression.getOptional("output_compression") + + /** + * The output format of the generated image. One of `png`, `webp`, or `jpeg`. Default: + * `png`. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun outputFormat(): Optional = outputFormat.getOptional("output_format") + + /** + * Number of partial images to generate in streaming mode, from 0 (default value) to 3. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun partialImages(): Optional = partialImages.getOptional("partial_images") + + /** + * The quality of the generated image. The GPT image models support `low`, `medium`, and + * `high`. `gpt-image-2.5-sunburst` and `gpt-image-2.5-flare`, including their + * `2026-09-08` snapshots, also support `xhigh` and `max`. Default: `auto`. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun quality(): Optional = quality.getOptional("quality") + + /** + * The size of the generated images. For `gpt-image-2`, `gpt-image-2-2026-04-21`, + * `gpt-image-2.5-sunburst`, `gpt-image-2.5-sunburst-2026-09-08`, `gpt-image-2.5-flare`, + * and `gpt-image-2.5-flare-2026-09-08`, arbitrary resolutions are supported as + * `WIDTHxHEIGHT` strings, for example `1536x864`. Width and height must both be + * divisible by 16 and the requested aspect ratio must be between 1:3 and 3:1. + * Resolutions above `2560x1440` are experimental, and the maximum supported resolution + * is `3840x2160`. The requested size must also satisfy the model's current pixel and + * edge limits. The standard sizes `1024x1024`, `1536x1024`, and `1024x1536` are + * supported by the GPT image models; `auto` is supported for models that allow + * automatic sizing. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun size(): Optional = size.getOptional("size") + + /** + * Returns the raw JSON value of [action]. + * + * Unlike [action], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("action") @ExcludeMissing fun _action(): JsonField = action + + /** + * Returns the raw JSON value of [background]. + * + * Unlike [background], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("background") + @ExcludeMissing + fun _background(): JsonField = background + + /** + * Returns the raw JSON value of [inputFidelity]. + * + * Unlike [inputFidelity], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("input_fidelity") + @ExcludeMissing + fun _inputFidelity(): JsonField = inputFidelity + + /** + * Returns the raw JSON value of [inputImageMask]. + * + * Unlike [inputImageMask], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("input_image_mask") + @ExcludeMissing + fun _inputImageMask(): JsonField = inputImageMask + + /** + * Returns the raw JSON value of [model]. + * + * Unlike [model], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("model") @ExcludeMissing fun _model(): JsonField = model + + /** + * Returns the raw JSON value of [moderation]. + * + * Unlike [moderation], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("moderation") + @ExcludeMissing + fun _moderation(): JsonField = moderation + + /** + * Returns the raw JSON value of [outputCompression]. + * + * Unlike [outputCompression], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("output_compression") + @ExcludeMissing + fun _outputCompression(): JsonField = outputCompression + + /** + * Returns the raw JSON value of [outputFormat]. + * + * Unlike [outputFormat], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("output_format") + @ExcludeMissing + fun _outputFormat(): JsonField = outputFormat + + /** + * Returns the raw JSON value of [partialImages]. + * + * Unlike [partialImages], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("partial_images") + @ExcludeMissing + fun _partialImages(): JsonField = partialImages + + /** + * Returns the raw JSON value of [quality]. + * + * Unlike [quality], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("quality") @ExcludeMissing fun _quality(): JsonField = quality + + /** + * Returns the raw JSON value of [size]. + * + * Unlike [size], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("size") @ExcludeMissing fun _size(): JsonField = size + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** Returns a mutable builder for constructing an instance of [ImageGeneration]. */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [ImageGeneration]. */ + class Builder internal constructor() { + + private var type: JsonValue = JsonValue.from("image_generation") + private var action: JsonField = JsonMissing.of() + private var background: JsonField = JsonMissing.of() + private var inputFidelity: JsonField = JsonMissing.of() + private var inputImageMask: JsonField = JsonMissing.of() + private var model: JsonField = JsonMissing.of() + private var moderation: JsonField = JsonMissing.of() + private var outputCompression: JsonField = JsonMissing.of() + private var outputFormat: JsonField = JsonMissing.of() + private var partialImages: JsonField = JsonMissing.of() + private var quality: JsonField = JsonMissing.of() + private var size: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(imageGeneration: ImageGeneration) = apply { + type = imageGeneration.type + action = imageGeneration.action + background = imageGeneration.background + inputFidelity = imageGeneration.inputFidelity + inputImageMask = imageGeneration.inputImageMask + model = imageGeneration.model + moderation = imageGeneration.moderation + outputCompression = imageGeneration.outputCompression + outputFormat = imageGeneration.outputFormat + partialImages = imageGeneration.partialImages + quality = imageGeneration.quality + size = imageGeneration.size + additionalProperties = imageGeneration.additionalProperties.toMutableMap() + } + + /** + * Sets the field to an arbitrary JSON value. + * + * It is usually unnecessary to call this method because the field defaults to the + * following: + * ```java + * JsonValue.from("image_generation") + * ``` + * + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun type(type: JsonValue) = apply { this.type = type } + + /** Whether to generate a new image or edit an existing image. Default: `auto`. */ + fun action(action: Action) = action(JsonField.of(action)) + + /** + * Sets [Builder.action] to an arbitrary JSON value. + * + * You should usually call [Builder.action] with a well-typed [Action] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun action(action: JsonField) = apply { this.action = action } + + /** + * Allows to set transparency for the background of the generated image(s). Must be + * one of `transparent`, `opaque`, or `auto` (default value). When `auto` is used, + * the model will automatically determine the best background for the image. + * + * `gpt-image-2.5-sunburst` and `gpt-image-2.5-flare`, including their `2026-09-08` + * snapshots, support `opaque` and `transparent` backgrounds. Transparent + * backgrounds are available for supported GPT Image models. For `gpt-image-2` and + * `gpt-image-2-2026-04-21`, this support is in preview. When using `transparent`, + * set the output format to `png` or `webp`. + */ + fun background(background: Background) = background(JsonField.of(background)) + + /** + * Sets [Builder.background] to an arbitrary JSON value. + * + * You should usually call [Builder.background] with a well-typed [Background] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun background(background: JsonField) = apply { + this.background = background + } + + /** + * Control how much effort the model will exert to match the style and features, + * especially facial features, of input images. Supports `high` and `low` on + * `gpt-image-1` and `gpt-image-1.5`; `gpt-image-1-mini` supports only `low`. For + * `gpt-image-2`, omit this parameter. Defaults to `low` on supported models. + */ + fun inputFidelity(inputFidelity: InputFidelity?) = + inputFidelity(JsonField.ofNullable(inputFidelity)) + + /** Alias for calling [Builder.inputFidelity] with `inputFidelity.orElse(null)`. */ + fun inputFidelity(inputFidelity: Optional) = + inputFidelity(inputFidelity.getOrNull()) + + /** + * Sets [Builder.inputFidelity] to an arbitrary JSON value. + * + * You should usually call [Builder.inputFidelity] with a well-typed [InputFidelity] + * value instead. This method is primarily for setting the field to an undocumented + * or not yet supported value. + */ + fun inputFidelity(inputFidelity: JsonField) = apply { + this.inputFidelity = inputFidelity + } + + /** + * Optional mask for inpainting. Contains `image_url` (string, optional) and + * `file_id` (string, optional). + */ + fun inputImageMask(inputImageMask: InputImageMask) = + inputImageMask(JsonField.of(inputImageMask)) + + /** + * Sets [Builder.inputImageMask] to an arbitrary JSON value. + * + * You should usually call [Builder.inputImageMask] with a well-typed + * [InputImageMask] value instead. This method is primarily for setting the field to + * an undocumented or not yet supported value. + */ + fun inputImageMask(inputImageMask: JsonField) = apply { + this.inputImageMask = inputImageMask + } + + /** + * The image generation model to use. One of `gpt-image-1`, `gpt-image-1-mini`, + * `gpt-image-1.5`, `gpt-image-2`, `gpt-image-2-2026-04-21`, + * `gpt-image-2.5-sunburst`, `gpt-image-2.5-sunburst-2026-09-08`, + * `gpt-image-2.5-flare`, `gpt-image-2.5-flare-2026-09-08`, or + * `chatgpt-image-latest`. Default: `gpt-image-1`. + */ + fun model(model: Model) = model(JsonField.of(model)) + + /** + * Sets [Builder.model] to an arbitrary JSON value. + * + * You should usually call [Builder.model] with a well-typed [Model] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun model(model: JsonField) = apply { this.model = model } + + /** + * Sets [model] to an arbitrary [String]. + * + * You should usually call [model] with a well-typed [Model] constant instead. This + * method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun model(value: String) = model(Model.of(value)) + + /** Moderation level for the generated image. Default: `auto`. */ + fun moderation(moderation: Moderation) = moderation(JsonField.of(moderation)) + + /** + * Sets [Builder.moderation] to an arbitrary JSON value. + * + * You should usually call [Builder.moderation] with a well-typed [Moderation] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun moderation(moderation: JsonField) = apply { + this.moderation = moderation + } + + /** Compression level for the output image. Default: 100. */ + fun outputCompression(outputCompression: Long) = + outputCompression(JsonField.of(outputCompression)) + + /** + * Sets [Builder.outputCompression] to an arbitrary JSON value. + * + * You should usually call [Builder.outputCompression] with a well-typed [Long] + * value instead. This method is primarily for setting the field to an undocumented + * or not yet supported value. + */ + fun outputCompression(outputCompression: JsonField) = apply { + this.outputCompression = outputCompression + } + + /** + * The output format of the generated image. One of `png`, `webp`, or `jpeg`. + * Default: `png`. + */ + fun outputFormat(outputFormat: OutputFormat) = + outputFormat(JsonField.of(outputFormat)) + + /** + * Sets [Builder.outputFormat] to an arbitrary JSON value. + * + * You should usually call [Builder.outputFormat] with a well-typed [OutputFormat] + * value instead. This method is primarily for setting the field to an undocumented + * or not yet supported value. + */ + fun outputFormat(outputFormat: JsonField) = apply { + this.outputFormat = outputFormat + } + + /** + * Number of partial images to generate in streaming mode, from 0 (default value) + * to 3. + */ + fun partialImages(partialImages: Long) = partialImages(JsonField.of(partialImages)) + + /** + * Sets [Builder.partialImages] to an arbitrary JSON value. + * + * You should usually call [Builder.partialImages] with a well-typed [Long] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun partialImages(partialImages: JsonField) = apply { + this.partialImages = partialImages + } + + /** + * The quality of the generated image. The GPT image models support `low`, `medium`, + * and `high`. `gpt-image-2.5-sunburst` and `gpt-image-2.5-flare`, including their + * `2026-09-08` snapshots, also support `xhigh` and `max`. Default: `auto`. + */ + fun quality(quality: Quality) = quality(JsonField.of(quality)) + + /** + * Sets [Builder.quality] to an arbitrary JSON value. + * + * You should usually call [Builder.quality] with a well-typed [Quality] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun quality(quality: JsonField) = apply { this.quality = quality } + + /** + * The size of the generated images. For `gpt-image-2`, `gpt-image-2-2026-04-21`, + * `gpt-image-2.5-sunburst`, `gpt-image-2.5-sunburst-2026-09-08`, + * `gpt-image-2.5-flare`, and `gpt-image-2.5-flare-2026-09-08`, arbitrary + * resolutions are supported as `WIDTHxHEIGHT` strings, for example `1536x864`. + * Width and height must both be divisible by 16 and the requested aspect ratio must + * be between 1:3 and 3:1. Resolutions above `2560x1440` are experimental, and the + * maximum supported resolution is `3840x2160`. The requested size must also satisfy + * the model's current pixel and edge limits. The standard sizes `1024x1024`, + * `1536x1024`, and `1024x1536` are supported by the GPT image models; `auto` is + * supported for models that allow automatic sizing. + */ + fun size(size: Size) = size(JsonField.of(size)) + + /** + * Sets [Builder.size] to an arbitrary JSON value. + * + * You should usually call [Builder.size] with a well-typed [Size] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun size(size: JsonField) = apply { this.size = size } + + /** + * Sets [size] to an arbitrary [String]. + * + * You should usually call [size] with a well-typed [Size] constant instead. This + * method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun size(value: String) = size(Size.of(value)) + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = + apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { + additionalProperties.remove(key) + } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [ImageGeneration]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): ImageGeneration = + ImageGeneration( + type, + action, + background, + inputFidelity, + inputImageMask, + model, + moderation, + outputCompression, + outputFormat, + partialImages, + quality, + size, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws OpenAIInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): ImageGeneration = apply { + if (validated) { + return@apply + } + + _type().let { + if (it != JsonValue.from("image_generation")) { + throw OpenAIInvalidDataException("'type' is invalid, received $it") + } + } + action().ifPresent { it.validate() } + background().ifPresent { it.validate() } + inputFidelity().ifPresent { it.validate() } + inputImageMask().ifPresent { it.validate() } + model() + moderation().ifPresent { it.validate() } + outputCompression() + outputFormat().ifPresent { it.validate() } + partialImages() + quality().ifPresent { it.validate() } + size() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: OpenAIInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + type.let { if (it == JsonValue.from("image_generation")) 1 else 0 } + + (action.asKnown().getOrNull()?.validity() ?: 0) + + (background.asKnown().getOrNull()?.validity() ?: 0) + + (inputFidelity.asKnown().getOrNull()?.validity() ?: 0) + + (inputImageMask.asKnown().getOrNull()?.validity() ?: 0) + + (if (model.asKnown().isPresent) 1 else 0) + + (moderation.asKnown().getOrNull()?.validity() ?: 0) + + (if (outputCompression.asKnown().isPresent) 1 else 0) + + (outputFormat.asKnown().getOrNull()?.validity() ?: 0) + + (if (partialImages.asKnown().isPresent) 1 else 0) + + (quality.asKnown().getOrNull()?.validity() ?: 0) + + (if (size.asKnown().isPresent) 1 else 0) + + /** Whether to generate a new image or edit an existing image. Default: `auto`. */ + class Action @JsonCreator private constructor(private val value: JsonField) : + Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that + * doesn't match any known member, and you want to know that value. For example, if + * the SDK is on an older version than the API, then the API may respond with new + * members that the SDK is unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val GENERATE = of("generate") + + @JvmField val EDIT = of("edit") + + @JvmField val AUTO = of("auto") + + @JvmStatic fun of(value: String) = Action(JsonField.of(value)) + } + + /** An enum containing [Action]'s known values. */ + enum class Known { + GENERATE, + EDIT, + AUTO, + } + + /** + * An enum containing [Action]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [Action] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, + * if the SDK is on an older version than the API, then the API may respond with + * new members that the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + GENERATE, + EDIT, + AUTO, + /** + * An enum member indicating that [Action] was instantiated with an unknown + * value. + */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or + * [Value._UNKNOWN] if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if + * you want to throw for the unknown case. + */ + fun value(): Value = + when (this) { + GENERATE -> Value.GENERATE + EDIT -> Value.EDIT + AUTO -> Value.AUTO + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and + * don't want to throw for the unknown case. + * + * @throws OpenAIInvalidDataException if this class instance's value is a not a + * known member. + */ + fun known(): Known = + when (this) { + GENERATE -> Known.GENERATE + EDIT -> Known.EDIT + AUTO -> Known.AUTO + else -> throw OpenAIInvalidDataException("Unknown Action: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for + * debugging and generally doesn't throw. + * + * @throws OpenAIInvalidDataException if this class instance's value does not have + * the expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { + OpenAIInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws OpenAIInvalidDataException if any value type in this object doesn't match + * its expected type. + */ + fun validate(): Action = apply { + if (validated) { + return@apply + } + + known() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: OpenAIInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Action && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + /** + * Allows to set transparency for the background of the generated image(s). Must be one + * of `transparent`, `opaque`, or `auto` (default value). When `auto` is used, the model + * will automatically determine the best background for the image. + * + * `gpt-image-2.5-sunburst` and `gpt-image-2.5-flare`, including their `2026-09-08` + * snapshots, support `opaque` and `transparent` backgrounds. Transparent backgrounds + * are available for supported GPT Image models. For `gpt-image-2` and + * `gpt-image-2-2026-04-21`, this support is in preview. When using `transparent`, set + * the output format to `png` or `webp`. + */ + class Background + @JsonCreator + private constructor(private val value: JsonField) : Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that + * doesn't match any known member, and you want to know that value. For example, if + * the SDK is on an older version than the API, then the API may respond with new + * members that the SDK is unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val TRANSPARENT = of("transparent") + + @JvmField val OPAQUE = of("opaque") + + @JvmField val AUTO = of("auto") + + @JvmStatic fun of(value: String) = Background(JsonField.of(value)) + } + + /** An enum containing [Background]'s known values. */ + enum class Known { + TRANSPARENT, + OPAQUE, + AUTO, + } + + /** + * An enum containing [Background]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [Background] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, + * if the SDK is on an older version than the API, then the API may respond with + * new members that the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + TRANSPARENT, + OPAQUE, + AUTO, + /** + * An enum member indicating that [Background] was instantiated with an unknown + * value. + */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or + * [Value._UNKNOWN] if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if + * you want to throw for the unknown case. + */ + fun value(): Value = + when (this) { + TRANSPARENT -> Value.TRANSPARENT + OPAQUE -> Value.OPAQUE + AUTO -> Value.AUTO + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and + * don't want to throw for the unknown case. + * + * @throws OpenAIInvalidDataException if this class instance's value is a not a + * known member. + */ + fun known(): Known = + when (this) { + TRANSPARENT -> Known.TRANSPARENT + OPAQUE -> Known.OPAQUE + AUTO -> Known.AUTO + else -> throw OpenAIInvalidDataException("Unknown Background: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for + * debugging and generally doesn't throw. + * + * @throws OpenAIInvalidDataException if this class instance's value does not have + * the expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { + OpenAIInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws OpenAIInvalidDataException if any value type in this object doesn't match + * its expected type. + */ + fun validate(): Background = apply { + if (validated) { + return@apply + } + + known() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: OpenAIInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Background && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + /** + * Control how much effort the model will exert to match the style and features, + * especially facial features, of input images. Supports `high` and `low` on + * `gpt-image-1` and `gpt-image-1.5`; `gpt-image-1-mini` supports only `low`. For + * `gpt-image-2`, omit this parameter. Defaults to `low` on supported models. + */ + class InputFidelity + @JsonCreator + private constructor(private val value: JsonField) : Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that + * doesn't match any known member, and you want to know that value. For example, if + * the SDK is on an older version than the API, then the API may respond with new + * members that the SDK is unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val HIGH = of("high") + + @JvmField val LOW = of("low") + + @JvmStatic fun of(value: String) = InputFidelity(JsonField.of(value)) + } + + /** An enum containing [InputFidelity]'s known values. */ + enum class Known { + HIGH, + LOW, + } + + /** + * An enum containing [InputFidelity]'s known values, as well as an [_UNKNOWN] + * member. + * + * An instance of [InputFidelity] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, + * if the SDK is on an older version than the API, then the API may respond with + * new members that the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + HIGH, + LOW, + /** + * An enum member indicating that [InputFidelity] was instantiated with an + * unknown value. + */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or + * [Value._UNKNOWN] if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if + * you want to throw for the unknown case. + */ + fun value(): Value = + when (this) { + HIGH -> Value.HIGH + LOW -> Value.LOW + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and + * don't want to throw for the unknown case. + * + * @throws OpenAIInvalidDataException if this class instance's value is a not a + * known member. + */ + fun known(): Known = + when (this) { + HIGH -> Known.HIGH + LOW -> Known.LOW + else -> throw OpenAIInvalidDataException("Unknown InputFidelity: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for + * debugging and generally doesn't throw. + * + * @throws OpenAIInvalidDataException if this class instance's value does not have + * the expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { + OpenAIInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws OpenAIInvalidDataException if any value type in this object doesn't match + * its expected type. + */ + fun validate(): InputFidelity = apply { + if (validated) { + return@apply + } + + known() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: OpenAIInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is InputFidelity && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + /** + * Optional mask for inpainting. Contains `image_url` (string, optional) and `file_id` + * (string, optional). + */ + class InputImageMask + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val fileId: JsonField, + private val imageUrl: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("file_id") + @ExcludeMissing + fileId: JsonField = JsonMissing.of(), + @JsonProperty("image_url") + @ExcludeMissing + imageUrl: JsonField = JsonMissing.of(), + ) : this(fileId, imageUrl, mutableMapOf()) + + /** + * File ID for the mask image. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. + * if the server responded with an unexpected value). + */ + fun fileId(): Optional = fileId.getOptional("file_id") + + /** + * Base64-encoded mask image. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. + * if the server responded with an unexpected value). + */ + fun imageUrl(): Optional = imageUrl.getOptional("image_url") + + /** + * Returns the raw JSON value of [fileId]. + * + * Unlike [fileId], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("file_id") @ExcludeMissing fun _fileId(): JsonField = fileId + + /** + * Returns the raw JSON value of [imageUrl]. + * + * Unlike [imageUrl], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("image_url") + @ExcludeMissing + fun _imageUrl(): JsonField = imageUrl + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [InputImageMask]. + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [InputImageMask]. */ + class Builder internal constructor() { + + private var fileId: JsonField = JsonMissing.of() + private var imageUrl: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(inputImageMask: InputImageMask) = apply { + fileId = inputImageMask.fileId + imageUrl = inputImageMask.imageUrl + additionalProperties = inputImageMask.additionalProperties.toMutableMap() + } + + /** File ID for the mask image. */ + fun fileId(fileId: String) = fileId(JsonField.of(fileId)) + + /** + * Sets [Builder.fileId] to an arbitrary JSON value. + * + * You should usually call [Builder.fileId] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or + * not yet supported value. + */ + fun fileId(fileId: JsonField) = apply { this.fileId = fileId } + + /** Base64-encoded mask image. */ + fun imageUrl(imageUrl: String) = imageUrl(JsonField.of(imageUrl)) + + /** + * Sets [Builder.imageUrl] to an arbitrary JSON value. + * + * You should usually call [Builder.imageUrl] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or + * not yet supported value. + */ + fun imageUrl(imageUrl: JsonField) = apply { this.imageUrl = imageUrl } + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = + apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { + additionalProperties.remove(key) + } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [InputImageMask]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): InputImageMask = + InputImageMask(fileId, imageUrl, additionalProperties.toMutableMap()) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws OpenAIInvalidDataException if any value type in this object doesn't match + * its expected type. + */ + fun validate(): InputImageMask = apply { + if (validated) { + return@apply + } + + fileId() + imageUrl() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: OpenAIInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + (if (fileId.asKnown().isPresent) 1 else 0) + + (if (imageUrl.asKnown().isPresent) 1 else 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is InputImageMask && + fileId == other.fileId && + imageUrl == other.imageUrl && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(fileId, imageUrl, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "InputImageMask{fileId=$fileId, imageUrl=$imageUrl, additionalProperties=$additionalProperties}" + } + + /** + * The image generation model to use. One of `gpt-image-1`, `gpt-image-1-mini`, + * `gpt-image-1.5`, `gpt-image-2`, `gpt-image-2-2026-04-21`, `gpt-image-2.5-sunburst`, + * `gpt-image-2.5-sunburst-2026-09-08`, `gpt-image-2.5-flare`, + * `gpt-image-2.5-flare-2026-09-08`, or `chatgpt-image-latest`. Default: `gpt-image-1`. + */ + class Model @JsonCreator private constructor(private val value: JsonField) : + Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that + * doesn't match any known member, and you want to know that value. For example, if + * the SDK is on an older version than the API, then the API may respond with new + * members that the SDK is unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val GPT_IMAGE_1 = of("gpt-image-1") + + @JvmField val GPT_IMAGE_1_MINI = of("gpt-image-1-mini") + + @JvmField val GPT_IMAGE_2 = of("gpt-image-2") + + @JvmField val GPT_IMAGE_2_2026_04_21 = of("gpt-image-2-2026-04-21") + + @JvmField val GPT_IMAGE_2_5_SUNBURST = of("gpt-image-2.5-sunburst") + + @JvmField + val GPT_IMAGE_2_5_SUNBURST_2026_09_08 = of("gpt-image-2.5-sunburst-2026-09-08") + + @JvmField val GPT_IMAGE_2_5_FLARE = of("gpt-image-2.5-flare") + + @JvmField + val GPT_IMAGE_2_5_FLARE_2026_09_08 = of("gpt-image-2.5-flare-2026-09-08") + + @JvmField val GPT_IMAGE_1_5 = of("gpt-image-1.5") + + @JvmField val CHATGPT_IMAGE_LATEST = of("chatgpt-image-latest") + + @JvmStatic fun of(value: String) = Model(JsonField.of(value)) + } + + /** An enum containing [Model]'s known values. */ + enum class Known { + GPT_IMAGE_1, + GPT_IMAGE_1_MINI, + GPT_IMAGE_2, + GPT_IMAGE_2_2026_04_21, + GPT_IMAGE_2_5_SUNBURST, + GPT_IMAGE_2_5_SUNBURST_2026_09_08, + GPT_IMAGE_2_5_FLARE, + GPT_IMAGE_2_5_FLARE_2026_09_08, + GPT_IMAGE_1_5, + CHATGPT_IMAGE_LATEST, + } + + /** + * An enum containing [Model]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [Model] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, + * if the SDK is on an older version than the API, then the API may respond with + * new members that the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + GPT_IMAGE_1, + GPT_IMAGE_1_MINI, + GPT_IMAGE_2, + GPT_IMAGE_2_2026_04_21, + GPT_IMAGE_2_5_SUNBURST, + GPT_IMAGE_2_5_SUNBURST_2026_09_08, + GPT_IMAGE_2_5_FLARE, + GPT_IMAGE_2_5_FLARE_2026_09_08, + GPT_IMAGE_1_5, + CHATGPT_IMAGE_LATEST, + /** + * An enum member indicating that [Model] was instantiated with an unknown + * value. + */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or + * [Value._UNKNOWN] if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if + * you want to throw for the unknown case. + */ + fun value(): Value = + when (this) { + GPT_IMAGE_1 -> Value.GPT_IMAGE_1 + GPT_IMAGE_1_MINI -> Value.GPT_IMAGE_1_MINI + GPT_IMAGE_2 -> Value.GPT_IMAGE_2 + GPT_IMAGE_2_2026_04_21 -> Value.GPT_IMAGE_2_2026_04_21 + GPT_IMAGE_2_5_SUNBURST -> Value.GPT_IMAGE_2_5_SUNBURST + GPT_IMAGE_2_5_SUNBURST_2026_09_08 -> Value.GPT_IMAGE_2_5_SUNBURST_2026_09_08 + GPT_IMAGE_2_5_FLARE -> Value.GPT_IMAGE_2_5_FLARE + GPT_IMAGE_2_5_FLARE_2026_09_08 -> Value.GPT_IMAGE_2_5_FLARE_2026_09_08 + GPT_IMAGE_1_5 -> Value.GPT_IMAGE_1_5 + CHATGPT_IMAGE_LATEST -> Value.CHATGPT_IMAGE_LATEST + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and + * don't want to throw for the unknown case. + * + * @throws OpenAIInvalidDataException if this class instance's value is a not a + * known member. + */ + fun known(): Known = + when (this) { + GPT_IMAGE_1 -> Known.GPT_IMAGE_1 + GPT_IMAGE_1_MINI -> Known.GPT_IMAGE_1_MINI + GPT_IMAGE_2 -> Known.GPT_IMAGE_2 + GPT_IMAGE_2_2026_04_21 -> Known.GPT_IMAGE_2_2026_04_21 + GPT_IMAGE_2_5_SUNBURST -> Known.GPT_IMAGE_2_5_SUNBURST + GPT_IMAGE_2_5_SUNBURST_2026_09_08 -> Known.GPT_IMAGE_2_5_SUNBURST_2026_09_08 + GPT_IMAGE_2_5_FLARE -> Known.GPT_IMAGE_2_5_FLARE + GPT_IMAGE_2_5_FLARE_2026_09_08 -> Known.GPT_IMAGE_2_5_FLARE_2026_09_08 + GPT_IMAGE_1_5 -> Known.GPT_IMAGE_1_5 + CHATGPT_IMAGE_LATEST -> Known.CHATGPT_IMAGE_LATEST + else -> throw OpenAIInvalidDataException("Unknown Model: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for + * debugging and generally doesn't throw. + * + * @throws OpenAIInvalidDataException if this class instance's value does not have + * the expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { + OpenAIInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws OpenAIInvalidDataException if any value type in this object doesn't match + * its expected type. + */ + fun validate(): Model = apply { + if (validated) { + return@apply + } + + known() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: OpenAIInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Model && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + /** Moderation level for the generated image. Default: `auto`. */ + class Moderation + @JsonCreator + private constructor(private val value: JsonField) : Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that + * doesn't match any known member, and you want to know that value. For example, if + * the SDK is on an older version than the API, then the API may respond with new + * members that the SDK is unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val AUTO = of("auto") + + @JvmField val LOW = of("low") + + @JvmStatic fun of(value: String) = Moderation(JsonField.of(value)) + } + + /** An enum containing [Moderation]'s known values. */ + enum class Known { + AUTO, + LOW, + } + + /** + * An enum containing [Moderation]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [Moderation] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, + * if the SDK is on an older version than the API, then the API may respond with + * new members that the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + AUTO, + LOW, + /** + * An enum member indicating that [Moderation] was instantiated with an unknown + * value. + */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or + * [Value._UNKNOWN] if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if + * you want to throw for the unknown case. + */ + fun value(): Value = + when (this) { + AUTO -> Value.AUTO + LOW -> Value.LOW + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and + * don't want to throw for the unknown case. + * + * @throws OpenAIInvalidDataException if this class instance's value is a not a + * known member. + */ + fun known(): Known = + when (this) { + AUTO -> Known.AUTO + LOW -> Known.LOW + else -> throw OpenAIInvalidDataException("Unknown Moderation: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for + * debugging and generally doesn't throw. + * + * @throws OpenAIInvalidDataException if this class instance's value does not have + * the expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { + OpenAIInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws OpenAIInvalidDataException if any value type in this object doesn't match + * its expected type. + */ + fun validate(): Moderation = apply { + if (validated) { + return@apply + } + + known() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: OpenAIInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Moderation && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + /** + * The output format of the generated image. One of `png`, `webp`, or `jpeg`. Default: + * `png`. + */ + class OutputFormat + @JsonCreator + private constructor(private val value: JsonField) : Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that + * doesn't match any known member, and you want to know that value. For example, if + * the SDK is on an older version than the API, then the API may respond with new + * members that the SDK is unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val PNG = of("png") + + @JvmField val WEBP = of("webp") + + @JvmField val JPEG = of("jpeg") + + @JvmStatic fun of(value: String) = OutputFormat(JsonField.of(value)) + } + + /** An enum containing [OutputFormat]'s known values. */ + enum class Known { + PNG, + WEBP, + JPEG, + } + + /** + * An enum containing [OutputFormat]'s known values, as well as an [_UNKNOWN] + * member. + * + * An instance of [OutputFormat] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, + * if the SDK is on an older version than the API, then the API may respond with + * new members that the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + PNG, + WEBP, + JPEG, + /** + * An enum member indicating that [OutputFormat] was instantiated with an + * unknown value. + */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or + * [Value._UNKNOWN] if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if + * you want to throw for the unknown case. + */ + fun value(): Value = + when (this) { + PNG -> Value.PNG + WEBP -> Value.WEBP + JPEG -> Value.JPEG + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and + * don't want to throw for the unknown case. + * + * @throws OpenAIInvalidDataException if this class instance's value is a not a + * known member. + */ + fun known(): Known = + when (this) { + PNG -> Known.PNG + WEBP -> Known.WEBP + JPEG -> Known.JPEG + else -> throw OpenAIInvalidDataException("Unknown OutputFormat: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for + * debugging and generally doesn't throw. + * + * @throws OpenAIInvalidDataException if this class instance's value does not have + * the expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { + OpenAIInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws OpenAIInvalidDataException if any value type in this object doesn't match + * its expected type. + */ + fun validate(): OutputFormat = apply { + if (validated) { + return@apply + } + + known() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: OpenAIInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is OutputFormat && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + /** + * The quality of the generated image. The GPT image models support `low`, `medium`, and + * `high`. `gpt-image-2.5-sunburst` and `gpt-image-2.5-flare`, including their + * `2026-09-08` snapshots, also support `xhigh` and `max`. Default: `auto`. + */ + class Quality @JsonCreator private constructor(private val value: JsonField) : + Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that + * doesn't match any known member, and you want to know that value. For example, if + * the SDK is on an older version than the API, then the API may respond with new + * members that the SDK is unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val LOW = of("low") + + @JvmField val MEDIUM = of("medium") + + @JvmField val HIGH = of("high") + + @JvmField val XHIGH = of("xhigh") + + @JvmField val MAX = of("max") + + @JvmField val AUTO = of("auto") + + @JvmStatic fun of(value: String) = Quality(JsonField.of(value)) + } + + /** An enum containing [Quality]'s known values. */ + enum class Known { + LOW, + MEDIUM, + HIGH, + XHIGH, + MAX, + AUTO, + } + + /** + * An enum containing [Quality]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [Quality] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, + * if the SDK is on an older version than the API, then the API may respond with + * new members that the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + LOW, + MEDIUM, + HIGH, + XHIGH, + MAX, + AUTO, + /** + * An enum member indicating that [Quality] was instantiated with an unknown + * value. + */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or + * [Value._UNKNOWN] if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if + * you want to throw for the unknown case. + */ + fun value(): Value = + when (this) { + LOW -> Value.LOW + MEDIUM -> Value.MEDIUM + HIGH -> Value.HIGH + XHIGH -> Value.XHIGH + MAX -> Value.MAX + AUTO -> Value.AUTO + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and + * don't want to throw for the unknown case. + * + * @throws OpenAIInvalidDataException if this class instance's value is a not a + * known member. + */ + fun known(): Known = + when (this) { + LOW -> Known.LOW + MEDIUM -> Known.MEDIUM + HIGH -> Known.HIGH + XHIGH -> Known.XHIGH + MAX -> Known.MAX + AUTO -> Known.AUTO + else -> throw OpenAIInvalidDataException("Unknown Quality: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for + * debugging and generally doesn't throw. + * + * @throws OpenAIInvalidDataException if this class instance's value does not have + * the expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { + OpenAIInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws OpenAIInvalidDataException if any value type in this object doesn't match + * its expected type. + */ + fun validate(): Quality = apply { + if (validated) { + return@apply + } + + known() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: OpenAIInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Quality && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + /** + * The size of the generated images. For `gpt-image-2`, `gpt-image-2-2026-04-21`, + * `gpt-image-2.5-sunburst`, `gpt-image-2.5-sunburst-2026-09-08`, `gpt-image-2.5-flare`, + * and `gpt-image-2.5-flare-2026-09-08`, arbitrary resolutions are supported as + * `WIDTHxHEIGHT` strings, for example `1536x864`. Width and height must both be + * divisible by 16 and the requested aspect ratio must be between 1:3 and 3:1. + * Resolutions above `2560x1440` are experimental, and the maximum supported resolution + * is `3840x2160`. The requested size must also satisfy the model's current pixel and + * edge limits. The standard sizes `1024x1024`, `1536x1024`, and `1024x1536` are + * supported by the GPT image models; `auto` is supported for models that allow + * automatic sizing. + */ + class Size @JsonCreator private constructor(private val value: JsonField) : + Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that + * doesn't match any known member, and you want to know that value. For example, if + * the SDK is on an older version than the API, then the API may respond with new + * members that the SDK is unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val _1024X1024 = of("1024x1024") + + @JvmField val _1024X1536 = of("1024x1536") + + @JvmField val _1536X1024 = of("1536x1024") + + @JvmField val AUTO = of("auto") + + @JvmStatic fun of(value: String) = Size(JsonField.of(value)) + } + + /** An enum containing [Size]'s known values. */ + enum class Known { + _1024X1024, + _1024X1536, + _1536X1024, + AUTO, + } + + /** + * An enum containing [Size]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [Size] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, + * if the SDK is on an older version than the API, then the API may respond with + * new members that the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + _1024X1024, + _1024X1536, + _1536X1024, + AUTO, + /** + * An enum member indicating that [Size] was instantiated with an unknown value. + */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or + * [Value._UNKNOWN] if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if + * you want to throw for the unknown case. + */ + fun value(): Value = + when (this) { + _1024X1024 -> Value._1024X1024 + _1024X1536 -> Value._1024X1536 + _1536X1024 -> Value._1536X1024 + AUTO -> Value.AUTO + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and + * don't want to throw for the unknown case. + * + * @throws OpenAIInvalidDataException if this class instance's value is a not a + * known member. + */ + fun known(): Known = + when (this) { + _1024X1024 -> Known._1024X1024 + _1024X1536 -> Known._1024X1536 + _1536X1024 -> Known._1536X1024 + AUTO -> Known.AUTO + else -> throw OpenAIInvalidDataException("Unknown Size: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for + * debugging and generally doesn't throw. + * + * @throws OpenAIInvalidDataException if this class instance's value does not have + * the expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { + OpenAIInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws OpenAIInvalidDataException if any value type in this object doesn't match + * its expected type. + */ + fun validate(): Size = apply { + if (validated) { + return@apply + } + + known() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: OpenAIInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Size && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is ImageGeneration && + type == other.type && + action == other.action && + background == other.background && + inputFidelity == other.inputFidelity && + inputImageMask == other.inputImageMask && + model == other.model && + moderation == other.moderation && + outputCompression == other.outputCompression && + outputFormat == other.outputFormat && + partialImages == other.partialImages && + quality == other.quality && + size == other.size && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash( + type, + action, + background, + inputFidelity, + inputImageMask, + model, + moderation, + outputCompression, + outputFormat, + partialImages, + quality, + size, + additionalProperties, + ) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "ImageGeneration{type=$type, action=$action, background=$background, inputFidelity=$inputFidelity, inputImageMask=$inputImageMask, model=$model, moderation=$moderation, outputCompression=$outputCompression, outputFormat=$outputFormat, partialImages=$partialImages, quality=$quality, size=$size, additionalProperties=$additionalProperties}" + } + } + /** The agent that produced this item. */ class Agent @JsonCreator(mode = JsonCreator.Mode.DISABLED) diff --git a/openai-java-core/src/main/kotlin/com/openai/models/beta/responses/BetaToolSearchOutputNamespaceTool.kt b/openai-java-core/src/main/kotlin/com/openai/models/beta/responses/BetaToolSearchOutputNamespaceTool.kt new file mode 100644 index 000000000..48e3be845 --- /dev/null +++ b/openai-java-core/src/main/kotlin/com/openai/models/beta/responses/BetaToolSearchOutputNamespaceTool.kt @@ -0,0 +1,1383 @@ +// File generated from our OpenAPI spec by Castiron. See CONTRIBUTING.md for details. + +package com.openai.models.beta.responses + +import com.fasterxml.jackson.annotation.JsonAnyGetter +import com.fasterxml.jackson.annotation.JsonAnySetter +import com.fasterxml.jackson.annotation.JsonCreator +import com.fasterxml.jackson.annotation.JsonProperty +import com.fasterxml.jackson.core.JsonGenerator +import com.fasterxml.jackson.core.ObjectCodec +import com.fasterxml.jackson.databind.JsonNode +import com.fasterxml.jackson.databind.SerializerProvider +import com.fasterxml.jackson.databind.annotation.JsonDeserialize +import com.fasterxml.jackson.databind.annotation.JsonSerialize +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import com.openai.core.BaseDeserializer +import com.openai.core.BaseSerializer +import com.openai.core.Enum +import com.openai.core.ExcludeMissing +import com.openai.core.JsonField +import com.openai.core.JsonMissing +import com.openai.core.JsonValue +import com.openai.core.checkKnown +import com.openai.core.checkRequired +import com.openai.core.getOrThrow +import com.openai.core.toImmutable +import com.openai.errors.OpenAIInvalidDataException +import java.util.Collections +import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +/** Groups function/custom tools under a shared namespace. */ +class BetaToolSearchOutputNamespaceTool +@JsonCreator(mode = JsonCreator.Mode.DISABLED) +private constructor( + private val description: JsonField, + private val name: JsonField, + private val tools: JsonField>, + private val type: JsonValue, + private val additionalProperties: MutableMap, +) { + + @JsonCreator + private constructor( + @JsonProperty("description") + @ExcludeMissing + description: JsonField = JsonMissing.of(), + @JsonProperty("name") @ExcludeMissing name: JsonField = JsonMissing.of(), + @JsonProperty("tools") @ExcludeMissing tools: JsonField> = JsonMissing.of(), + @JsonProperty("type") @ExcludeMissing type: JsonValue = JsonMissing.of(), + ) : this(description, name, tools, type, mutableMapOf()) + + /** + * A description of the namespace shown to the model. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun description(): String = description.getRequired("description") + + /** + * The namespace name used in tool calls (for example, `crm`). + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun name(): String = name.getRequired("name") + + /** + * The function/custom tools loaded inside this namespace. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun tools(): List = tools.getRequired("tools") + + /** + * The type of the tool. Always `namespace`. + * + * Expected to always return the following: + * ```java + * JsonValue.from("namespace") + * ``` + * + * However, this method can be useful for debugging and logging (e.g. if the server responded + * with an unexpected value). + */ + @JsonProperty("type") @ExcludeMissing fun _type(): JsonValue = type + + /** + * Returns the raw JSON value of [description]. + * + * Unlike [description], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("description") @ExcludeMissing fun _description(): JsonField = description + + /** + * Returns the raw JSON value of [name]. + * + * Unlike [name], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("name") @ExcludeMissing fun _name(): JsonField = name + + /** + * Returns the raw JSON value of [tools]. + * + * Unlike [tools], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("tools") @ExcludeMissing fun _tools(): JsonField> = tools + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of + * [BetaToolSearchOutputNamespaceTool]. + * + * The following fields are required: + * ```java + * .description() + * .name() + * .tools() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [BetaToolSearchOutputNamespaceTool]. */ + class Builder internal constructor() { + + private var description: JsonField? = null + private var name: JsonField? = null + private var tools: JsonField>? = null + private var type: JsonValue = JsonValue.from("namespace") + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(betaToolSearchOutputNamespaceTool: BetaToolSearchOutputNamespaceTool) = + apply { + description = betaToolSearchOutputNamespaceTool.description + name = betaToolSearchOutputNamespaceTool.name + tools = betaToolSearchOutputNamespaceTool.tools.map { it.toMutableList() } + type = betaToolSearchOutputNamespaceTool.type + additionalProperties = + betaToolSearchOutputNamespaceTool.additionalProperties.toMutableMap() + } + + /** A description of the namespace shown to the model. */ + fun description(description: String) = description(JsonField.of(description)) + + /** + * Sets [Builder.description] to an arbitrary JSON value. + * + * You should usually call [Builder.description] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun description(description: JsonField) = apply { this.description = description } + + /** The namespace name used in tool calls (for example, `crm`). */ + fun name(name: String) = name(JsonField.of(name)) + + /** + * Sets [Builder.name] to an arbitrary JSON value. + * + * You should usually call [Builder.name] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun name(name: JsonField) = apply { this.name = name } + + /** The function/custom tools loaded inside this namespace. */ + fun tools(tools: List) = tools(JsonField.of(tools)) + + /** + * Sets [Builder.tools] to an arbitrary JSON value. + * + * You should usually call [Builder.tools] with a well-typed `List` value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun tools(tools: JsonField>) = apply { + this.tools = tools.map { it.toMutableList() } + } + + /** + * Adds a single [Tool] to [tools]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addTool(tool: Tool) = apply { + tools = + (tools ?: JsonField.of(mutableListOf())).also { checkKnown("tools", it).add(tool) } + } + + /** Alias for calling [addTool] with `Tool.ofFunction(function)`. */ + fun addTool(function: Tool.Function) = addTool(Tool.ofFunction(function)) + + /** + * Alias for calling [addTool] with the following: + * ```java + * Tool.Function.builder() + * .name(name) + * .build() + * ``` + */ + fun addFunctionTool(name: String) = addTool(Tool.Function.builder().name(name).build()) + + /** Alias for calling [addTool] with `Tool.ofCustom(custom)`. */ + fun addTool(custom: BetaCustomTool) = addTool(Tool.ofCustom(custom)) + + /** + * Alias for calling [addTool] with the following: + * ```java + * BetaCustomTool.builder() + * .name(name) + * .build() + * ``` + */ + fun addCustomTool(name: String) = addTool(BetaCustomTool.builder().name(name).build()) + + /** + * Sets the field to an arbitrary JSON value. + * + * It is usually unnecessary to call this method because the field defaults to the + * following: + * ```java + * JsonValue.from("namespace") + * ``` + * + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun type(type: JsonValue) = apply { this.type = type } + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { additionalProperties.remove(key) } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [BetaToolSearchOutputNamespaceTool]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .description() + * .name() + * .tools() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): BetaToolSearchOutputNamespaceTool = + BetaToolSearchOutputNamespaceTool( + checkRequired("description", description), + checkRequired("name", name), + checkRequired("tools", tools).map { it.toImmutable() }, + type, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws OpenAIInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): BetaToolSearchOutputNamespaceTool = apply { + if (validated) { + return@apply + } + + description() + name() + tools().forEach { it.validate() } + _type().let { + if (it != JsonValue.from("namespace")) { + throw OpenAIInvalidDataException("'type' is invalid, received $it") + } + } + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: OpenAIInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + (if (description.asKnown().isPresent) 1 else 0) + + (if (name.asKnown().isPresent) 1 else 0) + + (tools.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + + type.let { if (it == JsonValue.from("namespace")) 1 else 0 } + + /** A function or custom tool loaded into a namespace by tool search. */ + @JsonDeserialize(using = Tool.Deserializer::class) + @JsonSerialize(using = Tool.Serializer::class) + class Tool + private constructor( + private val function: Function? = null, + private val custom: BetaCustomTool? = null, + private val _json: JsonValue? = null, + ) { + + fun function(): Optional = Optional.ofNullable(function) + + /** + * A custom tool that processes input using a specified format. Learn more about + * [custom tools](https://developers.openai.com/api/docs/guides/function-calling#custom-tools) + */ + fun custom(): Optional = Optional.ofNullable(custom) + + fun isFunction(): Boolean = function != null + + fun isCustom(): Boolean = custom != null + + fun asFunction(): Function = function.getOrThrow("function") + + /** + * A custom tool that processes input using a specified format. Learn more about + * [custom tools](https://developers.openai.com/api/docs/guides/function-calling#custom-tools) + */ + fun asCustom(): BetaCustomTool = custom.getOrThrow("custom") + + fun _json(): Optional = Optional.ofNullable(_json) + + /** + * Maps this instance's current variant to a value of type [T] using the given [visitor]. + * + * Note that this method is _not_ forwards compatible with new variants from the API, unless + * [visitor] overrides [Visitor.unknown]. To handle variants not known to this version of + * the SDK gracefully, consider overriding [Visitor.unknown]: + * ```java + * import com.openai.core.JsonValue; + * import java.util.Optional; + * + * Optional result = tool.accept(new Tool.Visitor>() { + * @Override + * public Optional visitFunction(Function function) { + * return Optional.of(function.toString()); + * } + * + * // ... + * + * @Override + * public Optional unknown(JsonValue json) { + * // Or inspect the `json`. + * return Optional.empty(); + * } + * }); + * ``` + * + * @throws OpenAIInvalidDataException if [Visitor.unknown] is not overridden in [visitor] + * and the current variant is unknown. + */ + fun accept(visitor: Visitor): T = + when { + function != null -> visitor.visitFunction(function) + custom != null -> visitor.visitCustom(custom) + else -> visitor.unknown(_json) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws OpenAIInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): Tool = apply { + if (validated) { + return@apply + } + + accept( + object : Visitor { + override fun visitFunction(function: Function) { + function.validate() + } + + override fun visitCustom(custom: BetaCustomTool) { + custom.validate() + } + } + ) + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: OpenAIInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + accept( + object : Visitor { + override fun visitFunction(function: Function) = function.validity() + + override fun visitCustom(custom: BetaCustomTool) = custom.validity() + + override fun unknown(json: JsonValue?) = 0 + } + ) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Tool && function == other.function && custom == other.custom + } + + override fun hashCode(): Int = Objects.hash(function, custom) + + override fun toString(): String = + when { + function != null -> "Tool{function=$function}" + custom != null -> "Tool{custom=$custom}" + _json != null -> "Tool{_unknown=$_json}" + else -> throw IllegalStateException("Invalid Tool") + } + + companion object { + + @JvmStatic fun ofFunction(function: Function) = Tool(function = function) + + /** + * A custom tool that processes input using a specified format. Learn more about + * [custom tools](https://developers.openai.com/api/docs/guides/function-calling#custom-tools) + */ + @JvmStatic fun ofCustom(custom: BetaCustomTool) = Tool(custom = custom) + } + + /** An interface that defines how to map each variant of [Tool] to a value of type [T]. */ + interface Visitor { + + fun visitFunction(function: Function): T + + /** + * A custom tool that processes input using a specified format. Learn more about + * [custom tools](https://developers.openai.com/api/docs/guides/function-calling#custom-tools) + */ + fun visitCustom(custom: BetaCustomTool): T + + /** + * Maps an unknown variant of [Tool] to a value of type [T]. + * + * An instance of [Tool] can contain an unknown variant if it was deserialized from data + * that doesn't match any known variant. For example, if the SDK is on an older version + * than the API, then the API may respond with new variants that the SDK is unaware of. + * + * @throws OpenAIInvalidDataException in the default implementation. + */ + fun unknown(json: JsonValue?): T { + throw OpenAIInvalidDataException("Unknown Tool") + } + } + + internal class Deserializer : BaseDeserializer(Tool::class) { + + override fun ObjectCodec.deserialize(node: JsonNode): Tool { + val json = JsonValue.fromJsonNode(node) + val type = json.asObject().getOrNull()?.get("type")?.asString()?.getOrNull() + + when (type) { + "function" -> { + return tryDeserialize(node, jacksonTypeRef())?.let { + Tool(function = it, _json = json) + } ?: Tool(_json = json) + } + "custom" -> { + return tryDeserialize(node, jacksonTypeRef())?.let { + Tool(custom = it, _json = json) + } ?: Tool(_json = json) + } + } + + return Tool(_json = json) + } + } + + internal class Serializer : BaseSerializer(Tool::class) { + + override fun serialize( + value: Tool, + generator: JsonGenerator, + provider: SerializerProvider, + ) { + when { + value.function != null -> generator.writeObject(value.function) + value.custom != null -> generator.writeObject(value.custom) + value._json != null -> generator.writeObject(value._json) + else -> throw IllegalStateException("Invalid Tool") + } + } + } + + class Function + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val name: JsonField, + private val type: JsonValue, + private val allowedCallers: JsonField>, + private val async: JsonField, + private val deferLoading: JsonField, + private val description: JsonField, + private val outputSchema: JsonField, + private val parameters: JsonValue, + private val strict: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("name") @ExcludeMissing name: JsonField = JsonMissing.of(), + @JsonProperty("type") @ExcludeMissing type: JsonValue = JsonMissing.of(), + @JsonProperty("allowed_callers") + @ExcludeMissing + allowedCallers: JsonField> = JsonMissing.of(), + @JsonProperty("async") @ExcludeMissing async: JsonField = JsonMissing.of(), + @JsonProperty("defer_loading") + @ExcludeMissing + deferLoading: JsonField = JsonMissing.of(), + @JsonProperty("description") + @ExcludeMissing + description: JsonField = JsonMissing.of(), + @JsonProperty("output_schema") + @ExcludeMissing + outputSchema: JsonField = JsonMissing.of(), + @JsonProperty("parameters") + @ExcludeMissing + parameters: JsonValue = JsonMissing.of(), + @JsonProperty("strict") + @ExcludeMissing + strict: JsonField = JsonMissing.of(), + ) : this( + name, + type, + allowedCallers, + async, + deferLoading, + description, + outputSchema, + parameters, + strict, + mutableMapOf(), + ) + + /** + * The name of the loaded function tool. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected + * value). + */ + fun name(): String = name.getRequired("name") + + /** + * Expected to always return the following: + * ```java + * JsonValue.from("function") + * ``` + * + * However, this method can be useful for debugging and logging (e.g. if the server + * responded with an unexpected value). + */ + @JsonProperty("type") @ExcludeMissing fun _type(): JsonValue = type + + /** + * The tool invocation context(s). + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun allowedCallers(): Optional> = + allowedCallers.getOptional("allowed_callers") + + /** + * Whether the tool response can be returned asynchronously versus immediately returned + * on next response creation. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun async(): Optional = async.getOptional("async") + + /** + * Whether this function should be deferred and discovered via tool search. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun deferLoading(): Optional = deferLoading.getOptional("defer_loading") + + /** + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun description(): Optional = description.getOptional("description") + + /** + * A JSON Schema describing the JSON value encoded in string outputs for this function + * tool. This does not describe content-array outputs. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun outputSchema(): Optional = outputSchema.getOptional("output_schema") + + /** + * This arbitrary value can be deserialized into a custom type using the `convert` + * method: + * ```java + * MyClass myObject = function.parameters().convert(MyClass.class); + * ``` + */ + @JsonProperty("parameters") @ExcludeMissing fun _parameters(): JsonValue = parameters + + /** + * Whether to enforce strict parameter validation. If omitted, Responses attempts to use + * strict validation when the schema is compatible, and falls back to non-strict + * validation otherwise. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun strict(): Optional = strict.getOptional("strict") + + /** + * Returns the raw JSON value of [name]. + * + * Unlike [name], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("name") @ExcludeMissing fun _name(): JsonField = name + + /** + * Returns the raw JSON value of [allowedCallers]. + * + * Unlike [allowedCallers], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("allowed_callers") + @ExcludeMissing + fun _allowedCallers(): JsonField> = allowedCallers + + /** + * Returns the raw JSON value of [async]. + * + * Unlike [async], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("async") @ExcludeMissing fun _async(): JsonField = async + + /** + * Returns the raw JSON value of [deferLoading]. + * + * Unlike [deferLoading], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("defer_loading") + @ExcludeMissing + fun _deferLoading(): JsonField = deferLoading + + /** + * Returns the raw JSON value of [description]. + * + * Unlike [description], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("description") + @ExcludeMissing + fun _description(): JsonField = description + + /** + * Returns the raw JSON value of [outputSchema]. + * + * Unlike [outputSchema], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("output_schema") + @ExcludeMissing + fun _outputSchema(): JsonField = outputSchema + + /** + * Returns the raw JSON value of [strict]. + * + * Unlike [strict], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("strict") @ExcludeMissing fun _strict(): JsonField = strict + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [Function]. + * + * The following fields are required: + * ```java + * .name() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Function]. */ + class Builder internal constructor() { + + private var name: JsonField? = null + private var type: JsonValue = JsonValue.from("function") + private var allowedCallers: JsonField>? = null + private var async: JsonField = JsonMissing.of() + private var deferLoading: JsonField = JsonMissing.of() + private var description: JsonField = JsonMissing.of() + private var outputSchema: JsonField = JsonMissing.of() + private var parameters: JsonValue = JsonMissing.of() + private var strict: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(function: Function) = apply { + name = function.name + type = function.type + allowedCallers = function.allowedCallers.map { it.toMutableList() } + async = function.async + deferLoading = function.deferLoading + description = function.description + outputSchema = function.outputSchema + parameters = function.parameters + strict = function.strict + additionalProperties = function.additionalProperties.toMutableMap() + } + + /** The name of the loaded function tool. */ + fun name(name: String) = name(JsonField.of(name)) + + /** + * Sets [Builder.name] to an arbitrary JSON value. + * + * You should usually call [Builder.name] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun name(name: JsonField) = apply { this.name = name } + + /** + * Sets the field to an arbitrary JSON value. + * + * It is usually unnecessary to call this method because the field defaults to the + * following: + * ```java + * JsonValue.from("function") + * ``` + * + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun type(type: JsonValue) = apply { this.type = type } + + /** The tool invocation context(s). */ + fun allowedCallers(allowedCallers: List?) = + allowedCallers(JsonField.ofNullable(allowedCallers)) + + /** + * Alias for calling [Builder.allowedCallers] with `allowedCallers.orElse(null)`. + */ + fun allowedCallers(allowedCallers: Optional>) = + allowedCallers(allowedCallers.getOrNull()) + + /** + * Sets [Builder.allowedCallers] to an arbitrary JSON value. + * + * You should usually call [Builder.allowedCallers] with a well-typed + * `List` value instead. This method is primarily for setting the + * field to an undocumented or not yet supported value. + */ + fun allowedCallers(allowedCallers: JsonField>) = apply { + this.allowedCallers = allowedCallers.map { it.toMutableList() } + } + + /** + * Adds a single [AllowedCaller] to [allowedCallers]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addAllowedCaller(allowedCaller: AllowedCaller) = apply { + allowedCallers = + (allowedCallers ?: JsonField.of(mutableListOf())).also { + checkKnown("allowedCallers", it).add(allowedCaller) + } + } + + /** + * Whether the tool response can be returned asynchronously versus immediately + * returned on next response creation. + */ + fun async(async: Boolean) = async(JsonField.of(async)) + + /** + * Sets [Builder.async] to an arbitrary JSON value. + * + * You should usually call [Builder.async] with a well-typed [Boolean] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun async(async: JsonField) = apply { this.async = async } + + /** Whether this function should be deferred and discovered via tool search. */ + fun deferLoading(deferLoading: Boolean) = deferLoading(JsonField.of(deferLoading)) + + /** + * Sets [Builder.deferLoading] to an arbitrary JSON value. + * + * You should usually call [Builder.deferLoading] with a well-typed [Boolean] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun deferLoading(deferLoading: JsonField) = apply { + this.deferLoading = deferLoading + } + + fun description(description: String?) = + description(JsonField.ofNullable(description)) + + /** Alias for calling [Builder.description] with `description.orElse(null)`. */ + fun description(description: Optional) = + description(description.getOrNull()) + + /** + * Sets [Builder.description] to an arbitrary JSON value. + * + * You should usually call [Builder.description] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun description(description: JsonField) = apply { + this.description = description + } + + /** + * A JSON Schema describing the JSON value encoded in string outputs for this + * function tool. This does not describe content-array outputs. + */ + fun outputSchema(outputSchema: OutputSchema?) = + outputSchema(JsonField.ofNullable(outputSchema)) + + /** Alias for calling [Builder.outputSchema] with `outputSchema.orElse(null)`. */ + fun outputSchema(outputSchema: Optional) = + outputSchema(outputSchema.getOrNull()) + + /** + * Sets [Builder.outputSchema] to an arbitrary JSON value. + * + * You should usually call [Builder.outputSchema] with a well-typed [OutputSchema] + * value instead. This method is primarily for setting the field to an undocumented + * or not yet supported value. + */ + fun outputSchema(outputSchema: JsonField) = apply { + this.outputSchema = outputSchema + } + + fun parameters(parameters: JsonValue) = apply { this.parameters = parameters } + + /** + * Whether to enforce strict parameter validation. If omitted, Responses attempts to + * use strict validation when the schema is compatible, and falls back to non-strict + * validation otherwise. + */ + fun strict(strict: Boolean?) = strict(JsonField.ofNullable(strict)) + + /** + * Alias for [Builder.strict]. + * + * This unboxed primitive overload exists for backwards compatibility. + */ + fun strict(strict: Boolean) = strict(strict as Boolean?) + + /** Alias for calling [Builder.strict] with `strict.orElse(null)`. */ + fun strict(strict: Optional) = strict(strict.getOrNull()) + + /** + * Sets [Builder.strict] to an arbitrary JSON value. + * + * You should usually call [Builder.strict] with a well-typed [Boolean] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun strict(strict: JsonField) = apply { this.strict = strict } + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = + apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { + additionalProperties.remove(key) + } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [Function]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .name() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): Function = + Function( + checkRequired("name", name), + type, + (allowedCallers ?: JsonMissing.of()).map { it.toImmutable() }, + async, + deferLoading, + description, + outputSchema, + parameters, + strict, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws OpenAIInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): Function = apply { + if (validated) { + return@apply + } + + name() + _type().let { + if (it != JsonValue.from("function")) { + throw OpenAIInvalidDataException("'type' is invalid, received $it") + } + } + allowedCallers().ifPresent { it.forEach { it.validate() } } + async() + deferLoading() + description() + outputSchema().ifPresent { it.validate() } + strict() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: OpenAIInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + (if (name.asKnown().isPresent) 1 else 0) + + type.let { if (it == JsonValue.from("function")) 1 else 0 } + + (allowedCallers.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + + (if (async.asKnown().isPresent) 1 else 0) + + (if (deferLoading.asKnown().isPresent) 1 else 0) + + (if (description.asKnown().isPresent) 1 else 0) + + (outputSchema.asKnown().getOrNull()?.validity() ?: 0) + + (if (strict.asKnown().isPresent) 1 else 0) + + class AllowedCaller + @JsonCreator + private constructor(private val value: JsonField) : Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that + * doesn't match any known member, and you want to know that value. For example, if + * the SDK is on an older version than the API, then the API may respond with new + * members that the SDK is unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val DIRECT = of("direct") + + @JvmField val PROGRAMMATIC = of("programmatic") + + @JvmStatic fun of(value: String) = AllowedCaller(JsonField.of(value)) + } + + /** An enum containing [AllowedCaller]'s known values. */ + enum class Known { + DIRECT, + PROGRAMMATIC, + } + + /** + * An enum containing [AllowedCaller]'s known values, as well as an [_UNKNOWN] + * member. + * + * An instance of [AllowedCaller] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, + * if the SDK is on an older version than the API, then the API may respond with + * new members that the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + DIRECT, + PROGRAMMATIC, + /** + * An enum member indicating that [AllowedCaller] was instantiated with an + * unknown value. + */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or + * [Value._UNKNOWN] if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if + * you want to throw for the unknown case. + */ + fun value(): Value = + when (this) { + DIRECT -> Value.DIRECT + PROGRAMMATIC -> Value.PROGRAMMATIC + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and + * don't want to throw for the unknown case. + * + * @throws OpenAIInvalidDataException if this class instance's value is a not a + * known member. + */ + fun known(): Known = + when (this) { + DIRECT -> Known.DIRECT + PROGRAMMATIC -> Known.PROGRAMMATIC + else -> throw OpenAIInvalidDataException("Unknown AllowedCaller: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for + * debugging and generally doesn't throw. + * + * @throws OpenAIInvalidDataException if this class instance's value does not have + * the expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { + OpenAIInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws OpenAIInvalidDataException if any value type in this object doesn't match + * its expected type. + */ + fun validate(): AllowedCaller = apply { + if (validated) { + return@apply + } + + known() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: OpenAIInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is AllowedCaller && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + /** + * A JSON Schema describing the JSON value encoded in string outputs for this function + * tool. This does not describe content-array outputs. + */ + class OutputSchema + @JsonCreator + private constructor( + @com.fasterxml.jackson.annotation.JsonValue + private val additionalProperties: Map + ) { + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = additionalProperties + + fun toBuilder() = Builder().from(this) + + companion object { + + /** Returns a mutable builder for constructing an instance of [OutputSchema]. */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [OutputSchema]. */ + class Builder internal constructor() { + + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(outputSchema: OutputSchema) = apply { + additionalProperties = outputSchema.additionalProperties.toMutableMap() + } + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = + apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { + additionalProperties.remove(key) + } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [OutputSchema]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): OutputSchema = OutputSchema(additionalProperties.toImmutable()) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws OpenAIInvalidDataException if any value type in this object doesn't match + * its expected type. + */ + fun validate(): OutputSchema = apply { + if (validated) { + return@apply + } + + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: OpenAIInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + additionalProperties.count { (_, value) -> + !value.isNull() && !value.isMissing() + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is OutputSchema && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(additionalProperties) } + + override fun hashCode(): Int = hashCode + + override fun toString() = "OutputSchema{additionalProperties=$additionalProperties}" + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Function && + name == other.name && + type == other.type && + allowedCallers == other.allowedCallers && + async == other.async && + deferLoading == other.deferLoading && + description == other.description && + outputSchema == other.outputSchema && + parameters == other.parameters && + strict == other.strict && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash( + name, + type, + allowedCallers, + async, + deferLoading, + description, + outputSchema, + parameters, + strict, + additionalProperties, + ) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Function{name=$name, type=$type, allowedCallers=$allowedCallers, async=$async, deferLoading=$deferLoading, description=$description, outputSchema=$outputSchema, parameters=$parameters, strict=$strict, additionalProperties=$additionalProperties}" + } + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is BetaToolSearchOutputNamespaceTool && + description == other.description && + name == other.name && + tools == other.tools && + type == other.type && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(description, name, tools, type, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "BetaToolSearchOutputNamespaceTool{description=$description, name=$name, tools=$tools, type=$type, additionalProperties=$additionalProperties}" +} diff --git a/openai-java-core/src/main/kotlin/com/openai/models/conversations/ConversationCreateParams.kt b/openai-java-core/src/main/kotlin/com/openai/models/conversations/ConversationCreateParams.kt index 19098f4ad..9d9dec3f3 100644 --- a/openai-java-core/src/main/kotlin/com/openai/models/conversations/ConversationCreateParams.kt +++ b/openai-java-core/src/main/kotlin/com/openai/models/conversations/ConversationCreateParams.kt @@ -265,7 +265,7 @@ private constructor( * .build() * ``` */ - fun addToolSearchOutputItem(tools: List) = apply { + fun addToolSearchOutputItem(tools: List) = apply { body.addToolSearchOutputItem(tools) } @@ -832,7 +832,7 @@ private constructor( * .build() * ``` */ - fun addToolSearchOutputItem(tools: List) = + fun addToolSearchOutputItem(tools: List) = addItem(ResponseToolSearchOutputItemParam.builder().tools(tools).build()) /** diff --git a/openai-java-core/src/main/kotlin/com/openai/models/conversations/items/ItemCreateParams.kt b/openai-java-core/src/main/kotlin/com/openai/models/conversations/items/ItemCreateParams.kt index 9ae674206..7a9ecc038 100644 --- a/openai-java-core/src/main/kotlin/com/openai/models/conversations/items/ItemCreateParams.kt +++ b/openai-java-core/src/main/kotlin/com/openai/models/conversations/items/ItemCreateParams.kt @@ -287,7 +287,7 @@ private constructor( * .build() * ``` */ - fun addToolSearchOutputItem(tools: List) = apply { + fun addToolSearchOutputItem(tools: List) = apply { body.addToolSearchOutputItem(tools) } @@ -827,7 +827,7 @@ private constructor( * .build() * ``` */ - fun addToolSearchOutputItem(tools: List) = + fun addToolSearchOutputItem(tools: List) = addItem(ResponseToolSearchOutputItemParam.builder().tools(tools).build()) /** diff --git a/openai-java-core/src/main/kotlin/com/openai/models/decisions/Decision.kt b/openai-java-core/src/main/kotlin/com/openai/models/decisions/Decision.kt new file mode 100644 index 000000000..925812ba2 --- /dev/null +++ b/openai-java-core/src/main/kotlin/com/openai/models/decisions/Decision.kt @@ -0,0 +1,2984 @@ +// File generated from our OpenAPI spec by Castiron. See CONTRIBUTING.md for details. + +package com.openai.models.decisions + +import com.fasterxml.jackson.annotation.JsonAnyGetter +import com.fasterxml.jackson.annotation.JsonAnySetter +import com.fasterxml.jackson.annotation.JsonCreator +import com.fasterxml.jackson.annotation.JsonProperty +import com.fasterxml.jackson.core.JsonGenerator +import com.fasterxml.jackson.core.ObjectCodec +import com.fasterxml.jackson.databind.JsonNode +import com.fasterxml.jackson.databind.SerializerProvider +import com.fasterxml.jackson.databind.annotation.JsonDeserialize +import com.fasterxml.jackson.databind.annotation.JsonSerialize +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import com.openai.core.BaseDeserializer +import com.openai.core.BaseSerializer +import com.openai.core.ExcludeMissing +import com.openai.core.JsonField +import com.openai.core.JsonMissing +import com.openai.core.JsonValue +import com.openai.core.checkKnown +import com.openai.core.checkRequired +import com.openai.core.getOrThrow +import com.openai.core.toImmutable +import com.openai.errors.OpenAIInvalidDataException +import java.util.Collections +import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +class Decision +@JsonCreator(mode = JsonCreator.Mode.DISABLED) +private constructor( + private val answers: JsonField>, + private val model: JsonField, + private val usage: JsonField, + private val additionalProperties: MutableMap, +) { + + @JsonCreator + private constructor( + @JsonProperty("answers") + @ExcludeMissing + answers: JsonField> = JsonMissing.of(), + @JsonProperty("model") @ExcludeMissing model: JsonField = JsonMissing.of(), + @JsonProperty("usage") @ExcludeMissing usage: JsonField = JsonMissing.of(), + ) : this(answers, model, usage, mutableMapOf()) + + /** + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun answers(): List = answers.getRequired("answers") + + /** + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun model(): String = model.getRequired("model") + + /** + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun usage(): Usage = usage.getRequired("usage") + + /** + * Returns the raw JSON value of [answers]. + * + * Unlike [answers], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("answers") @ExcludeMissing fun _answers(): JsonField> = answers + + /** + * Returns the raw JSON value of [model]. + * + * Unlike [model], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("model") @ExcludeMissing fun _model(): JsonField = model + + /** + * Returns the raw JSON value of [usage]. + * + * Unlike [usage], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("usage") @ExcludeMissing fun _usage(): JsonField = usage + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [Decision]. + * + * The following fields are required: + * ```java + * .answers() + * .model() + * .usage() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Decision]. */ + class Builder internal constructor() { + + private var answers: JsonField>? = null + private var model: JsonField? = null + private var usage: JsonField? = null + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(decision: Decision) = apply { + answers = decision.answers.map { it.toMutableList() } + model = decision.model + usage = decision.usage + additionalProperties = decision.additionalProperties.toMutableMap() + } + + fun answers(answers: List) = answers(JsonField.of(answers)) + + /** + * Sets [Builder.answers] to an arbitrary JSON value. + * + * You should usually call [Builder.answers] with a well-typed `List` value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun answers(answers: JsonField>) = apply { + this.answers = answers.map { it.toMutableList() } + } + + /** + * Adds a single [Answer] to [answers]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addAnswer(answer: Answer) = apply { + answers = + (answers ?: JsonField.of(mutableListOf())).also { + checkKnown("answers", it).add(answer) + } + } + + /** Alias for calling [addAnswer] with `Answer.ofPredicate(predicate)`. */ + fun addAnswer(predicate: Answer.Predicate) = addAnswer(Answer.ofPredicate(predicate)) + + /** Alias for calling [addAnswer] with `Answer.ofChoice(choice)`. */ + fun addAnswer(choice: Answer.Choice) = addAnswer(Answer.ofChoice(choice)) + + /** Alias for calling [addAnswer] with `Answer.ofScore(score)`. */ + fun addAnswer(score: Answer.Score) = addAnswer(Answer.ofScore(score)) + + /** Alias for calling [addAnswer] with `Answer.ofRefusal(refusal)`. */ + fun addAnswer(refusal: Answer.Refusal) = addAnswer(Answer.ofRefusal(refusal)) + + /** + * Alias for calling [addAnswer] with the following: + * ```java + * Answer.Refusal.builder() + * .name(name) + * .build() + * ``` + */ + fun addRefusalAnswer(name: String?) = addAnswer(Answer.Refusal.builder().name(name).build()) + + /** Alias for calling [addRefusalAnswer] with `name.orElse(null)`. */ + fun addRefusalAnswer(name: Optional) = addRefusalAnswer(name.getOrNull()) + + fun model(model: String) = model(JsonField.of(model)) + + /** + * Sets [Builder.model] to an arbitrary JSON value. + * + * You should usually call [Builder.model] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun model(model: JsonField) = apply { this.model = model } + + fun usage(usage: Usage) = usage(JsonField.of(usage)) + + /** + * Sets [Builder.usage] to an arbitrary JSON value. + * + * You should usually call [Builder.usage] with a well-typed [Usage] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun usage(usage: JsonField) = apply { this.usage = usage } + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { additionalProperties.remove(key) } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [Decision]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .answers() + * .model() + * .usage() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): Decision = + Decision( + checkRequired("answers", answers).map { it.toImmutable() }, + checkRequired("model", model), + checkRequired("usage", usage), + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws OpenAIInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): Decision = apply { + if (validated) { + return@apply + } + + answers().forEach { it.validate() } + model() + usage().validate() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: OpenAIInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + (answers.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + + (if (model.asKnown().isPresent) 1 else 0) + + (usage.asKnown().getOrNull()?.validity() ?: 0) + + /** A completed question always includes its name, including null when unnamed. */ + @JsonDeserialize(using = Answer.Deserializer::class) + @JsonSerialize(using = Answer.Serializer::class) + class Answer + private constructor( + private val predicate: Predicate? = null, + private val choice: Choice? = null, + private val score: Score? = null, + private val refusal: Refusal? = null, + private val _json: JsonValue? = null, + ) { + + fun predicate(): Optional = Optional.ofNullable(predicate) + + fun choice(): Optional = Optional.ofNullable(choice) + + fun score(): Optional = Optional.ofNullable(score) + + /** The host may decline one question without disclosing its refusal score. */ + fun refusal(): Optional = Optional.ofNullable(refusal) + + fun isPredicate(): Boolean = predicate != null + + fun isChoice(): Boolean = choice != null + + fun isScore(): Boolean = score != null + + fun isRefusal(): Boolean = refusal != null + + fun asPredicate(): Predicate = predicate.getOrThrow("predicate") + + fun asChoice(): Choice = choice.getOrThrow("choice") + + fun asScore(): Score = score.getOrThrow("score") + + /** The host may decline one question without disclosing its refusal score. */ + fun asRefusal(): Refusal = refusal.getOrThrow("refusal") + + fun _json(): Optional = Optional.ofNullable(_json) + + /** + * Maps this instance's current variant to a value of type [T] using the given [visitor]. + * + * Note that this method is _not_ forwards compatible with new variants from the API, unless + * [visitor] overrides [Visitor.unknown]. To handle variants not known to this version of + * the SDK gracefully, consider overriding [Visitor.unknown]: + * ```java + * import com.openai.core.JsonValue; + * import java.util.Optional; + * + * Optional result = answer.accept(new Answer.Visitor>() { + * @Override + * public Optional visitPredicate(Predicate predicate) { + * return Optional.of(predicate.toString()); + * } + * + * // ... + * + * @Override + * public Optional unknown(JsonValue json) { + * // Or inspect the `json`. + * return Optional.empty(); + * } + * }); + * ``` + * + * @throws OpenAIInvalidDataException if [Visitor.unknown] is not overridden in [visitor] + * and the current variant is unknown. + */ + fun accept(visitor: Visitor): T = + when { + predicate != null -> visitor.visitPredicate(predicate) + choice != null -> visitor.visitChoice(choice) + score != null -> visitor.visitScore(score) + refusal != null -> visitor.visitRefusal(refusal) + else -> visitor.unknown(_json) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws OpenAIInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): Answer = apply { + if (validated) { + return@apply + } + + accept( + object : Visitor { + override fun visitPredicate(predicate: Predicate) { + predicate.validate() + } + + override fun visitChoice(choice: Choice) { + choice.validate() + } + + override fun visitScore(score: Score) { + score.validate() + } + + override fun visitRefusal(refusal: Refusal) { + refusal.validate() + } + } + ) + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: OpenAIInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + accept( + object : Visitor { + override fun visitPredicate(predicate: Predicate) = predicate.validity() + + override fun visitChoice(choice: Choice) = choice.validity() + + override fun visitScore(score: Score) = score.validity() + + override fun visitRefusal(refusal: Refusal) = refusal.validity() + + override fun unknown(json: JsonValue?) = 0 + } + ) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Answer && + predicate == other.predicate && + choice == other.choice && + score == other.score && + refusal == other.refusal + } + + override fun hashCode(): Int = Objects.hash(predicate, choice, score, refusal) + + override fun toString(): String = + when { + predicate != null -> "Answer{predicate=$predicate}" + choice != null -> "Answer{choice=$choice}" + score != null -> "Answer{score=$score}" + refusal != null -> "Answer{refusal=$refusal}" + _json != null -> "Answer{_unknown=$_json}" + else -> throw IllegalStateException("Invalid Answer") + } + + companion object { + + @JvmStatic fun ofPredicate(predicate: Predicate) = Answer(predicate = predicate) + + @JvmStatic fun ofChoice(choice: Choice) = Answer(choice = choice) + + @JvmStatic fun ofScore(score: Score) = Answer(score = score) + + /** The host may decline one question without disclosing its refusal score. */ + @JvmStatic fun ofRefusal(refusal: Refusal) = Answer(refusal = refusal) + } + + /** An interface that defines how to map each variant of [Answer] to a value of type [T]. */ + interface Visitor { + + fun visitPredicate(predicate: Predicate): T + + fun visitChoice(choice: Choice): T + + fun visitScore(score: Score): T + + /** The host may decline one question without disclosing its refusal score. */ + fun visitRefusal(refusal: Refusal): T + + /** + * Maps an unknown variant of [Answer] to a value of type [T]. + * + * An instance of [Answer] can contain an unknown variant if it was deserialized from + * data that doesn't match any known variant. For example, if the SDK is on an older + * version than the API, then the API may respond with new variants that the SDK is + * unaware of. + * + * @throws OpenAIInvalidDataException in the default implementation. + */ + fun unknown(json: JsonValue?): T { + throw OpenAIInvalidDataException("Unknown Answer") + } + } + + internal class Deserializer : BaseDeserializer(Answer::class) { + + override fun ObjectCodec.deserialize(node: JsonNode): Answer { + val json = JsonValue.fromJsonNode(node) + val type = json.asObject().getOrNull()?.get("type")?.asString()?.getOrNull() + + when (type) { + "predicate" -> { + return tryDeserialize(node, jacksonTypeRef())?.let { + Answer(predicate = it, _json = json) + } ?: Answer(_json = json) + } + "choice" -> { + return tryDeserialize(node, jacksonTypeRef())?.let { + Answer(choice = it, _json = json) + } ?: Answer(_json = json) + } + "score" -> { + return tryDeserialize(node, jacksonTypeRef())?.let { + Answer(score = it, _json = json) + } ?: Answer(_json = json) + } + "refusal" -> { + return tryDeserialize(node, jacksonTypeRef())?.let { + Answer(refusal = it, _json = json) + } ?: Answer(_json = json) + } + } + + return Answer(_json = json) + } + } + + internal class Serializer : BaseSerializer(Answer::class) { + + override fun serialize( + value: Answer, + generator: JsonGenerator, + provider: SerializerProvider, + ) { + when { + value.predicate != null -> generator.writeObject(value.predicate) + value.choice != null -> generator.writeObject(value.choice) + value.score != null -> generator.writeObject(value.score) + value.refusal != null -> generator.writeObject(value.refusal) + value._json != null -> generator.writeObject(value._json) + else -> throw IllegalStateException("Invalid Answer") + } + } + } + + class Predicate + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val name: JsonField, + private val probability: JsonField, + private val type: JsonValue, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("name") @ExcludeMissing name: JsonField = JsonMissing.of(), + @JsonProperty("probability") + @ExcludeMissing + probability: JsonField = JsonMissing.of(), + @JsonProperty("type") @ExcludeMissing type: JsonValue = JsonMissing.of(), + ) : this(name, probability, type, mutableMapOf()) + + /** + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun name(): Optional = name.getOptional("name") + + /** + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected + * value). + */ + fun probability(): Double = probability.getRequired("probability") + + /** + * The type of the object. Always `predicate`. + * + * Expected to always return the following: + * ```java + * JsonValue.from("predicate") + * ``` + * + * However, this method can be useful for debugging and logging (e.g. if the server + * responded with an unexpected value). + */ + @JsonProperty("type") @ExcludeMissing fun _type(): JsonValue = type + + /** + * Returns the raw JSON value of [name]. + * + * Unlike [name], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("name") @ExcludeMissing fun _name(): JsonField = name + + /** + * Returns the raw JSON value of [probability]. + * + * Unlike [probability], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("probability") + @ExcludeMissing + fun _probability(): JsonField = probability + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [Predicate]. + * + * The following fields are required: + * ```java + * .name() + * .probability() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Predicate]. */ + class Builder internal constructor() { + + private var name: JsonField? = null + private var probability: JsonField? = null + private var type: JsonValue = JsonValue.from("predicate") + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(predicate: Predicate) = apply { + name = predicate.name + probability = predicate.probability + type = predicate.type + additionalProperties = predicate.additionalProperties.toMutableMap() + } + + fun name(name: String?) = name(JsonField.ofNullable(name)) + + /** Alias for calling [Builder.name] with `name.orElse(null)`. */ + fun name(name: Optional) = name(name.getOrNull()) + + /** + * Sets [Builder.name] to an arbitrary JSON value. + * + * You should usually call [Builder.name] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun name(name: JsonField) = apply { this.name = name } + + fun probability(probability: Double) = probability(JsonField.of(probability)) + + /** + * Sets [Builder.probability] to an arbitrary JSON value. + * + * You should usually call [Builder.probability] with a well-typed [Double] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun probability(probability: JsonField) = apply { + this.probability = probability + } + + /** + * Sets the field to an arbitrary JSON value. + * + * It is usually unnecessary to call this method because the field defaults to the + * following: + * ```java + * JsonValue.from("predicate") + * ``` + * + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun type(type: JsonValue) = apply { this.type = type } + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = + apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { + additionalProperties.remove(key) + } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [Predicate]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .name() + * .probability() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): Predicate = + Predicate( + checkRequired("name", name), + checkRequired("probability", probability), + type, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws OpenAIInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): Predicate = apply { + if (validated) { + return@apply + } + + name() + probability() + _type().let { + if (it != JsonValue.from("predicate")) { + throw OpenAIInvalidDataException("'type' is invalid, received $it") + } + } + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: OpenAIInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + (if (name.asKnown().isPresent) 1 else 0) + + (if (probability.asKnown().isPresent) 1 else 0) + + type.let { if (it == JsonValue.from("predicate")) 1 else 0 } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Predicate && + name == other.name && + probability == other.probability && + type == other.type && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(name, probability, type, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Predicate{name=$name, probability=$probability, type=$type, additionalProperties=$additionalProperties}" + } + + class Choice + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val choice: JsonField, + private val confidence: JsonField, + private val name: JsonField, + private val probabilities: JsonField>, + private val type: JsonValue, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("choice") + @ExcludeMissing + choice: JsonField = JsonMissing.of(), + @JsonProperty("confidence") + @ExcludeMissing + confidence: JsonField = JsonMissing.of(), + @JsonProperty("name") @ExcludeMissing name: JsonField = JsonMissing.of(), + @JsonProperty("probabilities") + @ExcludeMissing + probabilities: JsonField> = JsonMissing.of(), + @JsonProperty("type") @ExcludeMissing type: JsonValue = JsonMissing.of(), + ) : this(choice, confidence, name, probabilities, type, mutableMapOf()) + + /** + * Choice values are typed: a string and a boolean with the same text are distinct. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected + * value). + */ + fun choice(): DecisionChoiceValue = choice.getRequired("choice") + + /** + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected + * value). + */ + fun confidence(): Double = confidence.getRequired("confidence") + + /** + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun name(): Optional = name.getOptional("name") + + /** + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected + * value). + */ + fun probabilities(): List = probabilities.getRequired("probabilities") + + /** + * The type of the object. Always `choice`. + * + * Expected to always return the following: + * ```java + * JsonValue.from("choice") + * ``` + * + * However, this method can be useful for debugging and logging (e.g. if the server + * responded with an unexpected value). + */ + @JsonProperty("type") @ExcludeMissing fun _type(): JsonValue = type + + /** + * Returns the raw JSON value of [choice]. + * + * Unlike [choice], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("choice") + @ExcludeMissing + fun _choice(): JsonField = choice + + /** + * Returns the raw JSON value of [confidence]. + * + * Unlike [confidence], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("confidence") + @ExcludeMissing + fun _confidence(): JsonField = confidence + + /** + * Returns the raw JSON value of [name]. + * + * Unlike [name], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("name") @ExcludeMissing fun _name(): JsonField = name + + /** + * Returns the raw JSON value of [probabilities]. + * + * Unlike [probabilities], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("probabilities") + @ExcludeMissing + fun _probabilities(): JsonField> = probabilities + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [Choice]. + * + * The following fields are required: + * ```java + * .choice() + * .confidence() + * .name() + * .probabilities() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Choice]. */ + class Builder internal constructor() { + + private var choice: JsonField? = null + private var confidence: JsonField? = null + private var name: JsonField? = null + private var probabilities: JsonField>? = null + private var type: JsonValue = JsonValue.from("choice") + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(choice: Choice) = apply { + this.choice = choice.choice + confidence = choice.confidence + name = choice.name + probabilities = choice.probabilities.map { it.toMutableList() } + type = choice.type + additionalProperties = choice.additionalProperties.toMutableMap() + } + + /** + * Choice values are typed: a string and a boolean with the same text are distinct. + */ + fun choice(choice: DecisionChoiceValue) = choice(JsonField.of(choice)) + + /** + * Sets [Builder.choice] to an arbitrary JSON value. + * + * You should usually call [Builder.choice] with a well-typed [DecisionChoiceValue] + * value instead. This method is primarily for setting the field to an undocumented + * or not yet supported value. + */ + fun choice(choice: JsonField) = apply { this.choice = choice } + + /** Alias for calling [choice] with `DecisionChoiceValue.ofString(string)`. */ + fun choice(string: String) = choice(DecisionChoiceValue.ofString(string)) + + /** Alias for calling [choice] with `DecisionChoiceValue.ofBool(bool)`. */ + fun choice(bool: Boolean) = choice(DecisionChoiceValue.ofBool(bool)) + + fun confidence(confidence: Double) = confidence(JsonField.of(confidence)) + + /** + * Sets [Builder.confidence] to an arbitrary JSON value. + * + * You should usually call [Builder.confidence] with a well-typed [Double] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun confidence(confidence: JsonField) = apply { + this.confidence = confidence + } + + fun name(name: String?) = name(JsonField.ofNullable(name)) + + /** Alias for calling [Builder.name] with `name.orElse(null)`. */ + fun name(name: Optional) = name(name.getOrNull()) + + /** + * Sets [Builder.name] to an arbitrary JSON value. + * + * You should usually call [Builder.name] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun name(name: JsonField) = apply { this.name = name } + + fun probabilities(probabilities: List) = + probabilities(JsonField.of(probabilities)) + + /** + * Sets [Builder.probabilities] to an arbitrary JSON value. + * + * You should usually call [Builder.probabilities] with a well-typed + * `List` value instead. This method is primarily for setting the field + * to an undocumented or not yet supported value. + */ + fun probabilities(probabilities: JsonField>) = apply { + this.probabilities = probabilities.map { it.toMutableList() } + } + + /** + * Adds a single [Probability] to [probabilities]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addProbability(probability: Probability) = apply { + probabilities = + (probabilities ?: JsonField.of(mutableListOf())).also { + checkKnown("probabilities", it).add(probability) + } + } + + /** + * Sets the field to an arbitrary JSON value. + * + * It is usually unnecessary to call this method because the field defaults to the + * following: + * ```java + * JsonValue.from("choice") + * ``` + * + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun type(type: JsonValue) = apply { this.type = type } + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = + apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { + additionalProperties.remove(key) + } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [Choice]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .choice() + * .confidence() + * .name() + * .probabilities() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): Choice = + Choice( + checkRequired("choice", choice), + checkRequired("confidence", confidence), + checkRequired("name", name), + checkRequired("probabilities", probabilities).map { it.toImmutable() }, + type, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws OpenAIInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): Choice = apply { + if (validated) { + return@apply + } + + choice().validate() + confidence() + name() + probabilities().forEach { it.validate() } + _type().let { + if (it != JsonValue.from("choice")) { + throw OpenAIInvalidDataException("'type' is invalid, received $it") + } + } + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: OpenAIInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + (choice.asKnown().getOrNull()?.validity() ?: 0) + + (if (confidence.asKnown().isPresent) 1 else 0) + + (if (name.asKnown().isPresent) 1 else 0) + + (probabilities.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + + type.let { if (it == JsonValue.from("choice")) 1 else 0 } + + class Probability + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val probability: JsonField, + private val value: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("probability") + @ExcludeMissing + probability: JsonField = JsonMissing.of(), + @JsonProperty("value") + @ExcludeMissing + value: JsonField = JsonMissing.of(), + ) : this(probability, value, mutableMapOf()) + + /** + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected + * value). + */ + fun probability(): Double = probability.getRequired("probability") + + /** + * Choice values are typed: a string and a boolean with the same text are distinct. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected + * value). + */ + fun value(): DecisionChoiceValue = value.getRequired("value") + + /** + * Returns the raw JSON value of [probability]. + * + * Unlike [probability], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("probability") + @ExcludeMissing + fun _probability(): JsonField = probability + + /** + * Returns the raw JSON value of [value]. + * + * Unlike [value], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("value") + @ExcludeMissing + fun _value(): JsonField = value + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [Probability]. + * + * The following fields are required: + * ```java + * .probability() + * .value() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Probability]. */ + class Builder internal constructor() { + + private var probability: JsonField? = null + private var value: JsonField? = null + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(probability: Probability) = apply { + this.probability = probability.probability + value = probability.value + additionalProperties = probability.additionalProperties.toMutableMap() + } + + fun probability(probability: Double) = probability(JsonField.of(probability)) + + /** + * Sets [Builder.probability] to an arbitrary JSON value. + * + * You should usually call [Builder.probability] with a well-typed [Double] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun probability(probability: JsonField) = apply { + this.probability = probability + } + + /** + * Choice values are typed: a string and a boolean with the same text are + * distinct. + */ + fun value(value: DecisionChoiceValue) = value(JsonField.of(value)) + + /** + * Sets [Builder.value] to an arbitrary JSON value. + * + * You should usually call [Builder.value] with a well-typed + * [DecisionChoiceValue] value instead. This method is primarily for setting the + * field to an undocumented or not yet supported value. + */ + fun value(value: JsonField) = apply { this.value = value } + + /** Alias for calling [value] with `DecisionChoiceValue.ofString(string)`. */ + fun value(string: String) = value(DecisionChoiceValue.ofString(string)) + + /** Alias for calling [value] with `DecisionChoiceValue.ofBool(bool)`. */ + fun value(bool: Boolean) = value(DecisionChoiceValue.ofBool(bool)) + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = + apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { + additionalProperties.remove(key) + } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [Probability]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .probability() + * .value() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): Probability = + Probability( + checkRequired("probability", probability), + checkRequired("value", value), + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws OpenAIInvalidDataException if any value type in this object doesn't match + * its expected type. + */ + fun validate(): Probability = apply { + if (validated) { + return@apply + } + + probability() + value().validate() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: OpenAIInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + (if (probability.asKnown().isPresent) 1 else 0) + + (value.asKnown().getOrNull()?.validity() ?: 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Probability && + probability == other.probability && + value == other.value && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(probability, value, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Probability{probability=$probability, value=$value, additionalProperties=$additionalProperties}" + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Choice && + choice == other.choice && + confidence == other.confidence && + name == other.name && + probabilities == other.probabilities && + type == other.type && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(choice, confidence, name, probabilities, type, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Choice{choice=$choice, confidence=$confidence, name=$name, probabilities=$probabilities, type=$type, additionalProperties=$additionalProperties}" + } + + class Score + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val confidence: JsonField, + private val name: JsonField, + private val probabilities: JsonField>, + private val score: JsonField, + private val type: JsonValue, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("confidence") + @ExcludeMissing + confidence: JsonField = JsonMissing.of(), + @JsonProperty("name") @ExcludeMissing name: JsonField = JsonMissing.of(), + @JsonProperty("probabilities") + @ExcludeMissing + probabilities: JsonField> = JsonMissing.of(), + @JsonProperty("score") @ExcludeMissing score: JsonField = JsonMissing.of(), + @JsonProperty("type") @ExcludeMissing type: JsonValue = JsonMissing.of(), + ) : this(confidence, name, probabilities, score, type, mutableMapOf()) + + /** + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected + * value). + */ + fun confidence(): Double = confidence.getRequired("confidence") + + /** + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun name(): Optional = name.getOptional("name") + + /** + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected + * value). + */ + fun probabilities(): List = probabilities.getRequired("probabilities") + + /** + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected + * value). + */ + fun score(): Double = score.getRequired("score") + + /** + * The type of the object. Always `score`. + * + * Expected to always return the following: + * ```java + * JsonValue.from("score") + * ``` + * + * However, this method can be useful for debugging and logging (e.g. if the server + * responded with an unexpected value). + */ + @JsonProperty("type") @ExcludeMissing fun _type(): JsonValue = type + + /** + * Returns the raw JSON value of [confidence]. + * + * Unlike [confidence], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("confidence") + @ExcludeMissing + fun _confidence(): JsonField = confidence + + /** + * Returns the raw JSON value of [name]. + * + * Unlike [name], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("name") @ExcludeMissing fun _name(): JsonField = name + + /** + * Returns the raw JSON value of [probabilities]. + * + * Unlike [probabilities], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("probabilities") + @ExcludeMissing + fun _probabilities(): JsonField> = probabilities + + /** + * Returns the raw JSON value of [score]. + * + * Unlike [score], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("score") @ExcludeMissing fun _score(): JsonField = score + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [Score]. + * + * The following fields are required: + * ```java + * .confidence() + * .name() + * .probabilities() + * .score() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Score]. */ + class Builder internal constructor() { + + private var confidence: JsonField? = null + private var name: JsonField? = null + private var probabilities: JsonField>? = null + private var score: JsonField? = null + private var type: JsonValue = JsonValue.from("score") + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(score: Score) = apply { + confidence = score.confidence + name = score.name + probabilities = score.probabilities.map { it.toMutableList() } + this.score = score.score + type = score.type + additionalProperties = score.additionalProperties.toMutableMap() + } + + fun confidence(confidence: Double) = confidence(JsonField.of(confidence)) + + /** + * Sets [Builder.confidence] to an arbitrary JSON value. + * + * You should usually call [Builder.confidence] with a well-typed [Double] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun confidence(confidence: JsonField) = apply { + this.confidence = confidence + } + + fun name(name: String?) = name(JsonField.ofNullable(name)) + + /** Alias for calling [Builder.name] with `name.orElse(null)`. */ + fun name(name: Optional) = name(name.getOrNull()) + + /** + * Sets [Builder.name] to an arbitrary JSON value. + * + * You should usually call [Builder.name] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun name(name: JsonField) = apply { this.name = name } + + fun probabilities(probabilities: List) = + probabilities(JsonField.of(probabilities)) + + /** + * Sets [Builder.probabilities] to an arbitrary JSON value. + * + * You should usually call [Builder.probabilities] with a well-typed + * `List` value instead. This method is primarily for setting the field + * to an undocumented or not yet supported value. + */ + fun probabilities(probabilities: JsonField>) = apply { + this.probabilities = probabilities.map { it.toMutableList() } + } + + /** + * Adds a single [Probability] to [probabilities]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addProbability(probability: Probability) = apply { + probabilities = + (probabilities ?: JsonField.of(mutableListOf())).also { + checkKnown("probabilities", it).add(probability) + } + } + + fun score(score: Double) = score(JsonField.of(score)) + + /** + * Sets [Builder.score] to an arbitrary JSON value. + * + * You should usually call [Builder.score] with a well-typed [Double] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun score(score: JsonField) = apply { this.score = score } + + /** + * Sets the field to an arbitrary JSON value. + * + * It is usually unnecessary to call this method because the field defaults to the + * following: + * ```java + * JsonValue.from("score") + * ``` + * + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun type(type: JsonValue) = apply { this.type = type } + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = + apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { + additionalProperties.remove(key) + } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [Score]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .confidence() + * .name() + * .probabilities() + * .score() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): Score = + Score( + checkRequired("confidence", confidence), + checkRequired("name", name), + checkRequired("probabilities", probabilities).map { it.toImmutable() }, + checkRequired("score", score), + type, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws OpenAIInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): Score = apply { + if (validated) { + return@apply + } + + confidence() + name() + probabilities().forEach { it.validate() } + score() + _type().let { + if (it != JsonValue.from("score")) { + throw OpenAIInvalidDataException("'type' is invalid, received $it") + } + } + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: OpenAIInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + (if (confidence.asKnown().isPresent) 1 else 0) + + (if (name.asKnown().isPresent) 1 else 0) + + (probabilities.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + + (if (score.asKnown().isPresent) 1 else 0) + + type.let { if (it == JsonValue.from("score")) 1 else 0 } + + class Probability + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val label: JsonField, + private val probability: JsonField, + private val value: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("label") + @ExcludeMissing + label: JsonField = JsonMissing.of(), + @JsonProperty("probability") + @ExcludeMissing + probability: JsonField = JsonMissing.of(), + @JsonProperty("value") @ExcludeMissing value: JsonField = JsonMissing.of(), + ) : this(label, probability, value, mutableMapOf()) + + /** + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected + * value). + */ + fun label(): String = label.getRequired("label") + + /** + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected + * value). + */ + fun probability(): Double = probability.getRequired("probability") + + /** + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected + * value). + */ + fun value(): Long = value.getRequired("value") + + /** + * Returns the raw JSON value of [label]. + * + * Unlike [label], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("label") @ExcludeMissing fun _label(): JsonField = label + + /** + * Returns the raw JSON value of [probability]. + * + * Unlike [probability], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("probability") + @ExcludeMissing + fun _probability(): JsonField = probability + + /** + * Returns the raw JSON value of [value]. + * + * Unlike [value], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("value") @ExcludeMissing fun _value(): JsonField = value + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [Probability]. + * + * The following fields are required: + * ```java + * .label() + * .probability() + * .value() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Probability]. */ + class Builder internal constructor() { + + private var label: JsonField? = null + private var probability: JsonField? = null + private var value: JsonField? = null + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(probability: Probability) = apply { + label = probability.label + this.probability = probability.probability + value = probability.value + additionalProperties = probability.additionalProperties.toMutableMap() + } + + fun label(label: String) = label(JsonField.of(label)) + + /** + * Sets [Builder.label] to an arbitrary JSON value. + * + * You should usually call [Builder.label] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or + * not yet supported value. + */ + fun label(label: JsonField) = apply { this.label = label } + + fun probability(probability: Double) = probability(JsonField.of(probability)) + + /** + * Sets [Builder.probability] to an arbitrary JSON value. + * + * You should usually call [Builder.probability] with a well-typed [Double] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun probability(probability: JsonField) = apply { + this.probability = probability + } + + fun value(value: Long) = value(JsonField.of(value)) + + /** + * Sets [Builder.value] to an arbitrary JSON value. + * + * You should usually call [Builder.value] with a well-typed [Long] value + * instead. This method is primarily for setting the field to an undocumented or + * not yet supported value. + */ + fun value(value: JsonField) = apply { this.value = value } + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = + apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { + additionalProperties.remove(key) + } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [Probability]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .label() + * .probability() + * .value() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): Probability = + Probability( + checkRequired("label", label), + checkRequired("probability", probability), + checkRequired("value", value), + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws OpenAIInvalidDataException if any value type in this object doesn't match + * its expected type. + */ + fun validate(): Probability = apply { + if (validated) { + return@apply + } + + label() + probability() + value() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: OpenAIInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + (if (label.asKnown().isPresent) 1 else 0) + + (if (probability.asKnown().isPresent) 1 else 0) + + (if (value.asKnown().isPresent) 1 else 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Probability && + label == other.label && + probability == other.probability && + value == other.value && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(label, probability, value, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Probability{label=$label, probability=$probability, value=$value, additionalProperties=$additionalProperties}" + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Score && + confidence == other.confidence && + name == other.name && + probabilities == other.probabilities && + score == other.score && + type == other.type && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(confidence, name, probabilities, score, type, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Score{confidence=$confidence, name=$name, probabilities=$probabilities, score=$score, type=$type, additionalProperties=$additionalProperties}" + } + + /** The host may decline one question without disclosing its refusal score. */ + class Refusal + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val name: JsonField, + private val type: JsonValue, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("name") @ExcludeMissing name: JsonField = JsonMissing.of(), + @JsonProperty("type") @ExcludeMissing type: JsonValue = JsonMissing.of(), + ) : this(name, type, mutableMapOf()) + + /** + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun name(): Optional = name.getOptional("name") + + /** + * The type of the object. Always `refusal`. + * + * Expected to always return the following: + * ```java + * JsonValue.from("refusal") + * ``` + * + * However, this method can be useful for debugging and logging (e.g. if the server + * responded with an unexpected value). + */ + @JsonProperty("type") @ExcludeMissing fun _type(): JsonValue = type + + /** + * Returns the raw JSON value of [name]. + * + * Unlike [name], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("name") @ExcludeMissing fun _name(): JsonField = name + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [Refusal]. + * + * The following fields are required: + * ```java + * .name() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Refusal]. */ + class Builder internal constructor() { + + private var name: JsonField? = null + private var type: JsonValue = JsonValue.from("refusal") + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(refusal: Refusal) = apply { + name = refusal.name + type = refusal.type + additionalProperties = refusal.additionalProperties.toMutableMap() + } + + fun name(name: String?) = name(JsonField.ofNullable(name)) + + /** Alias for calling [Builder.name] with `name.orElse(null)`. */ + fun name(name: Optional) = name(name.getOrNull()) + + /** + * Sets [Builder.name] to an arbitrary JSON value. + * + * You should usually call [Builder.name] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun name(name: JsonField) = apply { this.name = name } + + /** + * Sets the field to an arbitrary JSON value. + * + * It is usually unnecessary to call this method because the field defaults to the + * following: + * ```java + * JsonValue.from("refusal") + * ``` + * + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun type(type: JsonValue) = apply { this.type = type } + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = + apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { + additionalProperties.remove(key) + } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [Refusal]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .name() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): Refusal = + Refusal(checkRequired("name", name), type, additionalProperties.toMutableMap()) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws OpenAIInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): Refusal = apply { + if (validated) { + return@apply + } + + name() + _type().let { + if (it != JsonValue.from("refusal")) { + throw OpenAIInvalidDataException("'type' is invalid, received $it") + } + } + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: OpenAIInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + (if (name.asKnown().isPresent) 1 else 0) + + type.let { if (it == JsonValue.from("refusal")) 1 else 0 } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Refusal && + name == other.name && + type == other.type && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(name, type, additionalProperties) } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Refusal{name=$name, type=$type, additionalProperties=$additionalProperties}" + } + } + + class Usage + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val inputTokens: JsonField, + private val inputTokensDetails: JsonField, + private val outputTokens: JsonField, + private val outputTokensDetails: JsonField, + private val totalTokens: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("input_tokens") + @ExcludeMissing + inputTokens: JsonField = JsonMissing.of(), + @JsonProperty("input_tokens_details") + @ExcludeMissing + inputTokensDetails: JsonField = JsonMissing.of(), + @JsonProperty("output_tokens") + @ExcludeMissing + outputTokens: JsonField = JsonMissing.of(), + @JsonProperty("output_tokens_details") + @ExcludeMissing + outputTokensDetails: JsonField = JsonMissing.of(), + @JsonProperty("total_tokens") + @ExcludeMissing + totalTokens: JsonField = JsonMissing.of(), + ) : this( + inputTokens, + inputTokensDetails, + outputTokens, + outputTokensDetails, + totalTokens, + mutableMapOf(), + ) + + /** + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun inputTokens(): Long = inputTokens.getRequired("input_tokens") + + /** + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun inputTokensDetails(): InputTokensDetails = + inputTokensDetails.getRequired("input_tokens_details") + + /** + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun outputTokens(): Long = outputTokens.getRequired("output_tokens") + + /** + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun outputTokensDetails(): OutputTokensDetails = + outputTokensDetails.getRequired("output_tokens_details") + + /** + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun totalTokens(): Long = totalTokens.getRequired("total_tokens") + + /** + * Returns the raw JSON value of [inputTokens]. + * + * Unlike [inputTokens], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("input_tokens") + @ExcludeMissing + fun _inputTokens(): JsonField = inputTokens + + /** + * Returns the raw JSON value of [inputTokensDetails]. + * + * Unlike [inputTokensDetails], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("input_tokens_details") + @ExcludeMissing + fun _inputTokensDetails(): JsonField = inputTokensDetails + + /** + * Returns the raw JSON value of [outputTokens]. + * + * Unlike [outputTokens], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("output_tokens") + @ExcludeMissing + fun _outputTokens(): JsonField = outputTokens + + /** + * Returns the raw JSON value of [outputTokensDetails]. + * + * Unlike [outputTokensDetails], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("output_tokens_details") + @ExcludeMissing + fun _outputTokensDetails(): JsonField = outputTokensDetails + + /** + * Returns the raw JSON value of [totalTokens]. + * + * Unlike [totalTokens], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("total_tokens") + @ExcludeMissing + fun _totalTokens(): JsonField = totalTokens + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [Usage]. + * + * The following fields are required: + * ```java + * .inputTokens() + * .inputTokensDetails() + * .outputTokens() + * .outputTokensDetails() + * .totalTokens() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Usage]. */ + class Builder internal constructor() { + + private var inputTokens: JsonField? = null + private var inputTokensDetails: JsonField? = null + private var outputTokens: JsonField? = null + private var outputTokensDetails: JsonField? = null + private var totalTokens: JsonField? = null + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(usage: Usage) = apply { + inputTokens = usage.inputTokens + inputTokensDetails = usage.inputTokensDetails + outputTokens = usage.outputTokens + outputTokensDetails = usage.outputTokensDetails + totalTokens = usage.totalTokens + additionalProperties = usage.additionalProperties.toMutableMap() + } + + fun inputTokens(inputTokens: Long) = inputTokens(JsonField.of(inputTokens)) + + /** + * Sets [Builder.inputTokens] to an arbitrary JSON value. + * + * You should usually call [Builder.inputTokens] with a well-typed [Long] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun inputTokens(inputTokens: JsonField) = apply { this.inputTokens = inputTokens } + + fun inputTokensDetails(inputTokensDetails: InputTokensDetails) = + inputTokensDetails(JsonField.of(inputTokensDetails)) + + /** + * Sets [Builder.inputTokensDetails] to an arbitrary JSON value. + * + * You should usually call [Builder.inputTokensDetails] with a well-typed + * [InputTokensDetails] value instead. This method is primarily for setting the field to + * an undocumented or not yet supported value. + */ + fun inputTokensDetails(inputTokensDetails: JsonField) = apply { + this.inputTokensDetails = inputTokensDetails + } + + fun outputTokens(outputTokens: Long) = outputTokens(JsonField.of(outputTokens)) + + /** + * Sets [Builder.outputTokens] to an arbitrary JSON value. + * + * You should usually call [Builder.outputTokens] with a well-typed [Long] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun outputTokens(outputTokens: JsonField) = apply { + this.outputTokens = outputTokens + } + + fun outputTokensDetails(outputTokensDetails: OutputTokensDetails) = + outputTokensDetails(JsonField.of(outputTokensDetails)) + + /** + * Sets [Builder.outputTokensDetails] to an arbitrary JSON value. + * + * You should usually call [Builder.outputTokensDetails] with a well-typed + * [OutputTokensDetails] value instead. This method is primarily for setting the field + * to an undocumented or not yet supported value. + */ + fun outputTokensDetails(outputTokensDetails: JsonField) = apply { + this.outputTokensDetails = outputTokensDetails + } + + fun totalTokens(totalTokens: Long) = totalTokens(JsonField.of(totalTokens)) + + /** + * Sets [Builder.totalTokens] to an arbitrary JSON value. + * + * You should usually call [Builder.totalTokens] with a well-typed [Long] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun totalTokens(totalTokens: JsonField) = apply { this.totalTokens = totalTokens } + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { additionalProperties.remove(key) } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [Usage]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .inputTokens() + * .inputTokensDetails() + * .outputTokens() + * .outputTokensDetails() + * .totalTokens() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): Usage = + Usage( + checkRequired("inputTokens", inputTokens), + checkRequired("inputTokensDetails", inputTokensDetails), + checkRequired("outputTokens", outputTokens), + checkRequired("outputTokensDetails", outputTokensDetails), + checkRequired("totalTokens", totalTokens), + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws OpenAIInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): Usage = apply { + if (validated) { + return@apply + } + + inputTokens() + inputTokensDetails().validate() + outputTokens() + outputTokensDetails().validate() + totalTokens() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: OpenAIInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + (if (inputTokens.asKnown().isPresent) 1 else 0) + + (inputTokensDetails.asKnown().getOrNull()?.validity() ?: 0) + + (if (outputTokens.asKnown().isPresent) 1 else 0) + + (outputTokensDetails.asKnown().getOrNull()?.validity() ?: 0) + + (if (totalTokens.asKnown().isPresent) 1 else 0) + + class InputTokensDetails + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val cacheWriteTokens: JsonField, + private val cachedTokens: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("cache_write_tokens") + @ExcludeMissing + cacheWriteTokens: JsonField = JsonMissing.of(), + @JsonProperty("cached_tokens") + @ExcludeMissing + cachedTokens: JsonField = JsonMissing.of(), + ) : this(cacheWriteTokens, cachedTokens, mutableMapOf()) + + /** + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected + * value). + */ + fun cacheWriteTokens(): Long = cacheWriteTokens.getRequired("cache_write_tokens") + + /** + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected + * value). + */ + fun cachedTokens(): Long = cachedTokens.getRequired("cached_tokens") + + /** + * Returns the raw JSON value of [cacheWriteTokens]. + * + * Unlike [cacheWriteTokens], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("cache_write_tokens") + @ExcludeMissing + fun _cacheWriteTokens(): JsonField = cacheWriteTokens + + /** + * Returns the raw JSON value of [cachedTokens]. + * + * Unlike [cachedTokens], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("cached_tokens") + @ExcludeMissing + fun _cachedTokens(): JsonField = cachedTokens + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [InputTokensDetails]. + * + * The following fields are required: + * ```java + * .cacheWriteTokens() + * .cachedTokens() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [InputTokensDetails]. */ + class Builder internal constructor() { + + private var cacheWriteTokens: JsonField? = null + private var cachedTokens: JsonField? = null + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(inputTokensDetails: InputTokensDetails) = apply { + cacheWriteTokens = inputTokensDetails.cacheWriteTokens + cachedTokens = inputTokensDetails.cachedTokens + additionalProperties = inputTokensDetails.additionalProperties.toMutableMap() + } + + fun cacheWriteTokens(cacheWriteTokens: Long) = + cacheWriteTokens(JsonField.of(cacheWriteTokens)) + + /** + * Sets [Builder.cacheWriteTokens] to an arbitrary JSON value. + * + * You should usually call [Builder.cacheWriteTokens] with a well-typed [Long] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun cacheWriteTokens(cacheWriteTokens: JsonField) = apply { + this.cacheWriteTokens = cacheWriteTokens + } + + fun cachedTokens(cachedTokens: Long) = cachedTokens(JsonField.of(cachedTokens)) + + /** + * Sets [Builder.cachedTokens] to an arbitrary JSON value. + * + * You should usually call [Builder.cachedTokens] with a well-typed [Long] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun cachedTokens(cachedTokens: JsonField) = apply { + this.cachedTokens = cachedTokens + } + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = + apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { + additionalProperties.remove(key) + } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [InputTokensDetails]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .cacheWriteTokens() + * .cachedTokens() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): InputTokensDetails = + InputTokensDetails( + checkRequired("cacheWriteTokens", cacheWriteTokens), + checkRequired("cachedTokens", cachedTokens), + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws OpenAIInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): InputTokensDetails = apply { + if (validated) { + return@apply + } + + cacheWriteTokens() + cachedTokens() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: OpenAIInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + (if (cacheWriteTokens.asKnown().isPresent) 1 else 0) + + (if (cachedTokens.asKnown().isPresent) 1 else 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is InputTokensDetails && + cacheWriteTokens == other.cacheWriteTokens && + cachedTokens == other.cachedTokens && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(cacheWriteTokens, cachedTokens, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "InputTokensDetails{cacheWriteTokens=$cacheWriteTokens, cachedTokens=$cachedTokens, additionalProperties=$additionalProperties}" + } + + class OutputTokensDetails + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val reasoningTokens: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("reasoning_tokens") + @ExcludeMissing + reasoningTokens: JsonField = JsonMissing.of() + ) : this(reasoningTokens, mutableMapOf()) + + /** + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected + * value). + */ + fun reasoningTokens(): Long = reasoningTokens.getRequired("reasoning_tokens") + + /** + * Returns the raw JSON value of [reasoningTokens]. + * + * Unlike [reasoningTokens], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("reasoning_tokens") + @ExcludeMissing + fun _reasoningTokens(): JsonField = reasoningTokens + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [OutputTokensDetails]. + * + * The following fields are required: + * ```java + * .reasoningTokens() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [OutputTokensDetails]. */ + class Builder internal constructor() { + + private var reasoningTokens: JsonField? = null + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(outputTokensDetails: OutputTokensDetails) = apply { + reasoningTokens = outputTokensDetails.reasoningTokens + additionalProperties = outputTokensDetails.additionalProperties.toMutableMap() + } + + fun reasoningTokens(reasoningTokens: Long) = + reasoningTokens(JsonField.of(reasoningTokens)) + + /** + * Sets [Builder.reasoningTokens] to an arbitrary JSON value. + * + * You should usually call [Builder.reasoningTokens] with a well-typed [Long] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun reasoningTokens(reasoningTokens: JsonField) = apply { + this.reasoningTokens = reasoningTokens + } + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = + apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { + additionalProperties.remove(key) + } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [OutputTokensDetails]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .reasoningTokens() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): OutputTokensDetails = + OutputTokensDetails( + checkRequired("reasoningTokens", reasoningTokens), + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws OpenAIInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): OutputTokensDetails = apply { + if (validated) { + return@apply + } + + reasoningTokens() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: OpenAIInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = (if (reasoningTokens.asKnown().isPresent) 1 else 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is OutputTokensDetails && + reasoningTokens == other.reasoningTokens && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(reasoningTokens, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "OutputTokensDetails{reasoningTokens=$reasoningTokens, additionalProperties=$additionalProperties}" + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Usage && + inputTokens == other.inputTokens && + inputTokensDetails == other.inputTokensDetails && + outputTokens == other.outputTokens && + outputTokensDetails == other.outputTokensDetails && + totalTokens == other.totalTokens && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash( + inputTokens, + inputTokensDetails, + outputTokens, + outputTokensDetails, + totalTokens, + additionalProperties, + ) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Usage{inputTokens=$inputTokens, inputTokensDetails=$inputTokensDetails, outputTokens=$outputTokens, outputTokensDetails=$outputTokensDetails, totalTokens=$totalTokens, additionalProperties=$additionalProperties}" + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Decision && + answers == other.answers && + model == other.model && + usage == other.usage && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(answers, model, usage, additionalProperties) } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Decision{answers=$answers, model=$model, usage=$usage, additionalProperties=$additionalProperties}" +} diff --git a/openai-java-core/src/main/kotlin/com/openai/models/decisions/DecisionChoiceOption.kt b/openai-java-core/src/main/kotlin/com/openai/models/decisions/DecisionChoiceOption.kt new file mode 100644 index 000000000..2e18ee3b1 --- /dev/null +++ b/openai-java-core/src/main/kotlin/com/openai/models/decisions/DecisionChoiceOption.kt @@ -0,0 +1,442 @@ +// File generated from our OpenAPI spec by Castiron. See CONTRIBUTING.md for details. + +package com.openai.models.decisions + +import com.fasterxml.jackson.annotation.JsonAnyGetter +import com.fasterxml.jackson.annotation.JsonAnySetter +import com.fasterxml.jackson.annotation.JsonCreator +import com.fasterxml.jackson.annotation.JsonProperty +import com.fasterxml.jackson.core.JsonGenerator +import com.fasterxml.jackson.core.ObjectCodec +import com.fasterxml.jackson.databind.JsonNode +import com.fasterxml.jackson.databind.SerializerProvider +import com.fasterxml.jackson.databind.annotation.JsonDeserialize +import com.fasterxml.jackson.databind.annotation.JsonSerialize +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import com.openai.core.BaseDeserializer +import com.openai.core.BaseSerializer +import com.openai.core.ExcludeMissing +import com.openai.core.JsonField +import com.openai.core.JsonMissing +import com.openai.core.JsonValue +import com.openai.core.allMaxBy +import com.openai.core.checkRequired +import com.openai.core.getOrThrow +import com.openai.errors.OpenAIInvalidDataException +import java.util.Collections +import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +class DecisionChoiceOption +@JsonCreator(mode = JsonCreator.Mode.DISABLED) +private constructor( + private val value: JsonField, + private val description: JsonField, + private val additionalProperties: MutableMap, +) { + + @JsonCreator + private constructor( + @JsonProperty("value") @ExcludeMissing value: JsonField = JsonMissing.of(), + @JsonProperty("description") + @ExcludeMissing + description: JsonField = JsonMissing.of(), + ) : this(value, description, mutableMapOf()) + + /** + * Choice values are typed: a string and a boolean with the same text are distinct. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun value(): Value = value.getRequired("value") + + /** + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun description(): Optional = description.getOptional("description") + + /** + * Returns the raw JSON value of [value]. + * + * Unlike [value], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("value") @ExcludeMissing fun _value(): JsonField = value + + /** + * Returns the raw JSON value of [description]. + * + * Unlike [description], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("description") @ExcludeMissing fun _description(): JsonField = description + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [DecisionChoiceOption]. + * + * The following fields are required: + * ```java + * .value() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [DecisionChoiceOption]. */ + class Builder internal constructor() { + + private var value: JsonField? = null + private var description: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(decisionChoiceOption: DecisionChoiceOption) = apply { + value = decisionChoiceOption.value + description = decisionChoiceOption.description + additionalProperties = decisionChoiceOption.additionalProperties.toMutableMap() + } + + /** Choice values are typed: a string and a boolean with the same text are distinct. */ + fun value(value: Value) = value(JsonField.of(value)) + + /** + * Sets [Builder.value] to an arbitrary JSON value. + * + * You should usually call [Builder.value] with a well-typed [Value] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun value(value: JsonField) = apply { this.value = value } + + /** Alias for calling [value] with `Value.ofString(string)`. */ + fun value(string: String) = value(Value.ofString(string)) + + /** Alias for calling [value] with `Value.ofBool(bool)`. */ + fun value(bool: Boolean) = value(Value.ofBool(bool)) + + fun description(description: String) = description(JsonField.of(description)) + + /** + * Sets [Builder.description] to an arbitrary JSON value. + * + * You should usually call [Builder.description] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun description(description: JsonField) = apply { this.description = description } + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { additionalProperties.remove(key) } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [DecisionChoiceOption]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .value() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): DecisionChoiceOption = + DecisionChoiceOption( + checkRequired("value", value), + description, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws OpenAIInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): DecisionChoiceOption = apply { + if (validated) { + return@apply + } + + value().validate() + description() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: OpenAIInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + (value.asKnown().getOrNull()?.validity() ?: 0) + + (if (description.asKnown().isPresent) 1 else 0) + + /** Choice values are typed: a string and a boolean with the same text are distinct. */ + @JsonDeserialize(using = Value.Deserializer::class) + @JsonSerialize(using = Value.Serializer::class) + class Value + private constructor( + private val string: String? = null, + private val bool: Boolean? = null, + private val _json: JsonValue? = null, + ) { + + fun string(): Optional = Optional.ofNullable(string) + + fun bool(): Optional = Optional.ofNullable(bool) + + fun isString(): Boolean = string != null + + fun isBool(): Boolean = bool != null + + fun asString(): String = string.getOrThrow("string") + + fun asBool(): Boolean = bool.getOrThrow("bool") + + fun _json(): Optional = Optional.ofNullable(_json) + + /** + * Maps this instance's current variant to a value of type [T] using the given [visitor]. + * + * Note that this method is _not_ forwards compatible with new variants from the API, unless + * [visitor] overrides [Visitor.unknown]. To handle variants not known to this version of + * the SDK gracefully, consider overriding [Visitor.unknown]: + * ```java + * import com.openai.core.JsonValue; + * import java.util.Optional; + * + * Optional result = value.accept(new Value.Visitor>() { + * @Override + * public Optional visitString(String string) { + * return Optional.of(string.toString()); + * } + * + * // ... + * + * @Override + * public Optional unknown(JsonValue json) { + * // Or inspect the `json`. + * return Optional.empty(); + * } + * }); + * ``` + * + * @throws OpenAIInvalidDataException if [Visitor.unknown] is not overridden in [visitor] + * and the current variant is unknown. + */ + fun accept(visitor: Visitor): T = + when { + string != null -> visitor.visitString(string) + bool != null -> visitor.visitBool(bool) + else -> visitor.unknown(_json) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws OpenAIInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): Value = apply { + if (validated) { + return@apply + } + + accept( + object : Visitor { + override fun visitString(string: String) {} + + override fun visitBool(bool: Boolean) {} + } + ) + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: OpenAIInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + accept( + object : Visitor { + override fun visitString(string: String) = 1 + + override fun visitBool(bool: Boolean) = 1 + + override fun unknown(json: JsonValue?) = 0 + } + ) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Value && string == other.string && bool == other.bool + } + + override fun hashCode(): Int = Objects.hash(string, bool) + + override fun toString(): String = + when { + string != null -> "Value{string=$string}" + bool != null -> "Value{bool=$bool}" + _json != null -> "Value{_unknown=$_json}" + else -> throw IllegalStateException("Invalid Value") + } + + companion object { + + @JvmStatic fun ofString(string: String) = Value(string = string) + + @JvmStatic fun ofBool(bool: Boolean) = Value(bool = bool) + } + + /** An interface that defines how to map each variant of [Value] to a value of type [T]. */ + interface Visitor { + + fun visitString(string: String): T + + fun visitBool(bool: Boolean): T + + /** + * Maps an unknown variant of [Value] to a value of type [T]. + * + * An instance of [Value] can contain an unknown variant if it was deserialized from + * data that doesn't match any known variant. For example, if the SDK is on an older + * version than the API, then the API may respond with new variants that the SDK is + * unaware of. + * + * @throws OpenAIInvalidDataException in the default implementation. + */ + fun unknown(json: JsonValue?): T { + throw OpenAIInvalidDataException("Unknown Value") + } + } + + internal class Deserializer : BaseDeserializer(Value::class) { + + override fun ObjectCodec.deserialize(node: JsonNode): Value { + val json = JsonValue.fromJsonNode(node) + + val bestMatches = + sequenceOf( + tryDeserialize(node, jacksonTypeRef())?.let { + Value(string = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef())?.let { + Value(bool = it, _json = json) + }, + ) + .filterNotNull() + .allMaxBy { it.validity() } + .toList() + return when (bestMatches.size) { + // This can happen if what we're deserializing is completely incompatible with + // all the possible variants (e.g. deserializing from object). + 0 -> Value(_json = json) + 1 -> bestMatches.single() + // If there's more than one match with the highest validity, then use the first + // completely valid match, or simply the first match if none are completely + // valid. + else -> bestMatches.firstOrNull { it.isValid() } ?: bestMatches.first() + } + } + } + + internal class Serializer : BaseSerializer(Value::class) { + + override fun serialize( + value: Value, + generator: JsonGenerator, + provider: SerializerProvider, + ) { + when { + value.string != null -> generator.writeObject(value.string) + value.bool != null -> generator.writeObject(value.bool) + value._json != null -> generator.writeObject(value._json) + else -> throw IllegalStateException("Invalid Value") + } + } + } + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is DecisionChoiceOption && + value == other.value && + description == other.description && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(value, description, additionalProperties) } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "DecisionChoiceOption{value=$value, description=$description, additionalProperties=$additionalProperties}" +} diff --git a/openai-java-core/src/main/kotlin/com/openai/models/decisions/DecisionChoiceValue.kt b/openai-java-core/src/main/kotlin/com/openai/models/decisions/DecisionChoiceValue.kt new file mode 100644 index 000000000..3670745f5 --- /dev/null +++ b/openai-java-core/src/main/kotlin/com/openai/models/decisions/DecisionChoiceValue.kt @@ -0,0 +1,226 @@ +// File generated from our OpenAPI spec by Castiron. See CONTRIBUTING.md for details. + +package com.openai.models.decisions + +import com.fasterxml.jackson.core.JsonGenerator +import com.fasterxml.jackson.core.ObjectCodec +import com.fasterxml.jackson.databind.JsonNode +import com.fasterxml.jackson.databind.SerializerProvider +import com.fasterxml.jackson.databind.annotation.JsonDeserialize +import com.fasterxml.jackson.databind.annotation.JsonSerialize +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import com.openai.core.BaseDeserializer +import com.openai.core.BaseSerializer +import com.openai.core.JsonValue +import com.openai.core.allMaxBy +import com.openai.core.getOrThrow +import com.openai.errors.OpenAIInvalidDataException +import java.util.Objects +import java.util.Optional + +/** Choice values are typed: a string and a boolean with the same text are distinct. */ +@JsonDeserialize(using = DecisionChoiceValue.Deserializer::class) +@JsonSerialize(using = DecisionChoiceValue.Serializer::class) +class DecisionChoiceValue +private constructor( + private val string: String? = null, + private val bool: Boolean? = null, + private val _json: JsonValue? = null, +) { + + fun string(): Optional = Optional.ofNullable(string) + + fun bool(): Optional = Optional.ofNullable(bool) + + fun isString(): Boolean = string != null + + fun isBool(): Boolean = bool != null + + fun asString(): String = string.getOrThrow("string") + + fun asBool(): Boolean = bool.getOrThrow("bool") + + fun _json(): Optional = Optional.ofNullable(_json) + + /** + * Maps this instance's current variant to a value of type [T] using the given [visitor]. + * + * Note that this method is _not_ forwards compatible with new variants from the API, unless + * [visitor] overrides [Visitor.unknown]. To handle variants not known to this version of the + * SDK gracefully, consider overriding [Visitor.unknown]: + * ```java + * import com.openai.core.JsonValue; + * import java.util.Optional; + * + * Optional result = decisionChoiceValue.accept(new DecisionChoiceValue.Visitor>() { + * @Override + * public Optional visitString(String string) { + * return Optional.of(string.toString()); + * } + * + * // ... + * + * @Override + * public Optional unknown(JsonValue json) { + * // Or inspect the `json`. + * return Optional.empty(); + * } + * }); + * ``` + * + * @throws OpenAIInvalidDataException if [Visitor.unknown] is not overridden in [visitor] and + * the current variant is unknown. + */ + fun accept(visitor: Visitor): T = + when { + string != null -> visitor.visitString(string) + bool != null -> visitor.visitBool(bool) + else -> visitor.unknown(_json) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws OpenAIInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): DecisionChoiceValue = apply { + if (validated) { + return@apply + } + + accept( + object : Visitor { + override fun visitString(string: String) {} + + override fun visitBool(bool: Boolean) {} + } + ) + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: OpenAIInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + accept( + object : Visitor { + override fun visitString(string: String) = 1 + + override fun visitBool(bool: Boolean) = 1 + + override fun unknown(json: JsonValue?) = 0 + } + ) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is DecisionChoiceValue && string == other.string && bool == other.bool + } + + override fun hashCode(): Int = Objects.hash(string, bool) + + override fun toString(): String = + when { + string != null -> "DecisionChoiceValue{string=$string}" + bool != null -> "DecisionChoiceValue{bool=$bool}" + _json != null -> "DecisionChoiceValue{_unknown=$_json}" + else -> throw IllegalStateException("Invalid DecisionChoiceValue") + } + + companion object { + + @JvmStatic fun ofString(string: String) = DecisionChoiceValue(string = string) + + @JvmStatic fun ofBool(bool: Boolean) = DecisionChoiceValue(bool = bool) + } + + /** + * An interface that defines how to map each variant of [DecisionChoiceValue] to a value of type + * [T]. + */ + interface Visitor { + + fun visitString(string: String): T + + fun visitBool(bool: Boolean): T + + /** + * Maps an unknown variant of [DecisionChoiceValue] to a value of type [T]. + * + * An instance of [DecisionChoiceValue] can contain an unknown variant if it was + * deserialized from data that doesn't match any known variant. For example, if the SDK is + * on an older version than the API, then the API may respond with new variants that the SDK + * is unaware of. + * + * @throws OpenAIInvalidDataException in the default implementation. + */ + fun unknown(json: JsonValue?): T { + throw OpenAIInvalidDataException("Unknown DecisionChoiceValue") + } + } + + internal class Deserializer : + BaseDeserializer(DecisionChoiceValue::class) { + + override fun ObjectCodec.deserialize(node: JsonNode): DecisionChoiceValue { + val json = JsonValue.fromJsonNode(node) + + val bestMatches = + sequenceOf( + tryDeserialize(node, jacksonTypeRef())?.let { + DecisionChoiceValue(string = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef())?.let { + DecisionChoiceValue(bool = it, _json = json) + }, + ) + .filterNotNull() + .allMaxBy { it.validity() } + .toList() + return when (bestMatches.size) { + // This can happen if what we're deserializing is completely incompatible with all + // the possible variants (e.g. deserializing from object). + 0 -> DecisionChoiceValue(_json = json) + 1 -> bestMatches.single() + // If there's more than one match with the highest validity, then use the first + // completely valid match, or simply the first match if none are completely valid. + else -> bestMatches.firstOrNull { it.isValid() } ?: bestMatches.first() + } + } + } + + internal class Serializer : BaseSerializer(DecisionChoiceValue::class) { + + override fun serialize( + value: DecisionChoiceValue, + generator: JsonGenerator, + provider: SerializerProvider, + ) { + when { + value.string != null -> generator.writeObject(value.string) + value.bool != null -> generator.writeObject(value.bool) + value._json != null -> generator.writeObject(value._json) + else -> throw IllegalStateException("Invalid DecisionChoiceValue") + } + } + } +} diff --git a/openai-java-core/src/main/kotlin/com/openai/models/decisions/DecisionCreateParams.kt b/openai-java-core/src/main/kotlin/com/openai/models/decisions/DecisionCreateParams.kt new file mode 100644 index 000000000..8714fcec7 --- /dev/null +++ b/openai-java-core/src/main/kotlin/com/openai/models/decisions/DecisionCreateParams.kt @@ -0,0 +1,2308 @@ +// File generated from our OpenAPI spec by Castiron. See CONTRIBUTING.md for details. + +package com.openai.models.decisions + +import com.fasterxml.jackson.annotation.JsonAnyGetter +import com.fasterxml.jackson.annotation.JsonAnySetter +import com.fasterxml.jackson.annotation.JsonCreator +import com.fasterxml.jackson.annotation.JsonProperty +import com.fasterxml.jackson.core.JsonGenerator +import com.fasterxml.jackson.core.ObjectCodec +import com.fasterxml.jackson.databind.JsonNode +import com.fasterxml.jackson.databind.SerializerProvider +import com.fasterxml.jackson.databind.annotation.JsonDeserialize +import com.fasterxml.jackson.databind.annotation.JsonSerialize +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import com.openai.core.BaseDeserializer +import com.openai.core.BaseSerializer +import com.openai.core.ExcludeMissing +import com.openai.core.JsonField +import com.openai.core.JsonMissing +import com.openai.core.JsonValue +import com.openai.core.Params +import com.openai.core.allMaxBy +import com.openai.core.checkKnown +import com.openai.core.checkRequired +import com.openai.core.getOrThrow +import com.openai.core.http.Headers +import com.openai.core.http.QueryParams +import com.openai.core.toImmutable +import com.openai.errors.OpenAIInvalidDataException +import java.util.Collections +import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +/** + * Evaluate ordered classification and scoring questions against shared input. Answers are returned + * in question order. + * + * Supply input as a string or user messages containing text and inline images. Only user messages + * with `input_text` and `input_image` parts are supported; non-user roles, function calls, files, + * audio, and item references are not supported. Images require a data URL, not an external URL or + * file ID. At most 128 images are allowed across the request. + * + * Each question can return a refusal instead of a scored answer. A refusal has type `refusal` and + * the corresponding question name, or null if unnamed. + */ +class DecisionCreateParams +private constructor( + private val body: Body, + private val additionalHeaders: Headers, + private val additionalQueryParams: QueryParams, +) : Params { + + /** + * Shared evidence, as a string or an array of user messages containing text and inline images. + * Non-user roles, function calls, function-call outputs, files, audio, and item references are + * not supported. At most 128 image parts are allowed across all messages in one request. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun input(): Input = body.input() + + /** + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun model(): String = body.model() + + /** + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun questions(): List = body.questions() + + /** + * Opaque caller-provided end-user identifier, scoped by the verified org. Match Responses' + * limit; this is never the authenticated user identity. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun safetyIdentifier(): Optional = body.safetyIdentifier() + + /** + * Returns the raw JSON value of [input]. + * + * Unlike [input], this method doesn't throw if the JSON field has an unexpected type. + */ + fun _input(): JsonField = body._input() + + /** + * Returns the raw JSON value of [model]. + * + * Unlike [model], this method doesn't throw if the JSON field has an unexpected type. + */ + fun _model(): JsonField = body._model() + + /** + * Returns the raw JSON value of [questions]. + * + * Unlike [questions], this method doesn't throw if the JSON field has an unexpected type. + */ + fun _questions(): JsonField> = body._questions() + + /** + * Returns the raw JSON value of [safetyIdentifier]. + * + * Unlike [safetyIdentifier], this method doesn't throw if the JSON field has an unexpected + * type. + */ + fun _safetyIdentifier(): JsonField = body._safetyIdentifier() + + fun _additionalBodyProperties(): Map = body._additionalProperties() + + /** Additional headers to send with the request. */ + fun _additionalHeaders(): Headers = additionalHeaders + + /** Additional query param to send with the request. */ + fun _additionalQueryParams(): QueryParams = additionalQueryParams + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [DecisionCreateParams]. + * + * The following fields are required: + * ```java + * .input() + * .model() + * .questions() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [DecisionCreateParams]. */ + class Builder internal constructor() { + + private var body: Body.Builder = Body.builder() + private var additionalHeaders: Headers.Builder = Headers.builder() + private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() + + @JvmSynthetic + internal fun from(decisionCreateParams: DecisionCreateParams) = apply { + body = decisionCreateParams.body.toBuilder() + additionalHeaders = decisionCreateParams.additionalHeaders.toBuilder() + additionalQueryParams = decisionCreateParams.additionalQueryParams.toBuilder() + } + + /** + * Sets the entire request body. + * + * This is generally only useful if you are already constructing the body separately. + * Otherwise, it's more convenient to use the top-level setters instead: + * - [input] + * - [model] + * - [questions] + * - [safetyIdentifier] + */ + fun body(body: Body) = apply { this.body = body.toBuilder() } + + /** + * Shared evidence, as a string or an array of user messages containing text and inline + * images. Non-user roles, function calls, function-call outputs, files, audio, and item + * references are not supported. At most 128 image parts are allowed across all messages in + * one request. + */ + fun input(input: Input) = apply { body.input(input) } + + /** + * Sets [Builder.input] to an arbitrary JSON value. + * + * You should usually call [Builder.input] with a well-typed [Input] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun input(input: JsonField) = apply { body.input(input) } + + /** Alias for calling [input] with `Input.ofString(string)`. */ + fun input(string: String) = apply { body.input(string) } + + /** + * Alias for calling [input] with `Input.ofDecisionInputMessages(decisionInputMessages)`. + */ + fun inputOfDecisionInputMessages(decisionInputMessages: List) = + apply { + body.inputOfDecisionInputMessages(decisionInputMessages) + } + + fun model(model: String) = apply { body.model(model) } + + /** + * Sets [Builder.model] to an arbitrary JSON value. + * + * You should usually call [Builder.model] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun model(model: JsonField) = apply { body.model(model) } + + fun questions(questions: List) = apply { body.questions(questions) } + + /** + * Sets [Builder.questions] to an arbitrary JSON value. + * + * You should usually call [Builder.questions] with a well-typed `List` value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun questions(questions: JsonField>) = apply { body.questions(questions) } + + /** + * Adds a single [Question] to [questions]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addQuestion(question: Question) = apply { body.addQuestion(question) } + + /** Alias for calling [addQuestion] with `Question.ofPredicate(predicate)`. */ + fun addQuestion(predicate: Question.Predicate) = apply { body.addQuestion(predicate) } + + /** + * Alias for calling [addQuestion] with the following: + * ```java + * Question.Predicate.builder() + * .instructions(instructions) + * .build() + * ``` + */ + fun addPredicateQuestion(instructions: String) = apply { + body.addPredicateQuestion(instructions) + } + + /** Alias for calling [addQuestion] with `Question.ofChoice(choice)`. */ + fun addQuestion(choice: Question.Choice) = apply { body.addQuestion(choice) } + + /** Alias for calling [addQuestion] with `Question.ofScore(score)`. */ + fun addQuestion(score: Question.Score) = apply { body.addQuestion(score) } + + /** + * Opaque caller-provided end-user identifier, scoped by the verified org. Match Responses' + * limit; this is never the authenticated user identity. + */ + fun safetyIdentifier(safetyIdentifier: String?) = apply { + body.safetyIdentifier(safetyIdentifier) + } + + /** Alias for calling [Builder.safetyIdentifier] with `safetyIdentifier.orElse(null)`. */ + fun safetyIdentifier(safetyIdentifier: Optional) = + safetyIdentifier(safetyIdentifier.getOrNull()) + + /** + * Sets [Builder.safetyIdentifier] to an arbitrary JSON value. + * + * You should usually call [Builder.safetyIdentifier] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun safetyIdentifier(safetyIdentifier: JsonField) = apply { + body.safetyIdentifier(safetyIdentifier) + } + + fun additionalBodyProperties(additionalBodyProperties: Map) = apply { + body.additionalProperties(additionalBodyProperties) + } + + fun putAdditionalBodyProperty(key: String, value: JsonValue) = apply { + body.putAdditionalProperty(key, value) + } + + fun putAllAdditionalBodyProperties(additionalBodyProperties: Map) = + apply { + body.putAllAdditionalProperties(additionalBodyProperties) + } + + fun removeAdditionalBodyProperty(key: String) = apply { body.removeAdditionalProperty(key) } + + fun removeAllAdditionalBodyProperties(keys: Set) = apply { + body.removeAllAdditionalProperties(keys) + } + + fun additionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun additionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun putAdditionalHeader(name: String, value: String) = apply { + additionalHeaders.put(name, value) + } + + fun putAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.put(name, values) + } + + fun putAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun putAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun replaceAdditionalHeaders(name: String, value: String) = apply { + additionalHeaders.replace(name, value) + } + + fun replaceAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.replace(name, values) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun removeAdditionalHeaders(name: String) = apply { additionalHeaders.remove(name) } + + fun removeAllAdditionalHeaders(names: Set) = apply { + additionalHeaders.removeAll(names) + } + + fun additionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun additionalQueryParams(additionalQueryParams: Map>) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun putAdditionalQueryParam(key: String, value: String) = apply { + additionalQueryParams.put(key, value) + } + + fun putAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.put(key, values) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun replaceAdditionalQueryParams(key: String, value: String) = apply { + additionalQueryParams.replace(key, value) + } + + fun replaceAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.replace(key, values) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun removeAdditionalQueryParams(key: String) = apply { additionalQueryParams.remove(key) } + + fun removeAllAdditionalQueryParams(keys: Set) = apply { + additionalQueryParams.removeAll(keys) + } + + /** + * Returns an immutable instance of [DecisionCreateParams]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .input() + * .model() + * .questions() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): DecisionCreateParams = + DecisionCreateParams( + body.build(), + additionalHeaders.build(), + additionalQueryParams.build(), + ) + } + + fun _body(): Body = body + + override fun _headers(): Headers = additionalHeaders + + override fun _queryParams(): QueryParams = additionalQueryParams + + class Body + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val input: JsonField, + private val model: JsonField, + private val questions: JsonField>, + private val safetyIdentifier: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("input") @ExcludeMissing input: JsonField = JsonMissing.of(), + @JsonProperty("model") @ExcludeMissing model: JsonField = JsonMissing.of(), + @JsonProperty("questions") + @ExcludeMissing + questions: JsonField> = JsonMissing.of(), + @JsonProperty("safety_identifier") + @ExcludeMissing + safetyIdentifier: JsonField = JsonMissing.of(), + ) : this(input, model, questions, safetyIdentifier, mutableMapOf()) + + /** + * Shared evidence, as a string or an array of user messages containing text and inline + * images. Non-user roles, function calls, function-call outputs, files, audio, and item + * references are not supported. At most 128 image parts are allowed across all messages in + * one request. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun input(): Input = input.getRequired("input") + + /** + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun model(): String = model.getRequired("model") + + /** + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun questions(): List = questions.getRequired("questions") + + /** + * Opaque caller-provided end-user identifier, scoped by the verified org. Match Responses' + * limit; this is never the authenticated user identity. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun safetyIdentifier(): Optional = safetyIdentifier.getOptional("safety_identifier") + + /** + * Returns the raw JSON value of [input]. + * + * Unlike [input], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("input") @ExcludeMissing fun _input(): JsonField = input + + /** + * Returns the raw JSON value of [model]. + * + * Unlike [model], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("model") @ExcludeMissing fun _model(): JsonField = model + + /** + * Returns the raw JSON value of [questions]. + * + * Unlike [questions], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("questions") + @ExcludeMissing + fun _questions(): JsonField> = questions + + /** + * Returns the raw JSON value of [safetyIdentifier]. + * + * Unlike [safetyIdentifier], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("safety_identifier") + @ExcludeMissing + fun _safetyIdentifier(): JsonField = safetyIdentifier + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [Body]. + * + * The following fields are required: + * ```java + * .input() + * .model() + * .questions() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Body]. */ + class Builder internal constructor() { + + private var input: JsonField? = null + private var model: JsonField? = null + private var questions: JsonField>? = null + private var safetyIdentifier: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(body: Body) = apply { + input = body.input + model = body.model + questions = body.questions.map { it.toMutableList() } + safetyIdentifier = body.safetyIdentifier + additionalProperties = body.additionalProperties.toMutableMap() + } + + /** + * Shared evidence, as a string or an array of user messages containing text and inline + * images. Non-user roles, function calls, function-call outputs, files, audio, and item + * references are not supported. At most 128 image parts are allowed across all messages + * in one request. + */ + fun input(input: Input) = input(JsonField.of(input)) + + /** + * Sets [Builder.input] to an arbitrary JSON value. + * + * You should usually call [Builder.input] with a well-typed [Input] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun input(input: JsonField) = apply { this.input = input } + + /** Alias for calling [input] with `Input.ofString(string)`. */ + fun input(string: String) = input(Input.ofString(string)) + + /** + * Alias for calling [input] with + * `Input.ofDecisionInputMessages(decisionInputMessages)`. + */ + fun inputOfDecisionInputMessages(decisionInputMessages: List) = + input(Input.ofDecisionInputMessages(decisionInputMessages)) + + fun model(model: String) = model(JsonField.of(model)) + + /** + * Sets [Builder.model] to an arbitrary JSON value. + * + * You should usually call [Builder.model] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun model(model: JsonField) = apply { this.model = model } + + fun questions(questions: List) = questions(JsonField.of(questions)) + + /** + * Sets [Builder.questions] to an arbitrary JSON value. + * + * You should usually call [Builder.questions] with a well-typed `List` value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun questions(questions: JsonField>) = apply { + this.questions = questions.map { it.toMutableList() } + } + + /** + * Adds a single [Question] to [questions]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addQuestion(question: Question) = apply { + questions = + (questions ?: JsonField.of(mutableListOf())).also { + checkKnown("questions", it).add(question) + } + } + + /** Alias for calling [addQuestion] with `Question.ofPredicate(predicate)`. */ + fun addQuestion(predicate: Question.Predicate) = + addQuestion(Question.ofPredicate(predicate)) + + /** + * Alias for calling [addQuestion] with the following: + * ```java + * Question.Predicate.builder() + * .instructions(instructions) + * .build() + * ``` + */ + fun addPredicateQuestion(instructions: String) = + addQuestion(Question.Predicate.builder().instructions(instructions).build()) + + /** Alias for calling [addQuestion] with `Question.ofChoice(choice)`. */ + fun addQuestion(choice: Question.Choice) = addQuestion(Question.ofChoice(choice)) + + /** Alias for calling [addQuestion] with `Question.ofScore(score)`. */ + fun addQuestion(score: Question.Score) = addQuestion(Question.ofScore(score)) + + /** + * Opaque caller-provided end-user identifier, scoped by the verified org. Match + * Responses' limit; this is never the authenticated user identity. + */ + fun safetyIdentifier(safetyIdentifier: String?) = + safetyIdentifier(JsonField.ofNullable(safetyIdentifier)) + + /** + * Alias for calling [Builder.safetyIdentifier] with `safetyIdentifier.orElse(null)`. + */ + fun safetyIdentifier(safetyIdentifier: Optional) = + safetyIdentifier(safetyIdentifier.getOrNull()) + + /** + * Sets [Builder.safetyIdentifier] to an arbitrary JSON value. + * + * You should usually call [Builder.safetyIdentifier] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun safetyIdentifier(safetyIdentifier: JsonField) = apply { + this.safetyIdentifier = safetyIdentifier + } + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { additionalProperties.remove(key) } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [Body]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .input() + * .model() + * .questions() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): Body = + Body( + checkRequired("input", input), + checkRequired("model", model), + checkRequired("questions", questions).map { it.toImmutable() }, + safetyIdentifier, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws OpenAIInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): Body = apply { + if (validated) { + return@apply + } + + input().validate() + model() + questions().forEach { it.validate() } + safetyIdentifier() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: OpenAIInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + (input.asKnown().getOrNull()?.validity() ?: 0) + + (if (model.asKnown().isPresent) 1 else 0) + + (questions.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + + (if (safetyIdentifier.asKnown().isPresent) 1 else 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Body && + input == other.input && + model == other.model && + questions == other.questions && + safetyIdentifier == other.safetyIdentifier && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(input, model, questions, safetyIdentifier, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Body{input=$input, model=$model, questions=$questions, safetyIdentifier=$safetyIdentifier, additionalProperties=$additionalProperties}" + } + + /** + * Shared evidence, as a string or an array of user messages containing text and inline images. + * Non-user roles, function calls, function-call outputs, files, audio, and item references are + * not supported. At most 128 image parts are allowed across all messages in one request. + */ + @JsonDeserialize(using = Input.Deserializer::class) + @JsonSerialize(using = Input.Serializer::class) + class Input + private constructor( + private val string: String? = null, + private val decisionInputMessages: List? = null, + private val _json: JsonValue? = null, + ) { + + fun string(): Optional = Optional.ofNullable(string) + + fun decisionInputMessages(): Optional> = + Optional.ofNullable(decisionInputMessages) + + fun isString(): Boolean = string != null + + fun isDecisionInputMessages(): Boolean = decisionInputMessages != null + + fun asString(): String = string.getOrThrow("string") + + fun asDecisionInputMessages(): List = + decisionInputMessages.getOrThrow("decisionInputMessages") + + fun _json(): Optional = Optional.ofNullable(_json) + + /** + * Maps this instance's current variant to a value of type [T] using the given [visitor]. + * + * Note that this method is _not_ forwards compatible with new variants from the API, unless + * [visitor] overrides [Visitor.unknown]. To handle variants not known to this version of + * the SDK gracefully, consider overriding [Visitor.unknown]: + * ```java + * import com.openai.core.JsonValue; + * import java.util.Optional; + * + * Optional result = input.accept(new Input.Visitor>() { + * @Override + * public Optional visitString(String string) { + * return Optional.of(string.toString()); + * } + * + * // ... + * + * @Override + * public Optional unknown(JsonValue json) { + * // Or inspect the `json`. + * return Optional.empty(); + * } + * }); + * ``` + * + * @throws OpenAIInvalidDataException if [Visitor.unknown] is not overridden in [visitor] + * and the current variant is unknown. + */ + fun accept(visitor: Visitor): T = + when { + string != null -> visitor.visitString(string) + decisionInputMessages != null -> + visitor.visitDecisionInputMessages(decisionInputMessages) + else -> visitor.unknown(_json) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws OpenAIInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): Input = apply { + if (validated) { + return@apply + } + + accept( + object : Visitor { + override fun visitString(string: String) {} + + override fun visitDecisionInputMessages( + decisionInputMessages: List + ) { + decisionInputMessages.forEach { it.validate() } + } + } + ) + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: OpenAIInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + accept( + object : Visitor { + override fun visitString(string: String) = 1 + + override fun visitDecisionInputMessages( + decisionInputMessages: List + ) = decisionInputMessages.sumOf { it.validity().toInt() } + + override fun unknown(json: JsonValue?) = 0 + } + ) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Input && + string == other.string && + decisionInputMessages == other.decisionInputMessages + } + + override fun hashCode(): Int = Objects.hash(string, decisionInputMessages) + + override fun toString(): String = + when { + string != null -> "Input{string=$string}" + decisionInputMessages != null -> + "Input{decisionInputMessages=$decisionInputMessages}" + _json != null -> "Input{_unknown=$_json}" + else -> throw IllegalStateException("Invalid Input") + } + + companion object { + + @JvmStatic fun ofString(string: String) = Input(string = string) + + @JvmStatic + fun ofDecisionInputMessages(decisionInputMessages: List) = + Input(decisionInputMessages = decisionInputMessages.toImmutable()) + } + + /** An interface that defines how to map each variant of [Input] to a value of type [T]. */ + interface Visitor { + + fun visitString(string: String): T + + fun visitDecisionInputMessages(decisionInputMessages: List): T + + /** + * Maps an unknown variant of [Input] to a value of type [T]. + * + * An instance of [Input] can contain an unknown variant if it was deserialized from + * data that doesn't match any known variant. For example, if the SDK is on an older + * version than the API, then the API may respond with new variants that the SDK is + * unaware of. + * + * @throws OpenAIInvalidDataException in the default implementation. + */ + fun unknown(json: JsonValue?): T { + throw OpenAIInvalidDataException("Unknown Input") + } + } + + internal class Deserializer : BaseDeserializer(Input::class) { + + override fun ObjectCodec.deserialize(node: JsonNode): Input { + val json = JsonValue.fromJsonNode(node) + + val bestMatches = + sequenceOf( + tryDeserialize(node, jacksonTypeRef())?.let { + Input(string = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef>()) + ?.let { Input(decisionInputMessages = it, _json = json) }, + ) + .filterNotNull() + .allMaxBy { it.validity() } + .toList() + return when (bestMatches.size) { + // This can happen if what we're deserializing is completely incompatible with + // all the possible variants (e.g. deserializing from boolean). + 0 -> Input(_json = json) + 1 -> bestMatches.single() + // If there's more than one match with the highest validity, then use the first + // completely valid match, or simply the first match if none are completely + // valid. + else -> bestMatches.firstOrNull { it.isValid() } ?: bestMatches.first() + } + } + } + + internal class Serializer : BaseSerializer(Input::class) { + + override fun serialize( + value: Input, + generator: JsonGenerator, + provider: SerializerProvider, + ) { + when { + value.string != null -> generator.writeObject(value.string) + value.decisionInputMessages != null -> + generator.writeObject(value.decisionInputMessages) + value._json != null -> generator.writeObject(value._json) + else -> throw IllegalStateException("Invalid Input") + } + } + } + } + + /** A question about the request's input, with an optional correlation name. */ + @JsonDeserialize(using = Question.Deserializer::class) + @JsonSerialize(using = Question.Serializer::class) + class Question + private constructor( + private val predicate: Predicate? = null, + private val choice: Choice? = null, + private val score: Score? = null, + private val _json: JsonValue? = null, + ) { + + fun predicate(): Optional = Optional.ofNullable(predicate) + + fun choice(): Optional = Optional.ofNullable(choice) + + fun score(): Optional = Optional.ofNullable(score) + + fun isPredicate(): Boolean = predicate != null + + fun isChoice(): Boolean = choice != null + + fun isScore(): Boolean = score != null + + fun asPredicate(): Predicate = predicate.getOrThrow("predicate") + + fun asChoice(): Choice = choice.getOrThrow("choice") + + fun asScore(): Score = score.getOrThrow("score") + + fun _json(): Optional = Optional.ofNullable(_json) + + /** + * Maps this instance's current variant to a value of type [T] using the given [visitor]. + * + * Note that this method is _not_ forwards compatible with new variants from the API, unless + * [visitor] overrides [Visitor.unknown]. To handle variants not known to this version of + * the SDK gracefully, consider overriding [Visitor.unknown]: + * ```java + * import com.openai.core.JsonValue; + * import java.util.Optional; + * + * Optional result = question.accept(new Question.Visitor>() { + * @Override + * public Optional visitPredicate(Predicate predicate) { + * return Optional.of(predicate.toString()); + * } + * + * // ... + * + * @Override + * public Optional unknown(JsonValue json) { + * // Or inspect the `json`. + * return Optional.empty(); + * } + * }); + * ``` + * + * @throws OpenAIInvalidDataException if [Visitor.unknown] is not overridden in [visitor] + * and the current variant is unknown. + */ + fun accept(visitor: Visitor): T = + when { + predicate != null -> visitor.visitPredicate(predicate) + choice != null -> visitor.visitChoice(choice) + score != null -> visitor.visitScore(score) + else -> visitor.unknown(_json) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws OpenAIInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): Question = apply { + if (validated) { + return@apply + } + + accept( + object : Visitor { + override fun visitPredicate(predicate: Predicate) { + predicate.validate() + } + + override fun visitChoice(choice: Choice) { + choice.validate() + } + + override fun visitScore(score: Score) { + score.validate() + } + } + ) + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: OpenAIInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + accept( + object : Visitor { + override fun visitPredicate(predicate: Predicate) = predicate.validity() + + override fun visitChoice(choice: Choice) = choice.validity() + + override fun visitScore(score: Score) = score.validity() + + override fun unknown(json: JsonValue?) = 0 + } + ) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Question && + predicate == other.predicate && + choice == other.choice && + score == other.score + } + + override fun hashCode(): Int = Objects.hash(predicate, choice, score) + + override fun toString(): String = + when { + predicate != null -> "Question{predicate=$predicate}" + choice != null -> "Question{choice=$choice}" + score != null -> "Question{score=$score}" + _json != null -> "Question{_unknown=$_json}" + else -> throw IllegalStateException("Invalid Question") + } + + companion object { + + @JvmStatic fun ofPredicate(predicate: Predicate) = Question(predicate = predicate) + + @JvmStatic fun ofChoice(choice: Choice) = Question(choice = choice) + + @JvmStatic fun ofScore(score: Score) = Question(score = score) + } + + /** + * An interface that defines how to map each variant of [Question] to a value of type [T]. + */ + interface Visitor { + + fun visitPredicate(predicate: Predicate): T + + fun visitChoice(choice: Choice): T + + fun visitScore(score: Score): T + + /** + * Maps an unknown variant of [Question] to a value of type [T]. + * + * An instance of [Question] can contain an unknown variant if it was deserialized from + * data that doesn't match any known variant. For example, if the SDK is on an older + * version than the API, then the API may respond with new variants that the SDK is + * unaware of. + * + * @throws OpenAIInvalidDataException in the default implementation. + */ + fun unknown(json: JsonValue?): T { + throw OpenAIInvalidDataException("Unknown Question") + } + } + + internal class Deserializer : BaseDeserializer(Question::class) { + + override fun ObjectCodec.deserialize(node: JsonNode): Question { + val json = JsonValue.fromJsonNode(node) + val type = json.asObject().getOrNull()?.get("type")?.asString()?.getOrNull() + + when (type) { + "predicate" -> { + return tryDeserialize(node, jacksonTypeRef())?.let { + Question(predicate = it, _json = json) + } ?: Question(_json = json) + } + "choice" -> { + return tryDeserialize(node, jacksonTypeRef())?.let { + Question(choice = it, _json = json) + } ?: Question(_json = json) + } + "score" -> { + return tryDeserialize(node, jacksonTypeRef())?.let { + Question(score = it, _json = json) + } ?: Question(_json = json) + } + } + + return Question(_json = json) + } + } + + internal class Serializer : BaseSerializer(Question::class) { + + override fun serialize( + value: Question, + generator: JsonGenerator, + provider: SerializerProvider, + ) { + when { + value.predicate != null -> generator.writeObject(value.predicate) + value.choice != null -> generator.writeObject(value.choice) + value.score != null -> generator.writeObject(value.score) + value._json != null -> generator.writeObject(value._json) + else -> throw IllegalStateException("Invalid Question") + } + } + } + + class Predicate + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val instructions: JsonField, + private val type: JsonValue, + private val name: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("instructions") + @ExcludeMissing + instructions: JsonField = JsonMissing.of(), + @JsonProperty("type") @ExcludeMissing type: JsonValue = JsonMissing.of(), + @JsonProperty("name") @ExcludeMissing name: JsonField = JsonMissing.of(), + ) : this(instructions, type, name, mutableMapOf()) + + /** + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected + * value). + */ + fun instructions(): String = instructions.getRequired("instructions") + + /** + * The type of the object. Always `predicate`. + * + * Expected to always return the following: + * ```java + * JsonValue.from("predicate") + * ``` + * + * However, this method can be useful for debugging and logging (e.g. if the server + * responded with an unexpected value). + */ + @JsonProperty("type") @ExcludeMissing fun _type(): JsonValue = type + + /** + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun name(): Optional = name.getOptional("name") + + /** + * Returns the raw JSON value of [instructions]. + * + * Unlike [instructions], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("instructions") + @ExcludeMissing + fun _instructions(): JsonField = instructions + + /** + * Returns the raw JSON value of [name]. + * + * Unlike [name], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("name") @ExcludeMissing fun _name(): JsonField = name + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [Predicate]. + * + * The following fields are required: + * ```java + * .instructions() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Predicate]. */ + class Builder internal constructor() { + + private var instructions: JsonField? = null + private var type: JsonValue = JsonValue.from("predicate") + private var name: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(predicate: Predicate) = apply { + instructions = predicate.instructions + type = predicate.type + name = predicate.name + additionalProperties = predicate.additionalProperties.toMutableMap() + } + + fun instructions(instructions: String) = instructions(JsonField.of(instructions)) + + /** + * Sets [Builder.instructions] to an arbitrary JSON value. + * + * You should usually call [Builder.instructions] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun instructions(instructions: JsonField) = apply { + this.instructions = instructions + } + + /** + * Sets the field to an arbitrary JSON value. + * + * It is usually unnecessary to call this method because the field defaults to the + * following: + * ```java + * JsonValue.from("predicate") + * ``` + * + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun type(type: JsonValue) = apply { this.type = type } + + fun name(name: String) = name(JsonField.of(name)) + + /** + * Sets [Builder.name] to an arbitrary JSON value. + * + * You should usually call [Builder.name] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun name(name: JsonField) = apply { this.name = name } + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = + apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { + additionalProperties.remove(key) + } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [Predicate]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .instructions() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): Predicate = + Predicate( + checkRequired("instructions", instructions), + type, + name, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws OpenAIInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): Predicate = apply { + if (validated) { + return@apply + } + + instructions() + _type().let { + if (it != JsonValue.from("predicate")) { + throw OpenAIInvalidDataException("'type' is invalid, received $it") + } + } + name() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: OpenAIInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + (if (instructions.asKnown().isPresent) 1 else 0) + + type.let { if (it == JsonValue.from("predicate")) 1 else 0 } + + (if (name.asKnown().isPresent) 1 else 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Predicate && + instructions == other.instructions && + type == other.type && + name == other.name && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(instructions, type, name, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Predicate{instructions=$instructions, type=$type, name=$name, additionalProperties=$additionalProperties}" + } + + class Choice + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val choices: JsonField>, + private val instructions: JsonField, + private val type: JsonValue, + private val name: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("choices") + @ExcludeMissing + choices: JsonField> = JsonMissing.of(), + @JsonProperty("instructions") + @ExcludeMissing + instructions: JsonField = JsonMissing.of(), + @JsonProperty("type") @ExcludeMissing type: JsonValue = JsonMissing.of(), + @JsonProperty("name") @ExcludeMissing name: JsonField = JsonMissing.of(), + ) : this(choices, instructions, type, name, mutableMapOf()) + + /** + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected + * value). + */ + fun choices(): List = choices.getRequired("choices") + + /** + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected + * value). + */ + fun instructions(): String = instructions.getRequired("instructions") + + /** + * The type of the object. Always `choice`. + * + * Expected to always return the following: + * ```java + * JsonValue.from("choice") + * ``` + * + * However, this method can be useful for debugging and logging (e.g. if the server + * responded with an unexpected value). + */ + @JsonProperty("type") @ExcludeMissing fun _type(): JsonValue = type + + /** + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun name(): Optional = name.getOptional("name") + + /** + * Returns the raw JSON value of [choices]. + * + * Unlike [choices], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("choices") + @ExcludeMissing + fun _choices(): JsonField> = choices + + /** + * Returns the raw JSON value of [instructions]. + * + * Unlike [instructions], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("instructions") + @ExcludeMissing + fun _instructions(): JsonField = instructions + + /** + * Returns the raw JSON value of [name]. + * + * Unlike [name], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("name") @ExcludeMissing fun _name(): JsonField = name + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [Choice]. + * + * The following fields are required: + * ```java + * .choices() + * .instructions() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Choice]. */ + class Builder internal constructor() { + + private var choices: JsonField>? = null + private var instructions: JsonField? = null + private var type: JsonValue = JsonValue.from("choice") + private var name: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(choice: Choice) = apply { + choices = choice.choices.map { it.toMutableList() } + instructions = choice.instructions + type = choice.type + name = choice.name + additionalProperties = choice.additionalProperties.toMutableMap() + } + + fun choices(choices: List) = choices(JsonField.of(choices)) + + /** + * Sets [Builder.choices] to an arbitrary JSON value. + * + * You should usually call [Builder.choices] with a well-typed + * `List` value instead. This method is primarily for setting + * the field to an undocumented or not yet supported value. + */ + fun choices(choices: JsonField>) = apply { + this.choices = choices.map { it.toMutableList() } + } + + /** + * Adds a single [DecisionChoiceOption] to [choices]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addChoice(choice: DecisionChoiceOption) = apply { + choices = + (choices ?: JsonField.of(mutableListOf())).also { + checkKnown("choices", it).add(choice) + } + } + + fun instructions(instructions: String) = instructions(JsonField.of(instructions)) + + /** + * Sets [Builder.instructions] to an arbitrary JSON value. + * + * You should usually call [Builder.instructions] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun instructions(instructions: JsonField) = apply { + this.instructions = instructions + } + + /** + * Sets the field to an arbitrary JSON value. + * + * It is usually unnecessary to call this method because the field defaults to the + * following: + * ```java + * JsonValue.from("choice") + * ``` + * + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun type(type: JsonValue) = apply { this.type = type } + + fun name(name: String) = name(JsonField.of(name)) + + /** + * Sets [Builder.name] to an arbitrary JSON value. + * + * You should usually call [Builder.name] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun name(name: JsonField) = apply { this.name = name } + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = + apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { + additionalProperties.remove(key) + } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [Choice]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .choices() + * .instructions() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): Choice = + Choice( + checkRequired("choices", choices).map { it.toImmutable() }, + checkRequired("instructions", instructions), + type, + name, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws OpenAIInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): Choice = apply { + if (validated) { + return@apply + } + + choices().forEach { it.validate() } + instructions() + _type().let { + if (it != JsonValue.from("choice")) { + throw OpenAIInvalidDataException("'type' is invalid, received $it") + } + } + name() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: OpenAIInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + (choices.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + + (if (instructions.asKnown().isPresent) 1 else 0) + + type.let { if (it == JsonValue.from("choice")) 1 else 0 } + + (if (name.asKnown().isPresent) 1 else 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Choice && + choices == other.choices && + instructions == other.instructions && + type == other.type && + name == other.name && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(choices, instructions, type, name, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Choice{choices=$choices, instructions=$instructions, type=$type, name=$name, additionalProperties=$additionalProperties}" + } + + class Score + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val instructions: JsonField, + private val levels: JsonField>, + private val type: JsonValue, + private val name: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("instructions") + @ExcludeMissing + instructions: JsonField = JsonMissing.of(), + @JsonProperty("levels") + @ExcludeMissing + levels: JsonField> = JsonMissing.of(), + @JsonProperty("type") @ExcludeMissing type: JsonValue = JsonMissing.of(), + @JsonProperty("name") @ExcludeMissing name: JsonField = JsonMissing.of(), + ) : this(instructions, levels, type, name, mutableMapOf()) + + /** + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected + * value). + */ + fun instructions(): String = instructions.getRequired("instructions") + + /** + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected + * value). + */ + fun levels(): List = levels.getRequired("levels") + + /** + * The type of the object. Always `score`. + * + * Expected to always return the following: + * ```java + * JsonValue.from("score") + * ``` + * + * However, this method can be useful for debugging and logging (e.g. if the server + * responded with an unexpected value). + */ + @JsonProperty("type") @ExcludeMissing fun _type(): JsonValue = type + + /** + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun name(): Optional = name.getOptional("name") + + /** + * Returns the raw JSON value of [instructions]. + * + * Unlike [instructions], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("instructions") + @ExcludeMissing + fun _instructions(): JsonField = instructions + + /** + * Returns the raw JSON value of [levels]. + * + * Unlike [levels], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("levels") @ExcludeMissing fun _levels(): JsonField> = levels + + /** + * Returns the raw JSON value of [name]. + * + * Unlike [name], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("name") @ExcludeMissing fun _name(): JsonField = name + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [Score]. + * + * The following fields are required: + * ```java + * .instructions() + * .levels() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Score]. */ + class Builder internal constructor() { + + private var instructions: JsonField? = null + private var levels: JsonField>? = null + private var type: JsonValue = JsonValue.from("score") + private var name: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(score: Score) = apply { + instructions = score.instructions + levels = score.levels.map { it.toMutableList() } + type = score.type + name = score.name + additionalProperties = score.additionalProperties.toMutableMap() + } + + fun instructions(instructions: String) = instructions(JsonField.of(instructions)) + + /** + * Sets [Builder.instructions] to an arbitrary JSON value. + * + * You should usually call [Builder.instructions] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun instructions(instructions: JsonField) = apply { + this.instructions = instructions + } + + fun levels(levels: List) = levels(JsonField.of(levels)) + + /** + * Sets [Builder.levels] to an arbitrary JSON value. + * + * You should usually call [Builder.levels] with a well-typed `List` value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun levels(levels: JsonField>) = apply { + this.levels = levels.map { it.toMutableList() } + } + + /** + * Adds a single [Level] to [levels]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addLevel(level: Level) = apply { + levels = + (levels ?: JsonField.of(mutableListOf())).also { + checkKnown("levels", it).add(level) + } + } + + /** + * Sets the field to an arbitrary JSON value. + * + * It is usually unnecessary to call this method because the field defaults to the + * following: + * ```java + * JsonValue.from("score") + * ``` + * + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun type(type: JsonValue) = apply { this.type = type } + + fun name(name: String) = name(JsonField.of(name)) + + /** + * Sets [Builder.name] to an arbitrary JSON value. + * + * You should usually call [Builder.name] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun name(name: JsonField) = apply { this.name = name } + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = + apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { + additionalProperties.remove(key) + } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [Score]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .instructions() + * .levels() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): Score = + Score( + checkRequired("instructions", instructions), + checkRequired("levels", levels).map { it.toImmutable() }, + type, + name, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws OpenAIInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): Score = apply { + if (validated) { + return@apply + } + + instructions() + levels().forEach { it.validate() } + _type().let { + if (it != JsonValue.from("score")) { + throw OpenAIInvalidDataException("'type' is invalid, received $it") + } + } + name() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: OpenAIInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + (if (instructions.asKnown().isPresent) 1 else 0) + + (levels.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + + type.let { if (it == JsonValue.from("score")) 1 else 0 } + + (if (name.asKnown().isPresent) 1 else 0) + + class Level + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val label: JsonField, + private val description: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("label") + @ExcludeMissing + label: JsonField = JsonMissing.of(), + @JsonProperty("description") + @ExcludeMissing + description: JsonField = JsonMissing.of(), + ) : this(label, description, mutableMapOf()) + + /** + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected + * value). + */ + fun label(): String = label.getRequired("label") + + /** + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. + * if the server responded with an unexpected value). + */ + fun description(): Optional = description.getOptional("description") + + /** + * Returns the raw JSON value of [label]. + * + * Unlike [label], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("label") @ExcludeMissing fun _label(): JsonField = label + + /** + * Returns the raw JSON value of [description]. + * + * Unlike [description], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("description") + @ExcludeMissing + fun _description(): JsonField = description + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [Level]. + * + * The following fields are required: + * ```java + * .label() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Level]. */ + class Builder internal constructor() { + + private var label: JsonField? = null + private var description: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(level: Level) = apply { + label = level.label + description = level.description + additionalProperties = level.additionalProperties.toMutableMap() + } + + fun label(label: String) = label(JsonField.of(label)) + + /** + * Sets [Builder.label] to an arbitrary JSON value. + * + * You should usually call [Builder.label] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or + * not yet supported value. + */ + fun label(label: JsonField) = apply { this.label = label } + + fun description(description: String) = description(JsonField.of(description)) + + /** + * Sets [Builder.description] to an arbitrary JSON value. + * + * You should usually call [Builder.description] with a well-typed [String] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun description(description: JsonField) = apply { + this.description = description + } + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = + apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { + additionalProperties.remove(key) + } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [Level]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .label() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): Level = + Level( + checkRequired("label", label), + description, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws OpenAIInvalidDataException if any value type in this object doesn't match + * its expected type. + */ + fun validate(): Level = apply { + if (validated) { + return@apply + } + + label() + description() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: OpenAIInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + (if (label.asKnown().isPresent) 1 else 0) + + (if (description.asKnown().isPresent) 1 else 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Level && + label == other.label && + description == other.description && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(label, description, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Level{label=$label, description=$description, additionalProperties=$additionalProperties}" + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Score && + instructions == other.instructions && + levels == other.levels && + type == other.type && + name == other.name && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(instructions, levels, type, name, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Score{instructions=$instructions, levels=$levels, type=$type, name=$name, additionalProperties=$additionalProperties}" + } + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is DecisionCreateParams && + body == other.body && + additionalHeaders == other.additionalHeaders && + additionalQueryParams == other.additionalQueryParams + } + + override fun hashCode(): Int = Objects.hash(body, additionalHeaders, additionalQueryParams) + + override fun toString() = + "DecisionCreateParams{body=$body, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" +} diff --git a/openai-java-core/src/main/kotlin/com/openai/models/decisions/DecisionInputImage.kt b/openai-java-core/src/main/kotlin/com/openai/models/decisions/DecisionInputImage.kt new file mode 100644 index 000000000..8a5390d9e --- /dev/null +++ b/openai-java-core/src/main/kotlin/com/openai/models/decisions/DecisionInputImage.kt @@ -0,0 +1,408 @@ +// File generated from our OpenAPI spec by Castiron. See CONTRIBUTING.md for details. + +package com.openai.models.decisions + +import com.fasterxml.jackson.annotation.JsonAnyGetter +import com.fasterxml.jackson.annotation.JsonAnySetter +import com.fasterxml.jackson.annotation.JsonCreator +import com.fasterxml.jackson.annotation.JsonProperty +import com.openai.core.Enum +import com.openai.core.ExcludeMissing +import com.openai.core.JsonField +import com.openai.core.JsonMissing +import com.openai.core.JsonValue +import com.openai.core.checkRequired +import com.openai.errors.OpenAIInvalidDataException +import java.util.Collections +import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +/** An inline image. External URLs and file IDs are not supported. */ +class DecisionInputImage +@JsonCreator(mode = JsonCreator.Mode.DISABLED) +private constructor( + private val imageUrl: JsonField, + private val type: JsonValue, + private val detail: JsonField, + private val additionalProperties: MutableMap, +) { + + @JsonCreator + private constructor( + @JsonProperty("image_url") @ExcludeMissing imageUrl: JsonField = JsonMissing.of(), + @JsonProperty("type") @ExcludeMissing type: JsonValue = JsonMissing.of(), + @JsonProperty("detail") @ExcludeMissing detail: JsonField = JsonMissing.of(), + ) : this(imageUrl, type, detail, mutableMapOf()) + + /** + * A base64-encoded image in a data URL. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun imageUrl(): String = imageUrl.getRequired("image_url") + + /** + * Expected to always return the following: + * ```java + * JsonValue.from("input_image") + * ``` + * + * However, this method can be useful for debugging and logging (e.g. if the server responded + * with an unexpected value). + */ + @JsonProperty("type") @ExcludeMissing fun _type(): JsonValue = type + + /** + * The image detail level, using the selected model's image profile. Defaults to auto. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun detail(): Optional = detail.getOptional("detail") + + /** + * Returns the raw JSON value of [imageUrl]. + * + * Unlike [imageUrl], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("image_url") @ExcludeMissing fun _imageUrl(): JsonField = imageUrl + + /** + * Returns the raw JSON value of [detail]. + * + * Unlike [detail], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("detail") @ExcludeMissing fun _detail(): JsonField = detail + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [DecisionInputImage]. + * + * The following fields are required: + * ```java + * .imageUrl() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [DecisionInputImage]. */ + class Builder internal constructor() { + + private var imageUrl: JsonField? = null + private var type: JsonValue = JsonValue.from("input_image") + private var detail: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(decisionInputImage: DecisionInputImage) = apply { + imageUrl = decisionInputImage.imageUrl + type = decisionInputImage.type + detail = decisionInputImage.detail + additionalProperties = decisionInputImage.additionalProperties.toMutableMap() + } + + /** A base64-encoded image in a data URL. */ + fun imageUrl(imageUrl: String) = imageUrl(JsonField.of(imageUrl)) + + /** + * Sets [Builder.imageUrl] to an arbitrary JSON value. + * + * You should usually call [Builder.imageUrl] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun imageUrl(imageUrl: JsonField) = apply { this.imageUrl = imageUrl } + + /** + * Sets the field to an arbitrary JSON value. + * + * It is usually unnecessary to call this method because the field defaults to the + * following: + * ```java + * JsonValue.from("input_image") + * ``` + * + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun type(type: JsonValue) = apply { this.type = type } + + /** The image detail level, using the selected model's image profile. Defaults to auto. */ + fun detail(detail: Detail?) = detail(JsonField.ofNullable(detail)) + + /** Alias for calling [Builder.detail] with `detail.orElse(null)`. */ + fun detail(detail: Optional) = detail(detail.getOrNull()) + + /** + * Sets [Builder.detail] to an arbitrary JSON value. + * + * You should usually call [Builder.detail] with a well-typed [Detail] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun detail(detail: JsonField) = apply { this.detail = detail } + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { additionalProperties.remove(key) } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [DecisionInputImage]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .imageUrl() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): DecisionInputImage = + DecisionInputImage( + checkRequired("imageUrl", imageUrl), + type, + detail, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws OpenAIInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): DecisionInputImage = apply { + if (validated) { + return@apply + } + + imageUrl() + _type().let { + if (it != JsonValue.from("input_image")) { + throw OpenAIInvalidDataException("'type' is invalid, received $it") + } + } + detail().ifPresent { it.validate() } + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: OpenAIInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + (if (imageUrl.asKnown().isPresent) 1 else 0) + + type.let { if (it == JsonValue.from("input_image")) 1 else 0 } + + (detail.asKnown().getOrNull()?.validity() ?: 0) + + /** The image detail level, using the selected model's image profile. Defaults to auto. */ + class Detail @JsonCreator private constructor(private val value: JsonField) : Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that doesn't + * match any known member, and you want to know that value. For example, if the SDK is on an + * older version than the API, then the API may respond with new members that the SDK is + * unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val LOW = of("low") + + @JvmField val HIGH = of("high") + + @JvmField val AUTO = of("auto") + + @JvmField val ORIGINAL = of("original") + + @JvmStatic fun of(value: String) = Detail(JsonField.of(value)) + } + + /** An enum containing [Detail]'s known values. */ + enum class Known { + LOW, + HIGH, + AUTO, + ORIGINAL, + } + + /** + * An enum containing [Detail]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [Detail] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, if the + * SDK is on an older version than the API, then the API may respond with new members that + * the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + LOW, + HIGH, + AUTO, + ORIGINAL, + /** An enum member indicating that [Detail] was instantiated with an unknown value. */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or [Value._UNKNOWN] + * if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if you want + * to throw for the unknown case. + */ + fun value(): Value = + when (this) { + LOW -> Value.LOW + HIGH -> Value.HIGH + AUTO -> Value.AUTO + ORIGINAL -> Value.ORIGINAL + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and don't + * want to throw for the unknown case. + * + * @throws OpenAIInvalidDataException if this class instance's value is a not a known + * member. + */ + fun known(): Known = + when (this) { + LOW -> Known.LOW + HIGH -> Known.HIGH + AUTO -> Known.AUTO + ORIGINAL -> Known.ORIGINAL + else -> throw OpenAIInvalidDataException("Unknown Detail: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for debugging + * and generally doesn't throw. + * + * @throws OpenAIInvalidDataException if this class instance's value does not have the + * expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { OpenAIInvalidDataException("Value is not a String") } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws OpenAIInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): Detail = apply { + if (validated) { + return@apply + } + + known() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: OpenAIInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Detail && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is DecisionInputImage && + imageUrl == other.imageUrl && + type == other.type && + detail == other.detail && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(imageUrl, type, detail, additionalProperties) } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "DecisionInputImage{imageUrl=$imageUrl, type=$type, detail=$detail, additionalProperties=$additionalProperties}" +} diff --git a/openai-java-core/src/main/kotlin/com/openai/models/decisions/DecisionInputMessage.kt b/openai-java-core/src/main/kotlin/com/openai/models/decisions/DecisionInputMessage.kt new file mode 100644 index 000000000..1d8c14b46 --- /dev/null +++ b/openai-java-core/src/main/kotlin/com/openai/models/decisions/DecisionInputMessage.kt @@ -0,0 +1,613 @@ +// File generated from our OpenAPI spec by Castiron. See CONTRIBUTING.md for details. + +package com.openai.models.decisions + +import com.fasterxml.jackson.annotation.JsonAnyGetter +import com.fasterxml.jackson.annotation.JsonAnySetter +import com.fasterxml.jackson.annotation.JsonCreator +import com.fasterxml.jackson.annotation.JsonProperty +import com.fasterxml.jackson.core.JsonGenerator +import com.fasterxml.jackson.core.ObjectCodec +import com.fasterxml.jackson.databind.JsonNode +import com.fasterxml.jackson.databind.SerializerProvider +import com.fasterxml.jackson.databind.annotation.JsonDeserialize +import com.fasterxml.jackson.databind.annotation.JsonSerialize +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import com.openai.core.BaseDeserializer +import com.openai.core.BaseSerializer +import com.openai.core.Enum +import com.openai.core.ExcludeMissing +import com.openai.core.JsonField +import com.openai.core.JsonMissing +import com.openai.core.JsonValue +import com.openai.core.allMaxBy +import com.openai.core.checkRequired +import com.openai.core.getOrThrow +import com.openai.core.toImmutable +import com.openai.errors.OpenAIInvalidDataException +import java.util.Collections +import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +/** A user message containing text or inline images. */ +class DecisionInputMessage +@JsonCreator(mode = JsonCreator.Mode.DISABLED) +private constructor( + private val content: JsonField, + private val role: JsonValue, + private val type: JsonField, + private val additionalProperties: MutableMap, +) { + + @JsonCreator + private constructor( + @JsonProperty("content") @ExcludeMissing content: JsonField = JsonMissing.of(), + @JsonProperty("role") @ExcludeMissing role: JsonValue = JsonMissing.of(), + @JsonProperty("type") @ExcludeMissing type: JsonField = JsonMissing.of(), + ) : this(content, role, type, mutableMapOf()) + + /** + * Text evidence or an ordered list of text and inline image parts. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun content(): Content = content.getRequired("content") + + /** + * Expected to always return the following: + * ```java + * JsonValue.from("user") + * ``` + * + * However, this method can be useful for debugging and logging (e.g. if the server responded + * with an unexpected value). + */ + @JsonProperty("role") @ExcludeMissing fun _role(): JsonValue = role + + /** + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun type(): Optional = type.getOptional("type") + + /** + * Returns the raw JSON value of [content]. + * + * Unlike [content], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("content") @ExcludeMissing fun _content(): JsonField = content + + /** + * Returns the raw JSON value of [type]. + * + * Unlike [type], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("type") @ExcludeMissing fun _type(): JsonField = type + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [DecisionInputMessage]. + * + * The following fields are required: + * ```java + * .content() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [DecisionInputMessage]. */ + class Builder internal constructor() { + + private var content: JsonField? = null + private var role: JsonValue = JsonValue.from("user") + private var type: JsonField = JsonField.of(Type.MESSAGE) + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(decisionInputMessage: DecisionInputMessage) = apply { + content = decisionInputMessage.content + role = decisionInputMessage.role + type = decisionInputMessage.type + additionalProperties = decisionInputMessage.additionalProperties.toMutableMap() + } + + /** Text evidence or an ordered list of text and inline image parts. */ + fun content(content: Content) = content(JsonField.of(content)) + + /** + * Sets [Builder.content] to an arbitrary JSON value. + * + * You should usually call [Builder.content] with a well-typed [Content] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun content(content: JsonField) = apply { this.content = content } + + /** Alias for calling [content] with `Content.ofString(string)`. */ + fun content(string: String) = content(Content.ofString(string)) + + /** Alias for calling [content] with `Content.ofParts(parts)`. */ + fun contentOfParts(parts: List) = content(Content.ofParts(parts)) + + /** + * Sets the field to an arbitrary JSON value. + * + * It is usually unnecessary to call this method because the field defaults to the + * following: + * ```java + * JsonValue.from("user") + * ``` + * + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun role(role: JsonValue) = apply { this.role = role } + + fun type(type: Type) = type(JsonField.of(type)) + + /** + * Sets [Builder.type] to an arbitrary JSON value. + * + * You should usually call [Builder.type] with a well-typed [Type] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun type(type: JsonField) = apply { this.type = type } + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { additionalProperties.remove(key) } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [DecisionInputMessage]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .content() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): DecisionInputMessage = + DecisionInputMessage( + checkRequired("content", content), + role, + type, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws OpenAIInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): DecisionInputMessage = apply { + if (validated) { + return@apply + } + + content().validate() + _role().let { + if (it != JsonValue.from("user")) { + throw OpenAIInvalidDataException("'role' is invalid, received $it") + } + } + type().ifPresent { it.validate() } + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: OpenAIInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + (content.asKnown().getOrNull()?.validity() ?: 0) + + role.let { if (it == JsonValue.from("user")) 1 else 0 } + + (type.asKnown().getOrNull()?.validity() ?: 0) + + /** Text evidence or an ordered list of text and inline image parts. */ + @JsonDeserialize(using = Content.Deserializer::class) + @JsonSerialize(using = Content.Serializer::class) + class Content + private constructor( + private val string: String? = null, + private val parts: List? = null, + private val _json: JsonValue? = null, + ) { + + fun string(): Optional = Optional.ofNullable(string) + + fun parts(): Optional> = Optional.ofNullable(parts) + + fun isString(): Boolean = string != null + + fun isParts(): Boolean = parts != null + + fun asString(): String = string.getOrThrow("string") + + fun asParts(): List = parts.getOrThrow("parts") + + fun _json(): Optional = Optional.ofNullable(_json) + + /** + * Maps this instance's current variant to a value of type [T] using the given [visitor]. + * + * Note that this method is _not_ forwards compatible with new variants from the API, unless + * [visitor] overrides [Visitor.unknown]. To handle variants not known to this version of + * the SDK gracefully, consider overriding [Visitor.unknown]: + * ```java + * import com.openai.core.JsonValue; + * import java.util.Optional; + * + * Optional result = content.accept(new Content.Visitor>() { + * @Override + * public Optional visitString(String string) { + * return Optional.of(string.toString()); + * } + * + * // ... + * + * @Override + * public Optional unknown(JsonValue json) { + * // Or inspect the `json`. + * return Optional.empty(); + * } + * }); + * ``` + * + * @throws OpenAIInvalidDataException if [Visitor.unknown] is not overridden in [visitor] + * and the current variant is unknown. + */ + fun accept(visitor: Visitor): T = + when { + string != null -> visitor.visitString(string) + parts != null -> visitor.visitParts(parts) + else -> visitor.unknown(_json) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws OpenAIInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): Content = apply { + if (validated) { + return@apply + } + + accept( + object : Visitor { + override fun visitString(string: String) {} + + override fun visitParts(parts: List) { + parts.forEach { it.validate() } + } + } + ) + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: OpenAIInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + accept( + object : Visitor { + override fun visitString(string: String) = 1 + + override fun visitParts(parts: List) = + parts.sumOf { it.validity().toInt() } + + override fun unknown(json: JsonValue?) = 0 + } + ) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Content && string == other.string && parts == other.parts + } + + override fun hashCode(): Int = Objects.hash(string, parts) + + override fun toString(): String = + when { + string != null -> "Content{string=$string}" + parts != null -> "Content{parts=$parts}" + _json != null -> "Content{_unknown=$_json}" + else -> throw IllegalStateException("Invalid Content") + } + + companion object { + + @JvmStatic fun ofString(string: String) = Content(string = string) + + @JvmStatic + fun ofParts(parts: List) = Content(parts = parts.toImmutable()) + } + + /** + * An interface that defines how to map each variant of [Content] to a value of type [T]. + */ + interface Visitor { + + fun visitString(string: String): T + + fun visitParts(parts: List): T + + /** + * Maps an unknown variant of [Content] to a value of type [T]. + * + * An instance of [Content] can contain an unknown variant if it was deserialized from + * data that doesn't match any known variant. For example, if the SDK is on an older + * version than the API, then the API may respond with new variants that the SDK is + * unaware of. + * + * @throws OpenAIInvalidDataException in the default implementation. + */ + fun unknown(json: JsonValue?): T { + throw OpenAIInvalidDataException("Unknown Content") + } + } + + internal class Deserializer : BaseDeserializer(Content::class) { + + override fun ObjectCodec.deserialize(node: JsonNode): Content { + val json = JsonValue.fromJsonNode(node) + + val bestMatches = + sequenceOf( + tryDeserialize(node, jacksonTypeRef())?.let { + Content(string = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef>())?.let { + Content(parts = it, _json = json) + }, + ) + .filterNotNull() + .allMaxBy { it.validity() } + .toList() + return when (bestMatches.size) { + // This can happen if what we're deserializing is completely incompatible with + // all the possible variants (e.g. deserializing from boolean). + 0 -> Content(_json = json) + 1 -> bestMatches.single() + // If there's more than one match with the highest validity, then use the first + // completely valid match, or simply the first match if none are completely + // valid. + else -> bestMatches.firstOrNull { it.isValid() } ?: bestMatches.first() + } + } + } + + internal class Serializer : BaseSerializer(Content::class) { + + override fun serialize( + value: Content, + generator: JsonGenerator, + provider: SerializerProvider, + ) { + when { + value.string != null -> generator.writeObject(value.string) + value.parts != null -> generator.writeObject(value.parts) + value._json != null -> generator.writeObject(value._json) + else -> throw IllegalStateException("Invalid Content") + } + } + } + } + + class Type @JsonCreator private constructor(private val value: JsonField) : Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that doesn't + * match any known member, and you want to know that value. For example, if the SDK is on an + * older version than the API, then the API may respond with new members that the SDK is + * unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val MESSAGE = of("message") + + @JvmStatic fun of(value: String) = Type(JsonField.of(value)) + } + + /** An enum containing [Type]'s known values. */ + enum class Known { + MESSAGE + } + + /** + * An enum containing [Type]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [Type] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, if the + * SDK is on an older version than the API, then the API may respond with new members that + * the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + MESSAGE, + /** An enum member indicating that [Type] was instantiated with an unknown value. */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or [Value._UNKNOWN] + * if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if you want + * to throw for the unknown case. + */ + fun value(): Value = + when (this) { + MESSAGE -> Value.MESSAGE + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and don't + * want to throw for the unknown case. + * + * @throws OpenAIInvalidDataException if this class instance's value is a not a known + * member. + */ + fun known(): Known = + when (this) { + MESSAGE -> Known.MESSAGE + else -> throw OpenAIInvalidDataException("Unknown Type: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for debugging + * and generally doesn't throw. + * + * @throws OpenAIInvalidDataException if this class instance's value does not have the + * expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { OpenAIInvalidDataException("Value is not a String") } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws OpenAIInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): Type = apply { + if (validated) { + return@apply + } + + known() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: OpenAIInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Type && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is DecisionInputMessage && + content == other.content && + role == other.role && + type == other.type && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(content, role, type, additionalProperties) } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "DecisionInputMessage{content=$content, role=$role, type=$type, additionalProperties=$additionalProperties}" +} diff --git a/openai-java-core/src/main/kotlin/com/openai/models/decisions/DecisionInputPart.kt b/openai-java-core/src/main/kotlin/com/openai/models/decisions/DecisionInputPart.kt new file mode 100644 index 000000000..d48332904 --- /dev/null +++ b/openai-java-core/src/main/kotlin/com/openai/models/decisions/DecisionInputPart.kt @@ -0,0 +1,232 @@ +// File generated from our OpenAPI spec by Castiron. See CONTRIBUTING.md for details. + +package com.openai.models.decisions + +import com.fasterxml.jackson.core.JsonGenerator +import com.fasterxml.jackson.core.ObjectCodec +import com.fasterxml.jackson.databind.JsonNode +import com.fasterxml.jackson.databind.SerializerProvider +import com.fasterxml.jackson.databind.annotation.JsonDeserialize +import com.fasterxml.jackson.databind.annotation.JsonSerialize +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import com.openai.core.BaseDeserializer +import com.openai.core.BaseSerializer +import com.openai.core.JsonValue +import com.openai.core.getOrThrow +import com.openai.errors.OpenAIInvalidDataException +import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +/** An inline image. External URLs and file IDs are not supported. */ +@JsonDeserialize(using = DecisionInputPart.Deserializer::class) +@JsonSerialize(using = DecisionInputPart.Serializer::class) +class DecisionInputPart +private constructor( + private val inputText: DecisionInputText? = null, + private val inputImage: DecisionInputImage? = null, + private val _json: JsonValue? = null, +) { + + fun inputText(): Optional = Optional.ofNullable(inputText) + + /** An inline image. External URLs and file IDs are not supported. */ + fun inputImage(): Optional = Optional.ofNullable(inputImage) + + fun isInputText(): Boolean = inputText != null + + fun isInputImage(): Boolean = inputImage != null + + fun asInputText(): DecisionInputText = inputText.getOrThrow("inputText") + + /** An inline image. External URLs and file IDs are not supported. */ + fun asInputImage(): DecisionInputImage = inputImage.getOrThrow("inputImage") + + fun _json(): Optional = Optional.ofNullable(_json) + + /** + * Maps this instance's current variant to a value of type [T] using the given [visitor]. + * + * Note that this method is _not_ forwards compatible with new variants from the API, unless + * [visitor] overrides [Visitor.unknown]. To handle variants not known to this version of the + * SDK gracefully, consider overriding [Visitor.unknown]: + * ```java + * import com.openai.core.JsonValue; + * import java.util.Optional; + * + * Optional result = decisionInputPart.accept(new DecisionInputPart.Visitor>() { + * @Override + * public Optional visitInputText(DecisionInputText inputText) { + * return Optional.of(inputText.toString()); + * } + * + * // ... + * + * @Override + * public Optional unknown(JsonValue json) { + * // Or inspect the `json`. + * return Optional.empty(); + * } + * }); + * ``` + * + * @throws OpenAIInvalidDataException if [Visitor.unknown] is not overridden in [visitor] and + * the current variant is unknown. + */ + fun accept(visitor: Visitor): T = + when { + inputText != null -> visitor.visitInputText(inputText) + inputImage != null -> visitor.visitInputImage(inputImage) + else -> visitor.unknown(_json) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws OpenAIInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): DecisionInputPart = apply { + if (validated) { + return@apply + } + + accept( + object : Visitor { + override fun visitInputText(inputText: DecisionInputText) { + inputText.validate() + } + + override fun visitInputImage(inputImage: DecisionInputImage) { + inputImage.validate() + } + } + ) + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: OpenAIInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + accept( + object : Visitor { + override fun visitInputText(inputText: DecisionInputText) = inputText.validity() + + override fun visitInputImage(inputImage: DecisionInputImage) = inputImage.validity() + + override fun unknown(json: JsonValue?) = 0 + } + ) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is DecisionInputPart && + inputText == other.inputText && + inputImage == other.inputImage + } + + override fun hashCode(): Int = Objects.hash(inputText, inputImage) + + override fun toString(): String = + when { + inputText != null -> "DecisionInputPart{inputText=$inputText}" + inputImage != null -> "DecisionInputPart{inputImage=$inputImage}" + _json != null -> "DecisionInputPart{_unknown=$_json}" + else -> throw IllegalStateException("Invalid DecisionInputPart") + } + + companion object { + + @JvmStatic + fun ofInputText(inputText: DecisionInputText) = DecisionInputPart(inputText = inputText) + + /** An inline image. External URLs and file IDs are not supported. */ + @JvmStatic + fun ofInputImage(inputImage: DecisionInputImage) = + DecisionInputPart(inputImage = inputImage) + } + + /** + * An interface that defines how to map each variant of [DecisionInputPart] to a value of type + * [T]. + */ + interface Visitor { + + fun visitInputText(inputText: DecisionInputText): T + + /** An inline image. External URLs and file IDs are not supported. */ + fun visitInputImage(inputImage: DecisionInputImage): T + + /** + * Maps an unknown variant of [DecisionInputPart] to a value of type [T]. + * + * An instance of [DecisionInputPart] can contain an unknown variant if it was deserialized + * from data that doesn't match any known variant. For example, if the SDK is on an older + * version than the API, then the API may respond with new variants that the SDK is unaware + * of. + * + * @throws OpenAIInvalidDataException in the default implementation. + */ + fun unknown(json: JsonValue?): T { + throw OpenAIInvalidDataException("Unknown DecisionInputPart") + } + } + + internal class Deserializer : BaseDeserializer(DecisionInputPart::class) { + + override fun ObjectCodec.deserialize(node: JsonNode): DecisionInputPart { + val json = JsonValue.fromJsonNode(node) + val type = json.asObject().getOrNull()?.get("type")?.asString()?.getOrNull() + + when (type) { + "input_text" -> { + return tryDeserialize(node, jacksonTypeRef())?.let { + DecisionInputPart(inputText = it, _json = json) + } ?: DecisionInputPart(_json = json) + } + "input_image" -> { + return tryDeserialize(node, jacksonTypeRef())?.let { + DecisionInputPart(inputImage = it, _json = json) + } ?: DecisionInputPart(_json = json) + } + } + + return DecisionInputPart(_json = json) + } + } + + internal class Serializer : BaseSerializer(DecisionInputPart::class) { + + override fun serialize( + value: DecisionInputPart, + generator: JsonGenerator, + provider: SerializerProvider, + ) { + when { + value.inputText != null -> generator.writeObject(value.inputText) + value.inputImage != null -> generator.writeObject(value.inputImage) + value._json != null -> generator.writeObject(value._json) + else -> throw IllegalStateException("Invalid DecisionInputPart") + } + } + } +} diff --git a/openai-java-core/src/main/kotlin/com/openai/models/decisions/DecisionInputText.kt b/openai-java-core/src/main/kotlin/com/openai/models/decisions/DecisionInputText.kt new file mode 100644 index 000000000..ee206f40e --- /dev/null +++ b/openai-java-core/src/main/kotlin/com/openai/models/decisions/DecisionInputText.kt @@ -0,0 +1,217 @@ +// File generated from our OpenAPI spec by Castiron. See CONTRIBUTING.md for details. + +package com.openai.models.decisions + +import com.fasterxml.jackson.annotation.JsonAnyGetter +import com.fasterxml.jackson.annotation.JsonAnySetter +import com.fasterxml.jackson.annotation.JsonCreator +import com.fasterxml.jackson.annotation.JsonProperty +import com.openai.core.ExcludeMissing +import com.openai.core.JsonField +import com.openai.core.JsonMissing +import com.openai.core.JsonValue +import com.openai.core.checkRequired +import com.openai.errors.OpenAIInvalidDataException +import java.util.Collections +import java.util.Objects + +class DecisionInputText +@JsonCreator(mode = JsonCreator.Mode.DISABLED) +private constructor( + private val text: JsonField, + private val type: JsonValue, + private val additionalProperties: MutableMap, +) { + + @JsonCreator + private constructor( + @JsonProperty("text") @ExcludeMissing text: JsonField = JsonMissing.of(), + @JsonProperty("type") @ExcludeMissing type: JsonValue = JsonMissing.of(), + ) : this(text, type, mutableMapOf()) + + /** + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun text(): String = text.getRequired("text") + + /** + * Expected to always return the following: + * ```java + * JsonValue.from("input_text") + * ``` + * + * However, this method can be useful for debugging and logging (e.g. if the server responded + * with an unexpected value). + */ + @JsonProperty("type") @ExcludeMissing fun _type(): JsonValue = type + + /** + * Returns the raw JSON value of [text]. + * + * Unlike [text], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("text") @ExcludeMissing fun _text(): JsonField = text + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [DecisionInputText]. + * + * The following fields are required: + * ```java + * .text() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [DecisionInputText]. */ + class Builder internal constructor() { + + private var text: JsonField? = null + private var type: JsonValue = JsonValue.from("input_text") + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(decisionInputText: DecisionInputText) = apply { + text = decisionInputText.text + type = decisionInputText.type + additionalProperties = decisionInputText.additionalProperties.toMutableMap() + } + + fun text(text: String) = text(JsonField.of(text)) + + /** + * Sets [Builder.text] to an arbitrary JSON value. + * + * You should usually call [Builder.text] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun text(text: JsonField) = apply { this.text = text } + + /** + * Sets the field to an arbitrary JSON value. + * + * It is usually unnecessary to call this method because the field defaults to the + * following: + * ```java + * JsonValue.from("input_text") + * ``` + * + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun type(type: JsonValue) = apply { this.type = type } + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { additionalProperties.remove(key) } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [DecisionInputText]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .text() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): DecisionInputText = + DecisionInputText( + checkRequired("text", text), + type, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws OpenAIInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): DecisionInputText = apply { + if (validated) { + return@apply + } + + text() + _type().let { + if (it != JsonValue.from("input_text")) { + throw OpenAIInvalidDataException("'type' is invalid, received $it") + } + } + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: OpenAIInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + (if (text.asKnown().isPresent) 1 else 0) + + type.let { if (it == JsonValue.from("input_text")) 1 else 0 } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is DecisionInputText && + text == other.text && + type == other.type && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(text, type, additionalProperties) } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "DecisionInputText{text=$text, type=$type, additionalProperties=$additionalProperties}" +} diff --git a/openai-java-core/src/main/kotlin/com/openai/models/live/ResponseItemCreateEvent.kt b/openai-java-core/src/main/kotlin/com/openai/models/live/ResponseItemCreateEvent.kt index fd2d1361a..d95933660 100644 --- a/openai-java-core/src/main/kotlin/com/openai/models/live/ResponseItemCreateEvent.kt +++ b/openai-java-core/src/main/kotlin/com/openai/models/live/ResponseItemCreateEvent.kt @@ -260,7 +260,7 @@ private constructor( * .build() * ``` */ - fun toolSearchOutputItem(tools: List) = + fun toolSearchOutputItem(tools: List) = item(ResponseToolSearchOutputItemParam.builder().tools(tools).build()) /** Alias for calling [item] with `ResponseInputItem.ofAdditionalTools(additionalTools)`. */ diff --git a/openai-java-core/src/main/kotlin/com/openai/models/responses/ResponseToolSearchOutputItemParam.kt b/openai-java-core/src/main/kotlin/com/openai/models/responses/ResponseToolSearchOutputItemParam.kt index f6d444909..89fbecd79 100644 --- a/openai-java-core/src/main/kotlin/com/openai/models/responses/ResponseToolSearchOutputItemParam.kt +++ b/openai-java-core/src/main/kotlin/com/openai/models/responses/ResponseToolSearchOutputItemParam.kt @@ -6,13 +6,24 @@ import com.fasterxml.jackson.annotation.JsonAnyGetter import com.fasterxml.jackson.annotation.JsonAnySetter import com.fasterxml.jackson.annotation.JsonCreator import com.fasterxml.jackson.annotation.JsonProperty +import com.fasterxml.jackson.core.JsonGenerator +import com.fasterxml.jackson.core.ObjectCodec +import com.fasterxml.jackson.databind.JsonNode +import com.fasterxml.jackson.databind.SerializerProvider +import com.fasterxml.jackson.databind.annotation.JsonDeserialize +import com.fasterxml.jackson.databind.annotation.JsonSerialize +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import com.openai.core.BaseDeserializer +import com.openai.core.BaseSerializer import com.openai.core.Enum import com.openai.core.ExcludeMissing import com.openai.core.JsonField import com.openai.core.JsonMissing import com.openai.core.JsonValue +import com.openai.core.allMaxBy import com.openai.core.checkKnown import com.openai.core.checkRequired +import com.openai.core.getOrThrow import com.openai.core.toImmutable import com.openai.errors.OpenAIInvalidDataException import java.util.Collections @@ -307,7 +318,7 @@ private constructor( fun addCustomTool(name: String) = addTool(CustomTool.builder().name(name).build()) /** Alias for calling [addTool] with `Tool.ofNamespace(namespace)`. */ - fun addTool(namespace: NamespaceTool) = addTool(Tool.ofNamespace(namespace)) + fun addTool(namespace: ToolSearchOutputNamespaceTool) = addTool(Tool.ofNamespace(namespace)) /** Alias for calling [addTool] with `Tool.ofSearch(search)`. */ fun addTool(search: ToolSearchTool) = addTool(Tool.ofSearch(search)) @@ -480,6 +491,7361 @@ private constructor( (execution.asKnown().getOrNull()?.validity() ?: 0) + (status.asKnown().getOrNull()?.validity() ?: 0) + /** A tool definition returned by a tool search output. */ + @JsonDeserialize(using = Tool.Deserializer::class) + @JsonSerialize(using = Tool.Serializer::class) + class Tool + private constructor( + private val function: FunctionTool? = null, + private val fileSearch: FileSearchTool? = null, + private val computer: ComputerTool? = null, + private val computerUsePreview: ComputerUsePreviewTool? = null, + private val webSearch: WebSearchTool? = null, + private val mcp: Mcp? = null, + private val codeInterpreter: CodeInterpreter? = null, + private val programmaticToolCalling: JsonValue? = null, + private val imageGeneration: ImageGeneration? = null, + private val localShell: JsonValue? = null, + private val shell: FunctionShellTool? = null, + private val custom: CustomTool? = null, + private val namespace: ToolSearchOutputNamespaceTool? = null, + private val search: ToolSearchTool? = null, + private val webSearchPreview: WebSearchPreviewTool? = null, + private val applyPatch: ApplyPatchTool? = null, + private val _json: JsonValue? = null, + ) { + + /** + * Defines a function in your own code the model can choose to call. Learn more about + * [function calling](https://developers.openai.com/api/docs/guides/function-calling). + */ + fun function(): Optional = Optional.ofNullable(function) + + /** + * A tool that searches for relevant content from uploaded files. Learn more about the + * [file search tool](https://developers.openai.com/api/docs/guides/tools-file-search). + */ + fun fileSearch(): Optional = Optional.ofNullable(fileSearch) + + /** + * A tool that controls a virtual computer. Learn more about the + * [computer tool](https://developers.openai.com/api/docs/guides/tools-computer-use). + */ + fun computer(): Optional = Optional.ofNullable(computer) + + /** + * A tool that controls a virtual computer. Learn more about the + * [computer tool](https://developers.openai.com/api/docs/guides/tools-computer-use). + */ + fun computerUsePreview(): Optional = + Optional.ofNullable(computerUsePreview) + + /** + * Search the Internet for sources related to the prompt. Learn more about the + * [web search tool](https://developers.openai.com/api/docs/guides/tools-web-search). + */ + fun webSearch(): Optional = Optional.ofNullable(webSearch) + + /** + * Give the model access to additional tools via remote Model Context Protocol (MCP) + * servers. + * [Learn more about MCP](https://developers.openai.com/api/docs/guides/tools-connectors-mcp). + */ + fun mcp(): Optional = Optional.ofNullable(mcp) + + /** A tool that runs Python code to help generate a response to a prompt. */ + fun codeInterpreter(): Optional = Optional.ofNullable(codeInterpreter) + + fun programmaticToolCalling(): Optional = + Optional.ofNullable(programmaticToolCalling) + + /** A tool that generates images using the GPT image models. */ + fun imageGeneration(): Optional = Optional.ofNullable(imageGeneration) + + /** A tool that allows the model to execute shell commands in a local environment. */ + fun localShell(): Optional = Optional.ofNullable(localShell) + + /** A tool that allows the model to execute shell commands. */ + fun shell(): Optional = Optional.ofNullable(shell) + + /** + * A custom tool that processes input using a specified format. Learn more about + * [custom tools](https://developers.openai.com/api/docs/guides/function-calling#custom-tools) + */ + fun custom(): Optional = Optional.ofNullable(custom) + + /** Groups function/custom tools under a shared namespace. */ + fun namespace(): Optional = Optional.ofNullable(namespace) + + /** Hosted or BYOT tool search configuration for deferred tools. */ + fun search(): Optional = Optional.ofNullable(search) + + /** + * This tool searches the web for relevant results to use in a response. Learn more about + * the [web search tool](https://developers.openai.com/api/docs/guides/tools-web-search). + */ + fun webSearchPreview(): Optional = + Optional.ofNullable(webSearchPreview) + + /** Allows the assistant to create, delete, or update files using unified diffs. */ + fun applyPatch(): Optional = Optional.ofNullable(applyPatch) + + fun isFunction(): Boolean = function != null + + fun isFileSearch(): Boolean = fileSearch != null + + fun isComputer(): Boolean = computer != null + + fun isComputerUsePreview(): Boolean = computerUsePreview != null + + fun isWebSearch(): Boolean = webSearch != null + + fun isMcp(): Boolean = mcp != null + + fun isCodeInterpreter(): Boolean = codeInterpreter != null + + fun isProgrammaticToolCalling(): Boolean = programmaticToolCalling != null + + fun isImageGeneration(): Boolean = imageGeneration != null + + fun isLocalShell(): Boolean = localShell != null + + fun isShell(): Boolean = shell != null + + fun isCustom(): Boolean = custom != null + + fun isNamespace(): Boolean = namespace != null + + fun isSearch(): Boolean = search != null + + fun isWebSearchPreview(): Boolean = webSearchPreview != null + + fun isApplyPatch(): Boolean = applyPatch != null + + /** + * Defines a function in your own code the model can choose to call. Learn more about + * [function calling](https://developers.openai.com/api/docs/guides/function-calling). + */ + fun asFunction(): FunctionTool = function.getOrThrow("function") + + /** + * A tool that searches for relevant content from uploaded files. Learn more about the + * [file search tool](https://developers.openai.com/api/docs/guides/tools-file-search). + */ + fun asFileSearch(): FileSearchTool = fileSearch.getOrThrow("fileSearch") + + /** + * A tool that controls a virtual computer. Learn more about the + * [computer tool](https://developers.openai.com/api/docs/guides/tools-computer-use). + */ + fun asComputer(): ComputerTool = computer.getOrThrow("computer") + + /** + * A tool that controls a virtual computer. Learn more about the + * [computer tool](https://developers.openai.com/api/docs/guides/tools-computer-use). + */ + fun asComputerUsePreview(): ComputerUsePreviewTool = + computerUsePreview.getOrThrow("computerUsePreview") + + /** + * Search the Internet for sources related to the prompt. Learn more about the + * [web search tool](https://developers.openai.com/api/docs/guides/tools-web-search). + */ + fun asWebSearch(): WebSearchTool = webSearch.getOrThrow("webSearch") + + /** + * Give the model access to additional tools via remote Model Context Protocol (MCP) + * servers. + * [Learn more about MCP](https://developers.openai.com/api/docs/guides/tools-connectors-mcp). + */ + fun asMcp(): Mcp = mcp.getOrThrow("mcp") + + /** A tool that runs Python code to help generate a response to a prompt. */ + fun asCodeInterpreter(): CodeInterpreter = codeInterpreter.getOrThrow("codeInterpreter") + + fun asProgrammaticToolCalling(): JsonValue = + programmaticToolCalling.getOrThrow("programmaticToolCalling") + + /** A tool that generates images using the GPT image models. */ + fun asImageGeneration(): ImageGeneration = imageGeneration.getOrThrow("imageGeneration") + + /** A tool that allows the model to execute shell commands in a local environment. */ + fun asLocalShell(): JsonValue = localShell.getOrThrow("localShell") + + /** A tool that allows the model to execute shell commands. */ + fun asShell(): FunctionShellTool = shell.getOrThrow("shell") + + /** + * A custom tool that processes input using a specified format. Learn more about + * [custom tools](https://developers.openai.com/api/docs/guides/function-calling#custom-tools) + */ + fun asCustom(): CustomTool = custom.getOrThrow("custom") + + /** Groups function/custom tools under a shared namespace. */ + fun asNamespace(): ToolSearchOutputNamespaceTool = namespace.getOrThrow("namespace") + + /** Hosted or BYOT tool search configuration for deferred tools. */ + fun asSearch(): ToolSearchTool = search.getOrThrow("search") + + /** + * This tool searches the web for relevant results to use in a response. Learn more about + * the [web search tool](https://developers.openai.com/api/docs/guides/tools-web-search). + */ + fun asWebSearchPreview(): WebSearchPreviewTool = + webSearchPreview.getOrThrow("webSearchPreview") + + /** Allows the assistant to create, delete, or update files using unified diffs. */ + fun asApplyPatch(): ApplyPatchTool = applyPatch.getOrThrow("applyPatch") + + fun _json(): Optional = Optional.ofNullable(_json) + + /** + * Maps this instance's current variant to a value of type [T] using the given [visitor]. + * + * Note that this method is _not_ forwards compatible with new variants from the API, unless + * [visitor] overrides [Visitor.unknown]. To handle variants not known to this version of + * the SDK gracefully, consider overriding [Visitor.unknown]: + * ```java + * import com.openai.core.JsonValue; + * import java.util.Optional; + * + * Optional result = tool.accept(new Tool.Visitor>() { + * @Override + * public Optional visitFunction(FunctionTool function) { + * return Optional.of(function.toString()); + * } + * + * // ... + * + * @Override + * public Optional unknown(JsonValue json) { + * // Or inspect the `json`. + * return Optional.empty(); + * } + * }); + * ``` + * + * @throws OpenAIInvalidDataException if [Visitor.unknown] is not overridden in [visitor] + * and the current variant is unknown. + */ + fun accept(visitor: Visitor): T = + when { + function != null -> visitor.visitFunction(function) + fileSearch != null -> visitor.visitFileSearch(fileSearch) + computer != null -> visitor.visitComputer(computer) + computerUsePreview != null -> visitor.visitComputerUsePreview(computerUsePreview) + webSearch != null -> visitor.visitWebSearch(webSearch) + mcp != null -> visitor.visitMcp(mcp) + codeInterpreter != null -> visitor.visitCodeInterpreter(codeInterpreter) + programmaticToolCalling != null -> + visitor.visitProgrammaticToolCalling(programmaticToolCalling) + imageGeneration != null -> visitor.visitImageGeneration(imageGeneration) + localShell != null -> visitor.visitLocalShell(localShell) + shell != null -> visitor.visitShell(shell) + custom != null -> visitor.visitCustom(custom) + namespace != null -> visitor.visitNamespace(namespace) + search != null -> visitor.visitSearch(search) + webSearchPreview != null -> visitor.visitWebSearchPreview(webSearchPreview) + applyPatch != null -> visitor.visitApplyPatch(applyPatch) + else -> visitor.unknown(_json) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws OpenAIInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): Tool = apply { + if (validated) { + return@apply + } + + accept( + object : Visitor { + override fun visitFunction(function: FunctionTool) { + function.validate() + } + + override fun visitFileSearch(fileSearch: FileSearchTool) { + fileSearch.validate() + } + + override fun visitComputer(computer: ComputerTool) { + computer.validate() + } + + override fun visitComputerUsePreview( + computerUsePreview: ComputerUsePreviewTool + ) { + computerUsePreview.validate() + } + + override fun visitWebSearch(webSearch: WebSearchTool) { + webSearch.validate() + } + + override fun visitMcp(mcp: Mcp) { + mcp.validate() + } + + override fun visitCodeInterpreter(codeInterpreter: CodeInterpreter) { + codeInterpreter.validate() + } + + override fun visitProgrammaticToolCalling(programmaticToolCalling: JsonValue) { + programmaticToolCalling.let { + if ( + it != JsonValue.from(mapOf("type" to "programmatic_tool_calling")) + ) { + throw OpenAIInvalidDataException( + "'programmaticToolCalling' is invalid, received $it" + ) + } + } + } + + override fun visitImageGeneration(imageGeneration: ImageGeneration) { + imageGeneration.validate() + } + + override fun visitLocalShell(localShell: JsonValue) { + localShell.let { + if (it != JsonValue.from(mapOf("type" to "local_shell"))) { + throw OpenAIInvalidDataException( + "'localShell' is invalid, received $it" + ) + } + } + } + + override fun visitShell(shell: FunctionShellTool) { + shell.validate() + } + + override fun visitCustom(custom: CustomTool) { + custom.validate() + } + + override fun visitNamespace(namespace: ToolSearchOutputNamespaceTool) { + namespace.validate() + } + + override fun visitSearch(search: ToolSearchTool) { + search.validate() + } + + override fun visitWebSearchPreview(webSearchPreview: WebSearchPreviewTool) { + webSearchPreview.validate() + } + + override fun visitApplyPatch(applyPatch: ApplyPatchTool) { + applyPatch.validate() + } + } + ) + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: OpenAIInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + accept( + object : Visitor { + override fun visitFunction(function: FunctionTool) = function.validity() + + override fun visitFileSearch(fileSearch: FileSearchTool) = fileSearch.validity() + + override fun visitComputer(computer: ComputerTool) = computer.validity() + + override fun visitComputerUsePreview( + computerUsePreview: ComputerUsePreviewTool + ) = computerUsePreview.validity() + + override fun visitWebSearch(webSearch: WebSearchTool) = webSearch.validity() + + override fun visitMcp(mcp: Mcp) = mcp.validity() + + override fun visitCodeInterpreter(codeInterpreter: CodeInterpreter) = + codeInterpreter.validity() + + override fun visitProgrammaticToolCalling(programmaticToolCalling: JsonValue) = + programmaticToolCalling.let { + if (it == JsonValue.from(mapOf("type" to "programmatic_tool_calling"))) + 1 + else 0 + } + + override fun visitImageGeneration(imageGeneration: ImageGeneration) = + imageGeneration.validity() + + override fun visitLocalShell(localShell: JsonValue) = + localShell.let { + if (it == JsonValue.from(mapOf("type" to "local_shell"))) 1 else 0 + } + + override fun visitShell(shell: FunctionShellTool) = shell.validity() + + override fun visitCustom(custom: CustomTool) = custom.validity() + + override fun visitNamespace(namespace: ToolSearchOutputNamespaceTool) = + namespace.validity() + + override fun visitSearch(search: ToolSearchTool) = search.validity() + + override fun visitWebSearchPreview(webSearchPreview: WebSearchPreviewTool) = + webSearchPreview.validity() + + override fun visitApplyPatch(applyPatch: ApplyPatchTool) = applyPatch.validity() + + override fun unknown(json: JsonValue?) = 0 + } + ) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Tool && + function == other.function && + fileSearch == other.fileSearch && + computer == other.computer && + computerUsePreview == other.computerUsePreview && + webSearch == other.webSearch && + mcp == other.mcp && + codeInterpreter == other.codeInterpreter && + programmaticToolCalling == other.programmaticToolCalling && + imageGeneration == other.imageGeneration && + localShell == other.localShell && + shell == other.shell && + custom == other.custom && + namespace == other.namespace && + search == other.search && + webSearchPreview == other.webSearchPreview && + applyPatch == other.applyPatch + } + + override fun hashCode(): Int = + Objects.hash( + function, + fileSearch, + computer, + computerUsePreview, + webSearch, + mcp, + codeInterpreter, + programmaticToolCalling, + imageGeneration, + localShell, + shell, + custom, + namespace, + search, + webSearchPreview, + applyPatch, + ) + + override fun toString(): String = + when { + function != null -> "Tool{function=$function}" + fileSearch != null -> "Tool{fileSearch=$fileSearch}" + computer != null -> "Tool{computer=$computer}" + computerUsePreview != null -> "Tool{computerUsePreview=$computerUsePreview}" + webSearch != null -> "Tool{webSearch=$webSearch}" + mcp != null -> "Tool{mcp=$mcp}" + codeInterpreter != null -> "Tool{codeInterpreter=$codeInterpreter}" + programmaticToolCalling != null -> + "Tool{programmaticToolCalling=$programmaticToolCalling}" + imageGeneration != null -> "Tool{imageGeneration=$imageGeneration}" + localShell != null -> "Tool{localShell=$localShell}" + shell != null -> "Tool{shell=$shell}" + custom != null -> "Tool{custom=$custom}" + namespace != null -> "Tool{namespace=$namespace}" + search != null -> "Tool{search=$search}" + webSearchPreview != null -> "Tool{webSearchPreview=$webSearchPreview}" + applyPatch != null -> "Tool{applyPatch=$applyPatch}" + _json != null -> "Tool{_unknown=$_json}" + else -> throw IllegalStateException("Invalid Tool") + } + + companion object { + + /** + * Defines a function in your own code the model can choose to call. Learn more about + * [function calling](https://developers.openai.com/api/docs/guides/function-calling). + */ + @JvmStatic fun ofFunction(function: FunctionTool) = Tool(function = function) + + /** + * A tool that searches for relevant content from uploaded files. Learn more about the + * [file search tool](https://developers.openai.com/api/docs/guides/tools-file-search). + */ + @JvmStatic fun ofFileSearch(fileSearch: FileSearchTool) = Tool(fileSearch = fileSearch) + + /** + * A tool that controls a virtual computer. Learn more about the + * [computer tool](https://developers.openai.com/api/docs/guides/tools-computer-use). + */ + @JvmStatic fun ofComputer(computer: ComputerTool) = Tool(computer = computer) + + /** + * A tool that controls a virtual computer. Learn more about the + * [computer tool](https://developers.openai.com/api/docs/guides/tools-computer-use). + */ + @JvmStatic + fun ofComputerUsePreview(computerUsePreview: ComputerUsePreviewTool) = + Tool(computerUsePreview = computerUsePreview) + + /** + * Search the Internet for sources related to the prompt. Learn more about the + * [web search tool](https://developers.openai.com/api/docs/guides/tools-web-search). + */ + @JvmStatic fun ofWebSearch(webSearch: WebSearchTool) = Tool(webSearch = webSearch) + + /** + * Give the model access to additional tools via remote Model Context Protocol (MCP) + * servers. + * [Learn more about MCP](https://developers.openai.com/api/docs/guides/tools-connectors-mcp). + */ + @JvmStatic fun ofMcp(mcp: Mcp) = Tool(mcp = mcp) + + /** A tool that runs Python code to help generate a response to a prompt. */ + @JvmStatic + fun ofCodeInterpreter(codeInterpreter: CodeInterpreter) = + Tool(codeInterpreter = codeInterpreter) + + @JvmStatic + fun ofProgrammaticToolCalling() = + Tool( + programmaticToolCalling = + JsonValue.from(mapOf("type" to "programmatic_tool_calling")) + ) + + /** A tool that generates images using the GPT image models. */ + @JvmStatic + fun ofImageGeneration(imageGeneration: ImageGeneration) = + Tool(imageGeneration = imageGeneration) + + /** A tool that allows the model to execute shell commands in a local environment. */ + @JvmStatic + fun ofLocalShell() = Tool(localShell = JsonValue.from(mapOf("type" to "local_shell"))) + + /** A tool that allows the model to execute shell commands. */ + @JvmStatic fun ofShell(shell: FunctionShellTool) = Tool(shell = shell) + + /** + * A custom tool that processes input using a specified format. Learn more about + * [custom tools](https://developers.openai.com/api/docs/guides/function-calling#custom-tools) + */ + @JvmStatic fun ofCustom(custom: CustomTool) = Tool(custom = custom) + + /** Groups function/custom tools under a shared namespace. */ + @JvmStatic + fun ofNamespace(namespace: ToolSearchOutputNamespaceTool) = Tool(namespace = namespace) + + /** Hosted or BYOT tool search configuration for deferred tools. */ + @JvmStatic fun ofSearch(search: ToolSearchTool) = Tool(search = search) + + /** + * This tool searches the web for relevant results to use in a response. Learn more + * about the + * [web search tool](https://developers.openai.com/api/docs/guides/tools-web-search). + */ + @JvmStatic + fun ofWebSearchPreview(webSearchPreview: WebSearchPreviewTool) = + Tool(webSearchPreview = webSearchPreview) + + /** Allows the assistant to create, delete, or update files using unified diffs. */ + @JvmStatic fun ofApplyPatch(applyPatch: ApplyPatchTool) = Tool(applyPatch = applyPatch) + } + + /** An interface that defines how to map each variant of [Tool] to a value of type [T]. */ + interface Visitor { + + /** + * Defines a function in your own code the model can choose to call. Learn more about + * [function calling](https://developers.openai.com/api/docs/guides/function-calling). + */ + fun visitFunction(function: FunctionTool): T + + /** + * A tool that searches for relevant content from uploaded files. Learn more about the + * [file search tool](https://developers.openai.com/api/docs/guides/tools-file-search). + */ + fun visitFileSearch(fileSearch: FileSearchTool): T + + /** + * A tool that controls a virtual computer. Learn more about the + * [computer tool](https://developers.openai.com/api/docs/guides/tools-computer-use). + */ + fun visitComputer(computer: ComputerTool): T + + /** + * A tool that controls a virtual computer. Learn more about the + * [computer tool](https://developers.openai.com/api/docs/guides/tools-computer-use). + */ + fun visitComputerUsePreview(computerUsePreview: ComputerUsePreviewTool): T + + /** + * Search the Internet for sources related to the prompt. Learn more about the + * [web search tool](https://developers.openai.com/api/docs/guides/tools-web-search). + */ + fun visitWebSearch(webSearch: WebSearchTool): T + + /** + * Give the model access to additional tools via remote Model Context Protocol (MCP) + * servers. + * [Learn more about MCP](https://developers.openai.com/api/docs/guides/tools-connectors-mcp). + */ + fun visitMcp(mcp: Mcp): T + + /** A tool that runs Python code to help generate a response to a prompt. */ + fun visitCodeInterpreter(codeInterpreter: CodeInterpreter): T + + fun visitProgrammaticToolCalling(programmaticToolCalling: JsonValue): T + + /** A tool that generates images using the GPT image models. */ + fun visitImageGeneration(imageGeneration: ImageGeneration): T + + /** A tool that allows the model to execute shell commands in a local environment. */ + fun visitLocalShell(localShell: JsonValue): T + + /** A tool that allows the model to execute shell commands. */ + fun visitShell(shell: FunctionShellTool): T + + /** + * A custom tool that processes input using a specified format. Learn more about + * [custom tools](https://developers.openai.com/api/docs/guides/function-calling#custom-tools) + */ + fun visitCustom(custom: CustomTool): T + + /** Groups function/custom tools under a shared namespace. */ + fun visitNamespace(namespace: ToolSearchOutputNamespaceTool): T + + /** Hosted or BYOT tool search configuration for deferred tools. */ + fun visitSearch(search: ToolSearchTool): T + + /** + * This tool searches the web for relevant results to use in a response. Learn more + * about the + * [web search tool](https://developers.openai.com/api/docs/guides/tools-web-search). + */ + fun visitWebSearchPreview(webSearchPreview: WebSearchPreviewTool): T + + /** Allows the assistant to create, delete, or update files using unified diffs. */ + fun visitApplyPatch(applyPatch: ApplyPatchTool): T + + /** + * Maps an unknown variant of [Tool] to a value of type [T]. + * + * An instance of [Tool] can contain an unknown variant if it was deserialized from data + * that doesn't match any known variant. For example, if the SDK is on an older version + * than the API, then the API may respond with new variants that the SDK is unaware of. + * + * @throws OpenAIInvalidDataException in the default implementation. + */ + fun unknown(json: JsonValue?): T { + throw OpenAIInvalidDataException("Unknown Tool") + } + } + + internal class Deserializer : BaseDeserializer(Tool::class) { + + override fun ObjectCodec.deserialize(node: JsonNode): Tool { + val json = JsonValue.fromJsonNode(node) + val type = json.asObject().getOrNull()?.get("type")?.asString()?.getOrNull() + + when (type) { + "function" -> { + return tryDeserialize(node, jacksonTypeRef())?.let { + Tool(function = it, _json = json) + } ?: Tool(_json = json) + } + "file_search" -> { + return tryDeserialize(node, jacksonTypeRef())?.let { + Tool(fileSearch = it, _json = json) + } ?: Tool(_json = json) + } + "computer" -> { + return tryDeserialize(node, jacksonTypeRef())?.let { + Tool(computer = it, _json = json) + } ?: Tool(_json = json) + } + "computer_use_preview" -> { + return tryDeserialize(node, jacksonTypeRef())?.let { + Tool(computerUsePreview = it, _json = json) + } ?: Tool(_json = json) + } + "mcp" -> { + return tryDeserialize(node, jacksonTypeRef())?.let { + Tool(mcp = it, _json = json) + } ?: Tool(_json = json) + } + "code_interpreter" -> { + return tryDeserialize(node, jacksonTypeRef())?.let { + Tool(codeInterpreter = it, _json = json) + } ?: Tool(_json = json) + } + "programmatic_tool_calling" -> { + return tryDeserialize(node, jacksonTypeRef()) + ?.let { Tool(programmaticToolCalling = it, _json = json) } + ?.takeIf { it.isValid() } ?: Tool(_json = json) + } + "image_generation" -> { + return tryDeserialize(node, jacksonTypeRef())?.let { + Tool(imageGeneration = it, _json = json) + } ?: Tool(_json = json) + } + "local_shell" -> { + return tryDeserialize(node, jacksonTypeRef()) + ?.let { Tool(localShell = it, _json = json) } + ?.takeIf { it.isValid() } ?: Tool(_json = json) + } + "shell" -> { + return tryDeserialize(node, jacksonTypeRef())?.let { + Tool(shell = it, _json = json) + } ?: Tool(_json = json) + } + "custom" -> { + return tryDeserialize(node, jacksonTypeRef())?.let { + Tool(custom = it, _json = json) + } ?: Tool(_json = json) + } + "namespace" -> { + return tryDeserialize(node, jacksonTypeRef()) + ?.let { Tool(namespace = it, _json = json) } ?: Tool(_json = json) + } + "tool_search" -> { + return tryDeserialize(node, jacksonTypeRef())?.let { + Tool(search = it, _json = json) + } ?: Tool(_json = json) + } + "apply_patch" -> { + return tryDeserialize(node, jacksonTypeRef())?.let { + Tool(applyPatch = it, _json = json) + } ?: Tool(_json = json) + } + } + + val bestMatches = + sequenceOf( + tryDeserialize(node, jacksonTypeRef())?.let { + Tool(webSearch = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef())?.let { + Tool(webSearchPreview = it, _json = json) + }, + ) + .filterNotNull() + .allMaxBy { it.validity() } + .toList() + return when (bestMatches.size) { + // This can happen if what we're deserializing is completely incompatible with + // all the possible variants (e.g. deserializing from boolean). + 0 -> Tool(_json = json) + 1 -> bestMatches.single() + // If there's more than one match with the highest validity, then use the first + // completely valid match, or simply the first match if none are completely + // valid. + else -> bestMatches.firstOrNull { it.isValid() } ?: bestMatches.first() + } + } + } + + internal class Serializer : BaseSerializer(Tool::class) { + + override fun serialize( + value: Tool, + generator: JsonGenerator, + provider: SerializerProvider, + ) { + when { + value.function != null -> generator.writeObject(value.function) + value.fileSearch != null -> generator.writeObject(value.fileSearch) + value.computer != null -> generator.writeObject(value.computer) + value.computerUsePreview != null -> + generator.writeObject(value.computerUsePreview) + value.webSearch != null -> generator.writeObject(value.webSearch) + value.mcp != null -> generator.writeObject(value.mcp) + value.codeInterpreter != null -> generator.writeObject(value.codeInterpreter) + value.programmaticToolCalling != null -> + generator.writeObject(value.programmaticToolCalling) + value.imageGeneration != null -> generator.writeObject(value.imageGeneration) + value.localShell != null -> generator.writeObject(value.localShell) + value.shell != null -> generator.writeObject(value.shell) + value.custom != null -> generator.writeObject(value.custom) + value.namespace != null -> generator.writeObject(value.namespace) + value.search != null -> generator.writeObject(value.search) + value.webSearchPreview != null -> generator.writeObject(value.webSearchPreview) + value.applyPatch != null -> generator.writeObject(value.applyPatch) + value._json != null -> generator.writeObject(value._json) + else -> throw IllegalStateException("Invalid Tool") + } + } + } + + /** + * Give the model access to additional tools via remote Model Context Protocol (MCP) + * servers. + * [Learn more about MCP](https://developers.openai.com/api/docs/guides/tools-connectors-mcp). + */ + class Mcp + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val serverLabel: JsonField, + private val type: JsonValue, + private val allowedCallers: JsonField>, + private val allowedTools: JsonField, + private val authorization: JsonField, + private val connectorId: JsonField, + private val deferLoading: JsonField, + private val headers: JsonField, + private val requireApproval: JsonField, + private val serverDescription: JsonField, + private val serverUrl: JsonField, + private val tunnelId: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("server_label") + @ExcludeMissing + serverLabel: JsonField = JsonMissing.of(), + @JsonProperty("type") @ExcludeMissing type: JsonValue = JsonMissing.of(), + @JsonProperty("allowed_callers") + @ExcludeMissing + allowedCallers: JsonField> = JsonMissing.of(), + @JsonProperty("allowed_tools") + @ExcludeMissing + allowedTools: JsonField = JsonMissing.of(), + @JsonProperty("authorization") + @ExcludeMissing + authorization: JsonField = JsonMissing.of(), + @JsonProperty("connector_id") + @ExcludeMissing + connectorId: JsonField = JsonMissing.of(), + @JsonProperty("defer_loading") + @ExcludeMissing + deferLoading: JsonField = JsonMissing.of(), + @JsonProperty("headers") + @ExcludeMissing + headers: JsonField = JsonMissing.of(), + @JsonProperty("require_approval") + @ExcludeMissing + requireApproval: JsonField = JsonMissing.of(), + @JsonProperty("server_description") + @ExcludeMissing + serverDescription: JsonField = JsonMissing.of(), + @JsonProperty("server_url") + @ExcludeMissing + serverUrl: JsonField = JsonMissing.of(), + @JsonProperty("tunnel_id") + @ExcludeMissing + tunnelId: JsonField = JsonMissing.of(), + ) : this( + serverLabel, + type, + allowedCallers, + allowedTools, + authorization, + connectorId, + deferLoading, + headers, + requireApproval, + serverDescription, + serverUrl, + tunnelId, + mutableMapOf(), + ) + + /** + * A label for this MCP server, used to identify it in tool calls. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected + * value). + */ + fun serverLabel(): String = serverLabel.getRequired("server_label") + + /** + * The type of the MCP tool. Always `mcp`. + * + * Expected to always return the following: + * ```java + * JsonValue.from("mcp") + * ``` + * + * However, this method can be useful for debugging and logging (e.g. if the server + * responded with an unexpected value). + */ + @JsonProperty("type") @ExcludeMissing fun _type(): JsonValue = type + + /** + * The tool invocation context(s). + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun allowedCallers(): Optional> = + allowedCallers.getOptional("allowed_callers") + + /** + * List of allowed tool names or a filter object. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun allowedTools(): Optional = allowedTools.getOptional("allowed_tools") + + /** + * An OAuth access token that can be used with a remote MCP server, either with a custom + * MCP server URL or a service connector. Your application must handle the OAuth + * authorization flow and provide the token here. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun authorization(): Optional = authorization.getOptional("authorization") + + /** + * Identifier for service connectors, like those available in ChatGPT. One of + * `server_url`, `connector_id`, or `tunnel_id` must be provided. Learn more about + * service connectors + * [here](https://developers.openai.com/api/docs/guides/tools-connectors-mcp#connectors). + * + * This field is deprecated for models released after September 1, 2026. Use + * `server_url` to connect to a remote MCP server, or `tunnel_id` to connect through a + * Secure MCP Tunnel. + * + * Currently supported `connector_id` values are: + * - Dropbox: `connector_dropbox` + * - Gmail: `connector_gmail` + * - Google Calendar: `connector_googlecalendar` + * - Google Drive: `connector_googledrive` + * - Microsoft Teams: `connector_microsoftteams` + * - Outlook Calendar: `connector_outlookcalendar` + * - Outlook Email: `connector_outlookemail` + * - SharePoint: `connector_sharepoint` + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + @Deprecated("deprecated") + fun connectorId(): Optional = connectorId.getOptional("connector_id") + + /** + * Whether this MCP tool is deferred and discovered via tool search. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun deferLoading(): Optional = deferLoading.getOptional("defer_loading") + + /** + * Optional HTTP headers to send to the MCP server. Use for authentication or other + * purposes. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun headers(): Optional = headers.getOptional("headers") + + /** + * Specify which of the MCP server's tools require approval. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun requireApproval(): Optional = + requireApproval.getOptional("require_approval") + + /** + * Optional description of the MCP server, used to provide more context. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun serverDescription(): Optional = + serverDescription.getOptional("server_description") + + /** + * The URL for the MCP server. One of `server_url`, `connector_id`, or `tunnel_id` must + * be provided. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun serverUrl(): Optional = serverUrl.getOptional("server_url") + + /** + * The Secure MCP Tunnel ID to use instead of a direct server URL. One of `server_url`, + * `connector_id`, or `tunnel_id` must be provided. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun tunnelId(): Optional = tunnelId.getOptional("tunnel_id") + + /** + * Returns the raw JSON value of [serverLabel]. + * + * Unlike [serverLabel], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("server_label") + @ExcludeMissing + fun _serverLabel(): JsonField = serverLabel + + /** + * Returns the raw JSON value of [allowedCallers]. + * + * Unlike [allowedCallers], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("allowed_callers") + @ExcludeMissing + fun _allowedCallers(): JsonField> = allowedCallers + + /** + * Returns the raw JSON value of [allowedTools]. + * + * Unlike [allowedTools], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("allowed_tools") + @ExcludeMissing + fun _allowedTools(): JsonField = allowedTools + + /** + * Returns the raw JSON value of [authorization]. + * + * Unlike [authorization], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("authorization") + @ExcludeMissing + fun _authorization(): JsonField = authorization + + /** + * Returns the raw JSON value of [connectorId]. + * + * Unlike [connectorId], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @Deprecated("deprecated") + @JsonProperty("connector_id") + @ExcludeMissing + fun _connectorId(): JsonField = connectorId + + /** + * Returns the raw JSON value of [deferLoading]. + * + * Unlike [deferLoading], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("defer_loading") + @ExcludeMissing + fun _deferLoading(): JsonField = deferLoading + + /** + * Returns the raw JSON value of [headers]. + * + * Unlike [headers], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("headers") @ExcludeMissing fun _headers(): JsonField = headers + + /** + * Returns the raw JSON value of [requireApproval]. + * + * Unlike [requireApproval], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("require_approval") + @ExcludeMissing + fun _requireApproval(): JsonField = requireApproval + + /** + * Returns the raw JSON value of [serverDescription]. + * + * Unlike [serverDescription], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("server_description") + @ExcludeMissing + fun _serverDescription(): JsonField = serverDescription + + /** + * Returns the raw JSON value of [serverUrl]. + * + * Unlike [serverUrl], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("server_url") + @ExcludeMissing + fun _serverUrl(): JsonField = serverUrl + + /** + * Returns the raw JSON value of [tunnelId]. + * + * Unlike [tunnelId], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("tunnel_id") @ExcludeMissing fun _tunnelId(): JsonField = tunnelId + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [Mcp]. + * + * The following fields are required: + * ```java + * .serverLabel() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Mcp]. */ + class Builder internal constructor() { + + private var serverLabel: JsonField? = null + private var type: JsonValue = JsonValue.from("mcp") + private var allowedCallers: JsonField>? = null + private var allowedTools: JsonField = JsonMissing.of() + private var authorization: JsonField = JsonMissing.of() + private var connectorId: JsonField = JsonMissing.of() + private var deferLoading: JsonField = JsonMissing.of() + private var headers: JsonField = JsonMissing.of() + private var requireApproval: JsonField = JsonMissing.of() + private var serverDescription: JsonField = JsonMissing.of() + private var serverUrl: JsonField = JsonMissing.of() + private var tunnelId: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(mcp: Mcp) = apply { + serverLabel = mcp.serverLabel + type = mcp.type + allowedCallers = mcp.allowedCallers.map { it.toMutableList() } + allowedTools = mcp.allowedTools + authorization = mcp.authorization + connectorId = mcp.connectorId + deferLoading = mcp.deferLoading + headers = mcp.headers + requireApproval = mcp.requireApproval + serverDescription = mcp.serverDescription + serverUrl = mcp.serverUrl + tunnelId = mcp.tunnelId + additionalProperties = mcp.additionalProperties.toMutableMap() + } + + /** A label for this MCP server, used to identify it in tool calls. */ + fun serverLabel(serverLabel: String) = serverLabel(JsonField.of(serverLabel)) + + /** + * Sets [Builder.serverLabel] to an arbitrary JSON value. + * + * You should usually call [Builder.serverLabel] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun serverLabel(serverLabel: JsonField) = apply { + this.serverLabel = serverLabel + } + + /** + * Sets the field to an arbitrary JSON value. + * + * It is usually unnecessary to call this method because the field defaults to the + * following: + * ```java + * JsonValue.from("mcp") + * ``` + * + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun type(type: JsonValue) = apply { this.type = type } + + /** The tool invocation context(s). */ + fun allowedCallers(allowedCallers: List?) = + allowedCallers(JsonField.ofNullable(allowedCallers)) + + /** + * Alias for calling [Builder.allowedCallers] with `allowedCallers.orElse(null)`. + */ + fun allowedCallers(allowedCallers: Optional>) = + allowedCallers(allowedCallers.getOrNull()) + + /** + * Sets [Builder.allowedCallers] to an arbitrary JSON value. + * + * You should usually call [Builder.allowedCallers] with a well-typed + * `List` value instead. This method is primarily for setting the + * field to an undocumented or not yet supported value. + */ + fun allowedCallers(allowedCallers: JsonField>) = apply { + this.allowedCallers = allowedCallers.map { it.toMutableList() } + } + + /** + * Adds a single [AllowedCaller] to [allowedCallers]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addAllowedCaller(allowedCaller: AllowedCaller) = apply { + allowedCallers = + (allowedCallers ?: JsonField.of(mutableListOf())).also { + checkKnown("allowedCallers", it).add(allowedCaller) + } + } + + /** List of allowed tool names or a filter object. */ + fun allowedTools(allowedTools: AllowedTools?) = + allowedTools(JsonField.ofNullable(allowedTools)) + + /** Alias for calling [Builder.allowedTools] with `allowedTools.orElse(null)`. */ + fun allowedTools(allowedTools: Optional) = + allowedTools(allowedTools.getOrNull()) + + /** + * Sets [Builder.allowedTools] to an arbitrary JSON value. + * + * You should usually call [Builder.allowedTools] with a well-typed [AllowedTools] + * value instead. This method is primarily for setting the field to an undocumented + * or not yet supported value. + */ + fun allowedTools(allowedTools: JsonField) = apply { + this.allowedTools = allowedTools + } + + /** Alias for calling [allowedTools] with `AllowedTools.ofMcp(mcp)`. */ + fun allowedToolsOfMcp(mcp: List) = allowedTools(AllowedTools.ofMcp(mcp)) + + /** + * Alias for calling [allowedTools] with + * `AllowedTools.ofMcpToolFilter(mcpToolFilter)`. + */ + fun allowedTools(mcpToolFilter: AllowedTools.McpToolFilter) = + allowedTools(AllowedTools.ofMcpToolFilter(mcpToolFilter)) + + /** + * An OAuth access token that can be used with a remote MCP server, either with a + * custom MCP server URL or a service connector. Your application must handle the + * OAuth authorization flow and provide the token here. + */ + fun authorization(authorization: String) = + authorization(JsonField.of(authorization)) + + /** + * Sets [Builder.authorization] to an arbitrary JSON value. + * + * You should usually call [Builder.authorization] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun authorization(authorization: JsonField) = apply { + this.authorization = authorization + } + + /** + * Identifier for service connectors, like those available in ChatGPT. One of + * `server_url`, `connector_id`, or `tunnel_id` must be provided. Learn more about + * service connectors + * [here](https://developers.openai.com/api/docs/guides/tools-connectors-mcp#connectors). + * + * This field is deprecated for models released after September 1, 2026. Use + * `server_url` to connect to a remote MCP server, or `tunnel_id` to connect through + * a Secure MCP Tunnel. + * + * Currently supported `connector_id` values are: + * - Dropbox: `connector_dropbox` + * - Gmail: `connector_gmail` + * - Google Calendar: `connector_googlecalendar` + * - Google Drive: `connector_googledrive` + * - Microsoft Teams: `connector_microsoftteams` + * - Outlook Calendar: `connector_outlookcalendar` + * - Outlook Email: `connector_outlookemail` + * - SharePoint: `connector_sharepoint` + */ + @Deprecated("deprecated") + fun connectorId(connectorId: ConnectorId) = connectorId(JsonField.of(connectorId)) + + /** + * Sets [Builder.connectorId] to an arbitrary JSON value. + * + * You should usually call [Builder.connectorId] with a well-typed [ConnectorId] + * value instead. This method is primarily for setting the field to an undocumented + * or not yet supported value. + */ + @Deprecated("deprecated") + fun connectorId(connectorId: JsonField) = apply { + this.connectorId = connectorId + } + + /** Whether this MCP tool is deferred and discovered via tool search. */ + fun deferLoading(deferLoading: Boolean) = deferLoading(JsonField.of(deferLoading)) + + /** + * Sets [Builder.deferLoading] to an arbitrary JSON value. + * + * You should usually call [Builder.deferLoading] with a well-typed [Boolean] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun deferLoading(deferLoading: JsonField) = apply { + this.deferLoading = deferLoading + } + + /** + * Optional HTTP headers to send to the MCP server. Use for authentication or other + * purposes. + */ + fun headers(headers: Headers?) = headers(JsonField.ofNullable(headers)) + + /** Alias for calling [Builder.headers] with `headers.orElse(null)`. */ + fun headers(headers: Optional) = headers(headers.getOrNull()) + + /** + * Sets [Builder.headers] to an arbitrary JSON value. + * + * You should usually call [Builder.headers] with a well-typed [Headers] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun headers(headers: JsonField) = apply { this.headers = headers } + + /** Specify which of the MCP server's tools require approval. */ + fun requireApproval(requireApproval: RequireApproval?) = + requireApproval(JsonField.ofNullable(requireApproval)) + + /** + * Alias for calling [Builder.requireApproval] with `requireApproval.orElse(null)`. + */ + fun requireApproval(requireApproval: Optional) = + requireApproval(requireApproval.getOrNull()) + + /** + * Sets [Builder.requireApproval] to an arbitrary JSON value. + * + * You should usually call [Builder.requireApproval] with a well-typed + * [RequireApproval] value instead. This method is primarily for setting the field + * to an undocumented or not yet supported value. + */ + fun requireApproval(requireApproval: JsonField) = apply { + this.requireApproval = requireApproval + } + + /** + * Alias for calling [requireApproval] with + * `RequireApproval.ofMcpToolApprovalFilter(mcpToolApprovalFilter)`. + */ + fun requireApproval(mcpToolApprovalFilter: RequireApproval.McpToolApprovalFilter) = + requireApproval(RequireApproval.ofMcpToolApprovalFilter(mcpToolApprovalFilter)) + + /** + * Alias for calling [requireApproval] with + * `RequireApproval.ofMcpToolApprovalSetting(mcpToolApprovalSetting)`. + */ + fun requireApproval( + mcpToolApprovalSetting: RequireApproval.McpToolApprovalSetting + ) = + requireApproval( + RequireApproval.ofMcpToolApprovalSetting(mcpToolApprovalSetting) + ) + + /** Optional description of the MCP server, used to provide more context. */ + fun serverDescription(serverDescription: String) = + serverDescription(JsonField.of(serverDescription)) + + /** + * Sets [Builder.serverDescription] to an arbitrary JSON value. + * + * You should usually call [Builder.serverDescription] with a well-typed [String] + * value instead. This method is primarily for setting the field to an undocumented + * or not yet supported value. + */ + fun serverDescription(serverDescription: JsonField) = apply { + this.serverDescription = serverDescription + } + + /** + * The URL for the MCP server. One of `server_url`, `connector_id`, or `tunnel_id` + * must be provided. + */ + fun serverUrl(serverUrl: String) = serverUrl(JsonField.of(serverUrl)) + + /** + * Sets [Builder.serverUrl] to an arbitrary JSON value. + * + * You should usually call [Builder.serverUrl] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun serverUrl(serverUrl: JsonField) = apply { this.serverUrl = serverUrl } + + /** + * The Secure MCP Tunnel ID to use instead of a direct server URL. One of + * `server_url`, `connector_id`, or `tunnel_id` must be provided. + */ + fun tunnelId(tunnelId: String) = tunnelId(JsonField.of(tunnelId)) + + /** + * Sets [Builder.tunnelId] to an arbitrary JSON value. + * + * You should usually call [Builder.tunnelId] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun tunnelId(tunnelId: JsonField) = apply { this.tunnelId = tunnelId } + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = + apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { + additionalProperties.remove(key) + } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [Mcp]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .serverLabel() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): Mcp = + Mcp( + checkRequired("serverLabel", serverLabel), + type, + (allowedCallers ?: JsonMissing.of()).map { it.toImmutable() }, + allowedTools, + authorization, + connectorId, + deferLoading, + headers, + requireApproval, + serverDescription, + serverUrl, + tunnelId, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws OpenAIInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): Mcp = apply { + if (validated) { + return@apply + } + + serverLabel() + _type().let { + if (it != JsonValue.from("mcp")) { + throw OpenAIInvalidDataException("'type' is invalid, received $it") + } + } + allowedCallers().ifPresent { it.forEach { it.validate() } } + allowedTools().ifPresent { it.validate() } + authorization() + connectorId().ifPresent { it.validate() } + deferLoading() + headers().ifPresent { it.validate() } + requireApproval().ifPresent { it.validate() } + serverDescription() + serverUrl() + tunnelId() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: OpenAIInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + (if (serverLabel.asKnown().isPresent) 1 else 0) + + type.let { if (it == JsonValue.from("mcp")) 1 else 0 } + + (allowedCallers.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + + (allowedTools.asKnown().getOrNull()?.validity() ?: 0) + + (if (authorization.asKnown().isPresent) 1 else 0) + + (connectorId.asKnown().getOrNull()?.validity() ?: 0) + + (if (deferLoading.asKnown().isPresent) 1 else 0) + + (headers.asKnown().getOrNull()?.validity() ?: 0) + + (requireApproval.asKnown().getOrNull()?.validity() ?: 0) + + (if (serverDescription.asKnown().isPresent) 1 else 0) + + (if (serverUrl.asKnown().isPresent) 1 else 0) + + (if (tunnelId.asKnown().isPresent) 1 else 0) + + class AllowedCaller + @JsonCreator + private constructor(private val value: JsonField) : Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that + * doesn't match any known member, and you want to know that value. For example, if + * the SDK is on an older version than the API, then the API may respond with new + * members that the SDK is unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val DIRECT = of("direct") + + @JvmField val PROGRAMMATIC = of("programmatic") + + @JvmStatic fun of(value: String) = AllowedCaller(JsonField.of(value)) + } + + /** An enum containing [AllowedCaller]'s known values. */ + enum class Known { + DIRECT, + PROGRAMMATIC, + } + + /** + * An enum containing [AllowedCaller]'s known values, as well as an [_UNKNOWN] + * member. + * + * An instance of [AllowedCaller] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, + * if the SDK is on an older version than the API, then the API may respond with + * new members that the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + DIRECT, + PROGRAMMATIC, + /** + * An enum member indicating that [AllowedCaller] was instantiated with an + * unknown value. + */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or + * [Value._UNKNOWN] if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if + * you want to throw for the unknown case. + */ + fun value(): Value = + when (this) { + DIRECT -> Value.DIRECT + PROGRAMMATIC -> Value.PROGRAMMATIC + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and + * don't want to throw for the unknown case. + * + * @throws OpenAIInvalidDataException if this class instance's value is a not a + * known member. + */ + fun known(): Known = + when (this) { + DIRECT -> Known.DIRECT + PROGRAMMATIC -> Known.PROGRAMMATIC + else -> throw OpenAIInvalidDataException("Unknown AllowedCaller: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for + * debugging and generally doesn't throw. + * + * @throws OpenAIInvalidDataException if this class instance's value does not have + * the expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { + OpenAIInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws OpenAIInvalidDataException if any value type in this object doesn't match + * its expected type. + */ + fun validate(): AllowedCaller = apply { + if (validated) { + return@apply + } + + known() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: OpenAIInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is AllowedCaller && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + /** List of allowed tool names or a filter object. */ + @JsonDeserialize(using = AllowedTools.Deserializer::class) + @JsonSerialize(using = AllowedTools.Serializer::class) + class AllowedTools + private constructor( + private val mcp: List? = null, + private val mcpToolFilter: McpToolFilter? = null, + private val _json: JsonValue? = null, + ) { + + /** A string array of allowed tool names */ + fun mcp(): Optional> = Optional.ofNullable(mcp) + + /** A filter object to specify which tools are allowed. */ + fun mcpToolFilter(): Optional = Optional.ofNullable(mcpToolFilter) + + fun isMcp(): Boolean = mcp != null + + fun isMcpToolFilter(): Boolean = mcpToolFilter != null + + /** A string array of allowed tool names */ + fun asMcp(): List = mcp.getOrThrow("mcp") + + /** A filter object to specify which tools are allowed. */ + fun asMcpToolFilter(): McpToolFilter = mcpToolFilter.getOrThrow("mcpToolFilter") + + fun _json(): Optional = Optional.ofNullable(_json) + + /** + * Maps this instance's current variant to a value of type [T] using the given + * [visitor]. + * + * Note that this method is _not_ forwards compatible with new variants from the + * API, unless [visitor] overrides [Visitor.unknown]. To handle variants not known + * to this version of the SDK gracefully, consider overriding [Visitor.unknown]: + * ```java + * import com.openai.core.JsonValue; + * import java.util.Optional; + * + * Optional result = allowedTools.accept(new AllowedTools.Visitor>() { + * @Override + * public Optional visitMcp(List mcp) { + * return Optional.of(mcp.toString()); + * } + * + * // ... + * + * @Override + * public Optional unknown(JsonValue json) { + * // Or inspect the `json`. + * return Optional.empty(); + * } + * }); + * ``` + * + * @throws OpenAIInvalidDataException if [Visitor.unknown] is not overridden in + * [visitor] and the current variant is unknown. + */ + fun accept(visitor: Visitor): T = + when { + mcp != null -> visitor.visitMcp(mcp) + mcpToolFilter != null -> visitor.visitMcpToolFilter(mcpToolFilter) + else -> visitor.unknown(_json) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws OpenAIInvalidDataException if any value type in this object doesn't match + * its expected type. + */ + fun validate(): AllowedTools = apply { + if (validated) { + return@apply + } + + accept( + object : Visitor { + override fun visitMcp(mcp: List) {} + + override fun visitMcpToolFilter(mcpToolFilter: McpToolFilter) { + mcpToolFilter.validate() + } + } + ) + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: OpenAIInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + accept( + object : Visitor { + override fun visitMcp(mcp: List) = mcp.size + + override fun visitMcpToolFilter(mcpToolFilter: McpToolFilter) = + mcpToolFilter.validity() + + override fun unknown(json: JsonValue?) = 0 + } + ) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is AllowedTools && + mcp == other.mcp && + mcpToolFilter == other.mcpToolFilter + } + + override fun hashCode(): Int = Objects.hash(mcp, mcpToolFilter) + + override fun toString(): String = + when { + mcp != null -> "AllowedTools{mcp=$mcp}" + mcpToolFilter != null -> "AllowedTools{mcpToolFilter=$mcpToolFilter}" + _json != null -> "AllowedTools{_unknown=$_json}" + else -> throw IllegalStateException("Invalid AllowedTools") + } + + companion object { + + /** A string array of allowed tool names */ + @JvmStatic fun ofMcp(mcp: List) = AllowedTools(mcp = mcp.toImmutable()) + + /** A filter object to specify which tools are allowed. */ + @JvmStatic + fun ofMcpToolFilter(mcpToolFilter: McpToolFilter) = + AllowedTools(mcpToolFilter = mcpToolFilter) + } + + /** + * An interface that defines how to map each variant of [AllowedTools] to a value of + * type [T]. + */ + interface Visitor { + + /** A string array of allowed tool names */ + fun visitMcp(mcp: List): T + + /** A filter object to specify which tools are allowed. */ + fun visitMcpToolFilter(mcpToolFilter: McpToolFilter): T + + /** + * Maps an unknown variant of [AllowedTools] to a value of type [T]. + * + * An instance of [AllowedTools] can contain an unknown variant if it was + * deserialized from data that doesn't match any known variant. For example, if + * the SDK is on an older version than the API, then the API may respond with + * new variants that the SDK is unaware of. + * + * @throws OpenAIInvalidDataException in the default implementation. + */ + fun unknown(json: JsonValue?): T { + throw OpenAIInvalidDataException("Unknown AllowedTools") + } + } + + internal class Deserializer : BaseDeserializer(AllowedTools::class) { + + override fun ObjectCodec.deserialize(node: JsonNode): AllowedTools { + val json = JsonValue.fromJsonNode(node) + + val bestMatches = + sequenceOf( + tryDeserialize(node, jacksonTypeRef())?.let { + AllowedTools(mcpToolFilter = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef>())?.let { + AllowedTools(mcp = it, _json = json) + }, + ) + .filterNotNull() + .allMaxBy { it.validity() } + .toList() + return when (bestMatches.size) { + // This can happen if what we're deserializing is completely + // incompatible with all the possible variants (e.g. deserializing from + // boolean). + 0 -> AllowedTools(_json = json) + 1 -> bestMatches.single() + // If there's more than one match with the highest validity, then use + // the first completely valid match, or simply the first match if none + // are completely valid. + else -> bestMatches.firstOrNull { it.isValid() } ?: bestMatches.first() + } + } + } + + internal class Serializer : BaseSerializer(AllowedTools::class) { + + override fun serialize( + value: AllowedTools, + generator: JsonGenerator, + provider: SerializerProvider, + ) { + when { + value.mcp != null -> generator.writeObject(value.mcp) + value.mcpToolFilter != null -> + generator.writeObject(value.mcpToolFilter) + value._json != null -> generator.writeObject(value._json) + else -> throw IllegalStateException("Invalid AllowedTools") + } + } + } + + /** A filter object to specify which tools are allowed. */ + class McpToolFilter + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val readOnly: JsonField, + private val toolNames: JsonField>, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("read_only") + @ExcludeMissing + readOnly: JsonField = JsonMissing.of(), + @JsonProperty("tool_names") + @ExcludeMissing + toolNames: JsonField> = JsonMissing.of(), + ) : this(readOnly, toolNames, mutableMapOf()) + + /** + * Indicates whether or not a tool modifies data or is read-only. If an MCP + * server is + * [annotated with `readOnlyHint`](https://modelcontextprotocol.io/specification/2025-06-18/schema#toolannotations-readonlyhint), + * it will match this filter. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun readOnly(): Optional = readOnly.getOptional("read_only") + + /** + * List of allowed tool names. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun toolNames(): Optional> = toolNames.getOptional("tool_names") + + /** + * Returns the raw JSON value of [readOnly]. + * + * Unlike [readOnly], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("read_only") + @ExcludeMissing + fun _readOnly(): JsonField = readOnly + + /** + * Returns the raw JSON value of [toolNames]. + * + * Unlike [toolNames], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("tool_names") + @ExcludeMissing + fun _toolNames(): JsonField> = toolNames + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of + * [McpToolFilter]. + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [McpToolFilter]. */ + class Builder internal constructor() { + + private var readOnly: JsonField = JsonMissing.of() + private var toolNames: JsonField>? = null + private var additionalProperties: MutableMap = + mutableMapOf() + + @JvmSynthetic + internal fun from(mcpToolFilter: McpToolFilter) = apply { + readOnly = mcpToolFilter.readOnly + toolNames = mcpToolFilter.toolNames.map { it.toMutableList() } + additionalProperties = mcpToolFilter.additionalProperties.toMutableMap() + } + + /** + * Indicates whether or not a tool modifies data or is read-only. If an MCP + * server is + * [annotated with `readOnlyHint`](https://modelcontextprotocol.io/specification/2025-06-18/schema#toolannotations-readonlyhint), + * it will match this filter. + */ + fun readOnly(readOnly: Boolean) = readOnly(JsonField.of(readOnly)) + + /** + * Sets [Builder.readOnly] to an arbitrary JSON value. + * + * You should usually call [Builder.readOnly] with a well-typed [Boolean] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun readOnly(readOnly: JsonField) = apply { + this.readOnly = readOnly + } + + /** List of allowed tool names. */ + fun toolNames(toolNames: List) = toolNames(JsonField.of(toolNames)) + + /** + * Sets [Builder.toolNames] to an arbitrary JSON value. + * + * You should usually call [Builder.toolNames] with a well-typed + * `List` value instead. This method is primarily for setting the + * field to an undocumented or not yet supported value. + */ + fun toolNames(toolNames: JsonField>) = apply { + this.toolNames = toolNames.map { it.toMutableList() } + } + + /** + * Adds a single [String] to [toolNames]. + * + * @throws IllegalStateException if the field was previously set to a + * non-list. + */ + fun addToolName(toolName: String) = apply { + toolNames = + (toolNames ?: JsonField.of(mutableListOf())).also { + checkKnown("toolNames", it).add(toolName) + } + } + + fun additionalProperties(additionalProperties: Map) = + apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties( + additionalProperties: Map + ) = apply { this.additionalProperties.putAll(additionalProperties) } + + fun removeAdditionalProperty(key: String) = apply { + additionalProperties.remove(key) + } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [McpToolFilter]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): McpToolFilter = + McpToolFilter( + readOnly, + (toolNames ?: JsonMissing.of()).map { it.toImmutable() }, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected + * types recursively. + * + * This method is _not_ forwards compatible with new types from the API for + * existing fields. + * + * @throws OpenAIInvalidDataException if any value type in this object doesn't + * match its expected type. + */ + fun validate(): McpToolFilter = apply { + if (validated) { + return@apply + } + + readOnly() + toolNames() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: OpenAIInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + (if (readOnly.asKnown().isPresent) 1 else 0) + + (toolNames.asKnown().getOrNull()?.size ?: 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is McpToolFilter && + readOnly == other.readOnly && + toolNames == other.toolNames && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(readOnly, toolNames, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "McpToolFilter{readOnly=$readOnly, toolNames=$toolNames, additionalProperties=$additionalProperties}" + } + } + + /** + * Identifier for service connectors, like those available in ChatGPT. One of + * `server_url`, `connector_id`, or `tunnel_id` must be provided. Learn more about + * service connectors + * [here](https://developers.openai.com/api/docs/guides/tools-connectors-mcp#connectors). + * + * This field is deprecated for models released after September 1, 2026. Use + * `server_url` to connect to a remote MCP server, or `tunnel_id` to connect through a + * Secure MCP Tunnel. + * + * Currently supported `connector_id` values are: + * - Dropbox: `connector_dropbox` + * - Gmail: `connector_gmail` + * - Google Calendar: `connector_googlecalendar` + * - Google Drive: `connector_googledrive` + * - Microsoft Teams: `connector_microsoftteams` + * - Outlook Calendar: `connector_outlookcalendar` + * - Outlook Email: `connector_outlookemail` + * - SharePoint: `connector_sharepoint` + */ + @Deprecated("deprecated") + class ConnectorId + @JsonCreator + private constructor(private val value: JsonField) : Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that + * doesn't match any known member, and you want to know that value. For example, if + * the SDK is on an older version than the API, then the API may respond with new + * members that the SDK is unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val CONNECTOR_DROPBOX = of("connector_dropbox") + + @JvmField val CONNECTOR_GMAIL = of("connector_gmail") + + @JvmField val CONNECTOR_GOOGLECALENDAR = of("connector_googlecalendar") + + @JvmField val CONNECTOR_GOOGLEDRIVE = of("connector_googledrive") + + @JvmField val CONNECTOR_MICROSOFTTEAMS = of("connector_microsoftteams") + + @JvmField val CONNECTOR_OUTLOOKCALENDAR = of("connector_outlookcalendar") + + @JvmField val CONNECTOR_OUTLOOKEMAIL = of("connector_outlookemail") + + @JvmField val CONNECTOR_SHAREPOINT = of("connector_sharepoint") + + @JvmStatic fun of(value: String) = ConnectorId(JsonField.of(value)) + } + + /** An enum containing [ConnectorId]'s known values. */ + enum class Known { + CONNECTOR_DROPBOX, + CONNECTOR_GMAIL, + CONNECTOR_GOOGLECALENDAR, + CONNECTOR_GOOGLEDRIVE, + CONNECTOR_MICROSOFTTEAMS, + CONNECTOR_OUTLOOKCALENDAR, + CONNECTOR_OUTLOOKEMAIL, + CONNECTOR_SHAREPOINT, + } + + /** + * An enum containing [ConnectorId]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [ConnectorId] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, + * if the SDK is on an older version than the API, then the API may respond with + * new members that the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + CONNECTOR_DROPBOX, + CONNECTOR_GMAIL, + CONNECTOR_GOOGLECALENDAR, + CONNECTOR_GOOGLEDRIVE, + CONNECTOR_MICROSOFTTEAMS, + CONNECTOR_OUTLOOKCALENDAR, + CONNECTOR_OUTLOOKEMAIL, + CONNECTOR_SHAREPOINT, + /** + * An enum member indicating that [ConnectorId] was instantiated with an unknown + * value. + */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or + * [Value._UNKNOWN] if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if + * you want to throw for the unknown case. + */ + fun value(): Value = + when (this) { + CONNECTOR_DROPBOX -> Value.CONNECTOR_DROPBOX + CONNECTOR_GMAIL -> Value.CONNECTOR_GMAIL + CONNECTOR_GOOGLECALENDAR -> Value.CONNECTOR_GOOGLECALENDAR + CONNECTOR_GOOGLEDRIVE -> Value.CONNECTOR_GOOGLEDRIVE + CONNECTOR_MICROSOFTTEAMS -> Value.CONNECTOR_MICROSOFTTEAMS + CONNECTOR_OUTLOOKCALENDAR -> Value.CONNECTOR_OUTLOOKCALENDAR + CONNECTOR_OUTLOOKEMAIL -> Value.CONNECTOR_OUTLOOKEMAIL + CONNECTOR_SHAREPOINT -> Value.CONNECTOR_SHAREPOINT + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and + * don't want to throw for the unknown case. + * + * @throws OpenAIInvalidDataException if this class instance's value is a not a + * known member. + */ + fun known(): Known = + when (this) { + CONNECTOR_DROPBOX -> Known.CONNECTOR_DROPBOX + CONNECTOR_GMAIL -> Known.CONNECTOR_GMAIL + CONNECTOR_GOOGLECALENDAR -> Known.CONNECTOR_GOOGLECALENDAR + CONNECTOR_GOOGLEDRIVE -> Known.CONNECTOR_GOOGLEDRIVE + CONNECTOR_MICROSOFTTEAMS -> Known.CONNECTOR_MICROSOFTTEAMS + CONNECTOR_OUTLOOKCALENDAR -> Known.CONNECTOR_OUTLOOKCALENDAR + CONNECTOR_OUTLOOKEMAIL -> Known.CONNECTOR_OUTLOOKEMAIL + CONNECTOR_SHAREPOINT -> Known.CONNECTOR_SHAREPOINT + else -> throw OpenAIInvalidDataException("Unknown ConnectorId: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for + * debugging and generally doesn't throw. + * + * @throws OpenAIInvalidDataException if this class instance's value does not have + * the expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { + OpenAIInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws OpenAIInvalidDataException if any value type in this object doesn't match + * its expected type. + */ + fun validate(): ConnectorId = apply { + if (validated) { + return@apply + } + + known() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: OpenAIInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is ConnectorId && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + /** + * Optional HTTP headers to send to the MCP server. Use for authentication or other + * purposes. + */ + class Headers + @JsonCreator + private constructor( + @com.fasterxml.jackson.annotation.JsonValue + private val additionalProperties: Map + ) { + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = additionalProperties + + fun toBuilder() = Builder().from(this) + + companion object { + + /** Returns a mutable builder for constructing an instance of [Headers]. */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Headers]. */ + class Builder internal constructor() { + + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(headers: Headers) = apply { + additionalProperties = headers.additionalProperties.toMutableMap() + } + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + /** Adds a string-valued property. */ + fun putProperty(key: String, value: String) = apply { + putAdditionalProperty(key, JsonValue.from(value)) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = + apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { + additionalProperties.remove(key) + } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [Headers]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): Headers = Headers(additionalProperties.toImmutable()) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws OpenAIInvalidDataException if any value type in this object doesn't match + * its expected type. + */ + fun validate(): Headers = apply { + if (validated) { + return@apply + } + + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: OpenAIInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + additionalProperties.count { (_, value) -> + !value.isNull() && !value.isMissing() + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Headers && additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(additionalProperties) } + + override fun hashCode(): Int = hashCode + + override fun toString() = "Headers{additionalProperties=$additionalProperties}" + } + + /** Specify which of the MCP server's tools require approval. */ + @JsonDeserialize(using = RequireApproval.Deserializer::class) + @JsonSerialize(using = RequireApproval.Serializer::class) + class RequireApproval + private constructor( + private val mcpToolApprovalFilter: McpToolApprovalFilter? = null, + private val mcpToolApprovalSetting: McpToolApprovalSetting? = null, + private val _json: JsonValue? = null, + ) { + + /** + * Specify which of the MCP server's tools require approval. Can be `always`, + * `never`, or a filter object associated with tools that require approval. + */ + fun mcpToolApprovalFilter(): Optional = + Optional.ofNullable(mcpToolApprovalFilter) + + /** + * Specify a single approval policy for all tools. One of `always` or `never`. When + * set to `always`, all tools will require approval. When set to `never`, all tools + * will not require approval. + */ + fun mcpToolApprovalSetting(): Optional = + Optional.ofNullable(mcpToolApprovalSetting) + + fun isMcpToolApprovalFilter(): Boolean = mcpToolApprovalFilter != null + + fun isMcpToolApprovalSetting(): Boolean = mcpToolApprovalSetting != null + + /** + * Specify which of the MCP server's tools require approval. Can be `always`, + * `never`, or a filter object associated with tools that require approval. + */ + fun asMcpToolApprovalFilter(): McpToolApprovalFilter = + mcpToolApprovalFilter.getOrThrow("mcpToolApprovalFilter") + + /** + * Specify a single approval policy for all tools. One of `always` or `never`. When + * set to `always`, all tools will require approval. When set to `never`, all tools + * will not require approval. + */ + fun asMcpToolApprovalSetting(): McpToolApprovalSetting = + mcpToolApprovalSetting.getOrThrow("mcpToolApprovalSetting") + + fun _json(): Optional = Optional.ofNullable(_json) + + /** + * Maps this instance's current variant to a value of type [T] using the given + * [visitor]. + * + * Note that this method is _not_ forwards compatible with new variants from the + * API, unless [visitor] overrides [Visitor.unknown]. To handle variants not known + * to this version of the SDK gracefully, consider overriding [Visitor.unknown]: + * ```java + * import com.openai.core.JsonValue; + * import java.util.Optional; + * + * Optional result = requireApproval.accept(new RequireApproval.Visitor>() { + * @Override + * public Optional visitMcpToolApprovalFilter(McpToolApprovalFilter mcpToolApprovalFilter) { + * return Optional.of(mcpToolApprovalFilter.toString()); + * } + * + * // ... + * + * @Override + * public Optional unknown(JsonValue json) { + * // Or inspect the `json`. + * return Optional.empty(); + * } + * }); + * ``` + * + * @throws OpenAIInvalidDataException if [Visitor.unknown] is not overridden in + * [visitor] and the current variant is unknown. + */ + fun accept(visitor: Visitor): T = + when { + mcpToolApprovalFilter != null -> + visitor.visitMcpToolApprovalFilter(mcpToolApprovalFilter) + mcpToolApprovalSetting != null -> + visitor.visitMcpToolApprovalSetting(mcpToolApprovalSetting) + else -> visitor.unknown(_json) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws OpenAIInvalidDataException if any value type in this object doesn't match + * its expected type. + */ + fun validate(): RequireApproval = apply { + if (validated) { + return@apply + } + + accept( + object : Visitor { + override fun visitMcpToolApprovalFilter( + mcpToolApprovalFilter: McpToolApprovalFilter + ) { + mcpToolApprovalFilter.validate() + } + + override fun visitMcpToolApprovalSetting( + mcpToolApprovalSetting: McpToolApprovalSetting + ) { + mcpToolApprovalSetting.validate() + } + } + ) + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: OpenAIInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + accept( + object : Visitor { + override fun visitMcpToolApprovalFilter( + mcpToolApprovalFilter: McpToolApprovalFilter + ) = mcpToolApprovalFilter.validity() + + override fun visitMcpToolApprovalSetting( + mcpToolApprovalSetting: McpToolApprovalSetting + ) = mcpToolApprovalSetting.validity() + + override fun unknown(json: JsonValue?) = 0 + } + ) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is RequireApproval && + mcpToolApprovalFilter == other.mcpToolApprovalFilter && + mcpToolApprovalSetting == other.mcpToolApprovalSetting + } + + override fun hashCode(): Int = + Objects.hash(mcpToolApprovalFilter, mcpToolApprovalSetting) + + override fun toString(): String = + when { + mcpToolApprovalFilter != null -> + "RequireApproval{mcpToolApprovalFilter=$mcpToolApprovalFilter}" + mcpToolApprovalSetting != null -> + "RequireApproval{mcpToolApprovalSetting=$mcpToolApprovalSetting}" + _json != null -> "RequireApproval{_unknown=$_json}" + else -> throw IllegalStateException("Invalid RequireApproval") + } + + companion object { + + /** + * Specify which of the MCP server's tools require approval. Can be `always`, + * `never`, or a filter object associated with tools that require approval. + */ + @JvmStatic + fun ofMcpToolApprovalFilter(mcpToolApprovalFilter: McpToolApprovalFilter) = + RequireApproval(mcpToolApprovalFilter = mcpToolApprovalFilter) + + /** + * Specify a single approval policy for all tools. One of `always` or `never`. + * When set to `always`, all tools will require approval. When set to `never`, + * all tools will not require approval. + */ + @JvmStatic + fun ofMcpToolApprovalSetting(mcpToolApprovalSetting: McpToolApprovalSetting) = + RequireApproval(mcpToolApprovalSetting = mcpToolApprovalSetting) + } + + /** + * An interface that defines how to map each variant of [RequireApproval] to a value + * of type [T]. + */ + interface Visitor { + + /** + * Specify which of the MCP server's tools require approval. Can be `always`, + * `never`, or a filter object associated with tools that require approval. + */ + fun visitMcpToolApprovalFilter(mcpToolApprovalFilter: McpToolApprovalFilter): T + + /** + * Specify a single approval policy for all tools. One of `always` or `never`. + * When set to `always`, all tools will require approval. When set to `never`, + * all tools will not require approval. + */ + fun visitMcpToolApprovalSetting( + mcpToolApprovalSetting: McpToolApprovalSetting + ): T + + /** + * Maps an unknown variant of [RequireApproval] to a value of type [T]. + * + * An instance of [RequireApproval] can contain an unknown variant if it was + * deserialized from data that doesn't match any known variant. For example, if + * the SDK is on an older version than the API, then the API may respond with + * new variants that the SDK is unaware of. + * + * @throws OpenAIInvalidDataException in the default implementation. + */ + fun unknown(json: JsonValue?): T { + throw OpenAIInvalidDataException("Unknown RequireApproval") + } + } + + internal class Deserializer : + BaseDeserializer(RequireApproval::class) { + + override fun ObjectCodec.deserialize(node: JsonNode): RequireApproval { + val json = JsonValue.fromJsonNode(node) + + val bestMatches = + sequenceOf( + tryDeserialize(node, jacksonTypeRef()) + ?.let { + RequireApproval( + mcpToolApprovalFilter = it, + _json = json, + ) + }, + tryDeserialize(node, jacksonTypeRef()) + ?.let { + RequireApproval( + mcpToolApprovalSetting = it, + _json = json, + ) + }, + ) + .filterNotNull() + .allMaxBy { it.validity() } + .toList() + return when (bestMatches.size) { + // This can happen if what we're deserializing is completely + // incompatible with all the possible variants (e.g. deserializing from + // boolean). + 0 -> RequireApproval(_json = json) + 1 -> bestMatches.single() + // If there's more than one match with the highest validity, then use + // the first completely valid match, or simply the first match if none + // are completely valid. + else -> bestMatches.firstOrNull { it.isValid() } ?: bestMatches.first() + } + } + } + + internal class Serializer : + BaseSerializer(RequireApproval::class) { + + override fun serialize( + value: RequireApproval, + generator: JsonGenerator, + provider: SerializerProvider, + ) { + when { + value.mcpToolApprovalFilter != null -> + generator.writeObject(value.mcpToolApprovalFilter) + value.mcpToolApprovalSetting != null -> + generator.writeObject(value.mcpToolApprovalSetting) + value._json != null -> generator.writeObject(value._json) + else -> throw IllegalStateException("Invalid RequireApproval") + } + } + } + + /** + * Specify which of the MCP server's tools require approval. Can be `always`, + * `never`, or a filter object associated with tools that require approval. + */ + class McpToolApprovalFilter + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val always: JsonField, + private val never: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("always") + @ExcludeMissing + always: JsonField = JsonMissing.of(), + @JsonProperty("never") + @ExcludeMissing + never: JsonField = JsonMissing.of(), + ) : this(always, never, mutableMapOf()) + + /** + * A filter object to specify which tools are allowed. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun always(): Optional = always.getOptional("always") + + /** + * A filter object to specify which tools are allowed. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun never(): Optional = never.getOptional("never") + + /** + * Returns the raw JSON value of [always]. + * + * Unlike [always], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("always") + @ExcludeMissing + fun _always(): JsonField = always + + /** + * Returns the raw JSON value of [never]. + * + * Unlike [never], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("never") @ExcludeMissing fun _never(): JsonField = never + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of + * [McpToolApprovalFilter]. + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [McpToolApprovalFilter]. */ + class Builder internal constructor() { + + private var always: JsonField = JsonMissing.of() + private var never: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = + mutableMapOf() + + @JvmSynthetic + internal fun from(mcpToolApprovalFilter: McpToolApprovalFilter) = apply { + always = mcpToolApprovalFilter.always + never = mcpToolApprovalFilter.never + additionalProperties = + mcpToolApprovalFilter.additionalProperties.toMutableMap() + } + + /** A filter object to specify which tools are allowed. */ + fun always(always: Always) = always(JsonField.of(always)) + + /** + * Sets [Builder.always] to an arbitrary JSON value. + * + * You should usually call [Builder.always] with a well-typed [Always] value + * instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun always(always: JsonField) = apply { this.always = always } + + /** A filter object to specify which tools are allowed. */ + fun never(never: Never) = never(JsonField.of(never)) + + /** + * Sets [Builder.never] to an arbitrary JSON value. + * + * You should usually call [Builder.never] with a well-typed [Never] value + * instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun never(never: JsonField) = apply { this.never = never } + + fun additionalProperties(additionalProperties: Map) = + apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties( + additionalProperties: Map + ) = apply { this.additionalProperties.putAll(additionalProperties) } + + fun removeAdditionalProperty(key: String) = apply { + additionalProperties.remove(key) + } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [McpToolApprovalFilter]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): McpToolApprovalFilter = + McpToolApprovalFilter( + always, + never, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected + * types recursively. + * + * This method is _not_ forwards compatible with new types from the API for + * existing fields. + * + * @throws OpenAIInvalidDataException if any value type in this object doesn't + * match its expected type. + */ + fun validate(): McpToolApprovalFilter = apply { + if (validated) { + return@apply + } + + always().ifPresent { it.validate() } + never().ifPresent { it.validate() } + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: OpenAIInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + (always.asKnown().getOrNull()?.validity() ?: 0) + + (never.asKnown().getOrNull()?.validity() ?: 0) + + /** A filter object to specify which tools are allowed. */ + class Always + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val readOnly: JsonField, + private val toolNames: JsonField>, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("read_only") + @ExcludeMissing + readOnly: JsonField = JsonMissing.of(), + @JsonProperty("tool_names") + @ExcludeMissing + toolNames: JsonField> = JsonMissing.of(), + ) : this(readOnly, toolNames, mutableMapOf()) + + /** + * Indicates whether or not a tool modifies data or is read-only. If an MCP + * server is + * [annotated with `readOnlyHint`](https://modelcontextprotocol.io/specification/2025-06-18/schema#toolannotations-readonlyhint), + * it will match this filter. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun readOnly(): Optional = readOnly.getOptional("read_only") + + /** + * List of allowed tool names. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun toolNames(): Optional> = + toolNames.getOptional("tool_names") + + /** + * Returns the raw JSON value of [readOnly]. + * + * Unlike [readOnly], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("read_only") + @ExcludeMissing + fun _readOnly(): JsonField = readOnly + + /** + * Returns the raw JSON value of [toolNames]. + * + * Unlike [toolNames], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("tool_names") + @ExcludeMissing + fun _toolNames(): JsonField> = toolNames + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [Always]. + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Always]. */ + class Builder internal constructor() { + + private var readOnly: JsonField = JsonMissing.of() + private var toolNames: JsonField>? = null + private var additionalProperties: MutableMap = + mutableMapOf() + + @JvmSynthetic + internal fun from(always: Always) = apply { + readOnly = always.readOnly + toolNames = always.toolNames.map { it.toMutableList() } + additionalProperties = always.additionalProperties.toMutableMap() + } + + /** + * Indicates whether or not a tool modifies data or is read-only. If an + * MCP server is + * [annotated with `readOnlyHint`](https://modelcontextprotocol.io/specification/2025-06-18/schema#toolannotations-readonlyhint), + * it will match this filter. + */ + fun readOnly(readOnly: Boolean) = readOnly(JsonField.of(readOnly)) + + /** + * Sets [Builder.readOnly] to an arbitrary JSON value. + * + * You should usually call [Builder.readOnly] with a well-typed + * [Boolean] value instead. This method is primarily for setting the + * field to an undocumented or not yet supported value. + */ + fun readOnly(readOnly: JsonField) = apply { + this.readOnly = readOnly + } + + /** List of allowed tool names. */ + fun toolNames(toolNames: List) = + toolNames(JsonField.of(toolNames)) + + /** + * Sets [Builder.toolNames] to an arbitrary JSON value. + * + * You should usually call [Builder.toolNames] with a well-typed + * `List` value instead. This method is primarily for setting + * the field to an undocumented or not yet supported value. + */ + fun toolNames(toolNames: JsonField>) = apply { + this.toolNames = toolNames.map { it.toMutableList() } + } + + /** + * Adds a single [String] to [toolNames]. + * + * @throws IllegalStateException if the field was previously set to a + * non-list. + */ + fun addToolName(toolName: String) = apply { + toolNames = + (toolNames ?: JsonField.of(mutableListOf())).also { + checkKnown("toolNames", it).add(toolName) + } + } + + fun additionalProperties(additionalProperties: Map) = + apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties( + additionalProperties: Map + ) = apply { this.additionalProperties.putAll(additionalProperties) } + + fun removeAdditionalProperty(key: String) = apply { + additionalProperties.remove(key) + } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [Always]. + * + * Further updates to this [Builder] will not mutate the returned + * instance. + */ + fun build(): Always = + Always( + readOnly, + (toolNames ?: JsonMissing.of()).map { it.toImmutable() }, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their + * expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for + * existing fields. + * + * @throws OpenAIInvalidDataException if any value type in this object + * doesn't match its expected type. + */ + fun validate(): Always = apply { + if (validated) { + return@apply + } + + readOnly() + toolNames() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: OpenAIInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this + * object recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + (if (readOnly.asKnown().isPresent) 1 else 0) + + (toolNames.asKnown().getOrNull()?.size ?: 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Always && + readOnly == other.readOnly && + toolNames == other.toolNames && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(readOnly, toolNames, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Always{readOnly=$readOnly, toolNames=$toolNames, additionalProperties=$additionalProperties}" + } + + /** A filter object to specify which tools are allowed. */ + class Never + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val readOnly: JsonField, + private val toolNames: JsonField>, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("read_only") + @ExcludeMissing + readOnly: JsonField = JsonMissing.of(), + @JsonProperty("tool_names") + @ExcludeMissing + toolNames: JsonField> = JsonMissing.of(), + ) : this(readOnly, toolNames, mutableMapOf()) + + /** + * Indicates whether or not a tool modifies data or is read-only. If an MCP + * server is + * [annotated with `readOnlyHint`](https://modelcontextprotocol.io/specification/2025-06-18/schema#toolannotations-readonlyhint), + * it will match this filter. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun readOnly(): Optional = readOnly.getOptional("read_only") + + /** + * List of allowed tool names. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun toolNames(): Optional> = + toolNames.getOptional("tool_names") + + /** + * Returns the raw JSON value of [readOnly]. + * + * Unlike [readOnly], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("read_only") + @ExcludeMissing + fun _readOnly(): JsonField = readOnly + + /** + * Returns the raw JSON value of [toolNames]. + * + * Unlike [toolNames], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("tool_names") + @ExcludeMissing + fun _toolNames(): JsonField> = toolNames + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [Never]. + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Never]. */ + class Builder internal constructor() { + + private var readOnly: JsonField = JsonMissing.of() + private var toolNames: JsonField>? = null + private var additionalProperties: MutableMap = + mutableMapOf() + + @JvmSynthetic + internal fun from(never: Never) = apply { + readOnly = never.readOnly + toolNames = never.toolNames.map { it.toMutableList() } + additionalProperties = never.additionalProperties.toMutableMap() + } + + /** + * Indicates whether or not a tool modifies data or is read-only. If an + * MCP server is + * [annotated with `readOnlyHint`](https://modelcontextprotocol.io/specification/2025-06-18/schema#toolannotations-readonlyhint), + * it will match this filter. + */ + fun readOnly(readOnly: Boolean) = readOnly(JsonField.of(readOnly)) + + /** + * Sets [Builder.readOnly] to an arbitrary JSON value. + * + * You should usually call [Builder.readOnly] with a well-typed + * [Boolean] value instead. This method is primarily for setting the + * field to an undocumented or not yet supported value. + */ + fun readOnly(readOnly: JsonField) = apply { + this.readOnly = readOnly + } + + /** List of allowed tool names. */ + fun toolNames(toolNames: List) = + toolNames(JsonField.of(toolNames)) + + /** + * Sets [Builder.toolNames] to an arbitrary JSON value. + * + * You should usually call [Builder.toolNames] with a well-typed + * `List` value instead. This method is primarily for setting + * the field to an undocumented or not yet supported value. + */ + fun toolNames(toolNames: JsonField>) = apply { + this.toolNames = toolNames.map { it.toMutableList() } + } + + /** + * Adds a single [String] to [toolNames]. + * + * @throws IllegalStateException if the field was previously set to a + * non-list. + */ + fun addToolName(toolName: String) = apply { + toolNames = + (toolNames ?: JsonField.of(mutableListOf())).also { + checkKnown("toolNames", it).add(toolName) + } + } + + fun additionalProperties(additionalProperties: Map) = + apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties( + additionalProperties: Map + ) = apply { this.additionalProperties.putAll(additionalProperties) } + + fun removeAdditionalProperty(key: String) = apply { + additionalProperties.remove(key) + } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [Never]. + * + * Further updates to this [Builder] will not mutate the returned + * instance. + */ + fun build(): Never = + Never( + readOnly, + (toolNames ?: JsonMissing.of()).map { it.toImmutable() }, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their + * expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for + * existing fields. + * + * @throws OpenAIInvalidDataException if any value type in this object + * doesn't match its expected type. + */ + fun validate(): Never = apply { + if (validated) { + return@apply + } + + readOnly() + toolNames() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: OpenAIInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this + * object recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + (if (readOnly.asKnown().isPresent) 1 else 0) + + (toolNames.asKnown().getOrNull()?.size ?: 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Never && + readOnly == other.readOnly && + toolNames == other.toolNames && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(readOnly, toolNames, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Never{readOnly=$readOnly, toolNames=$toolNames, additionalProperties=$additionalProperties}" + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is McpToolApprovalFilter && + always == other.always && + never == other.never && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(always, never, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "McpToolApprovalFilter{always=$always, never=$never, additionalProperties=$additionalProperties}" + } + + /** + * Specify a single approval policy for all tools. One of `always` or `never`. When + * set to `always`, all tools will require approval. When set to `never`, all tools + * will not require approval. + */ + class McpToolApprovalSetting + @JsonCreator + private constructor(private val value: JsonField) : Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that + * doesn't match any known member, and you want to know that value. For example, + * if the SDK is on an older version than the API, then the API may respond with + * new members that the SDK is unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue + fun _value(): JsonField = value + + companion object { + + @JvmField val ALWAYS = of("always") + + @JvmField val NEVER = of("never") + + @JvmStatic + fun of(value: String) = McpToolApprovalSetting(JsonField.of(value)) + } + + /** An enum containing [McpToolApprovalSetting]'s known values. */ + enum class Known { + ALWAYS, + NEVER, + } + + /** + * An enum containing [McpToolApprovalSetting]'s known values, as well as an + * [_UNKNOWN] member. + * + * An instance of [McpToolApprovalSetting] can contain an unknown value in a + * couple of cases: + * - It was deserialized from data that doesn't match any known member. For + * example, if the SDK is on an older version than the API, then the API may + * respond with new members that the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + ALWAYS, + NEVER, + /** + * An enum member indicating that [McpToolApprovalSetting] was instantiated + * with an unknown value. + */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or + * [Value._UNKNOWN] if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or + * if you want to throw for the unknown case. + */ + fun value(): Value = + when (this) { + ALWAYS -> Value.ALWAYS + NEVER -> Value.NEVER + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known + * and don't want to throw for the unknown case. + * + * @throws OpenAIInvalidDataException if this class instance's value is a not a + * known member. + */ + fun known(): Known = + when (this) { + ALWAYS -> Known.ALWAYS + NEVER -> Known.NEVER + else -> + throw OpenAIInvalidDataException( + "Unknown McpToolApprovalSetting: $value" + ) + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for + * debugging and generally doesn't throw. + * + * @throws OpenAIInvalidDataException if this class instance's value does not + * have the expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { + OpenAIInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected + * types recursively. + * + * This method is _not_ forwards compatible with new types from the API for + * existing fields. + * + * @throws OpenAIInvalidDataException if any value type in this object doesn't + * match its expected type. + */ + fun validate(): McpToolApprovalSetting = apply { + if (validated) { + return@apply + } + + known() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: OpenAIInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is McpToolApprovalSetting && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Mcp && + serverLabel == other.serverLabel && + type == other.type && + allowedCallers == other.allowedCallers && + allowedTools == other.allowedTools && + authorization == other.authorization && + connectorId == other.connectorId && + deferLoading == other.deferLoading && + headers == other.headers && + requireApproval == other.requireApproval && + serverDescription == other.serverDescription && + serverUrl == other.serverUrl && + tunnelId == other.tunnelId && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash( + serverLabel, + type, + allowedCallers, + allowedTools, + authorization, + connectorId, + deferLoading, + headers, + requireApproval, + serverDescription, + serverUrl, + tunnelId, + additionalProperties, + ) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Mcp{serverLabel=$serverLabel, type=$type, allowedCallers=$allowedCallers, allowedTools=$allowedTools, authorization=$authorization, connectorId=$connectorId, deferLoading=$deferLoading, headers=$headers, requireApproval=$requireApproval, serverDescription=$serverDescription, serverUrl=$serverUrl, tunnelId=$tunnelId, additionalProperties=$additionalProperties}" + } + + /** A tool that runs Python code to help generate a response to a prompt. */ + class CodeInterpreter + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val container: JsonField, + private val type: JsonValue, + private val allowedCallers: JsonField>, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("container") + @ExcludeMissing + container: JsonField = JsonMissing.of(), + @JsonProperty("type") @ExcludeMissing type: JsonValue = JsonMissing.of(), + @JsonProperty("allowed_callers") + @ExcludeMissing + allowedCallers: JsonField> = JsonMissing.of(), + ) : this(container, type, allowedCallers, mutableMapOf()) + + /** + * The code interpreter container. Can be a container ID or an object that specifies + * uploaded file IDs to make available to your code, along with an optional + * `memory_limit` setting. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected + * value). + */ + fun container(): Container = container.getRequired("container") + + /** + * The type of the code interpreter tool. Always `code_interpreter`. + * + * Expected to always return the following: + * ```java + * JsonValue.from("code_interpreter") + * ``` + * + * However, this method can be useful for debugging and logging (e.g. if the server + * responded with an unexpected value). + */ + @JsonProperty("type") @ExcludeMissing fun _type(): JsonValue = type + + /** + * The tool invocation context(s). + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun allowedCallers(): Optional> = + allowedCallers.getOptional("allowed_callers") + + /** + * Returns the raw JSON value of [container]. + * + * Unlike [container], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("container") + @ExcludeMissing + fun _container(): JsonField = container + + /** + * Returns the raw JSON value of [allowedCallers]. + * + * Unlike [allowedCallers], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("allowed_callers") + @ExcludeMissing + fun _allowedCallers(): JsonField> = allowedCallers + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [CodeInterpreter]. + * + * The following fields are required: + * ```java + * .container() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [CodeInterpreter]. */ + class Builder internal constructor() { + + private var container: JsonField? = null + private var type: JsonValue = JsonValue.from("code_interpreter") + private var allowedCallers: JsonField>? = null + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(codeInterpreter: CodeInterpreter) = apply { + container = codeInterpreter.container + type = codeInterpreter.type + allowedCallers = codeInterpreter.allowedCallers.map { it.toMutableList() } + additionalProperties = codeInterpreter.additionalProperties.toMutableMap() + } + + /** + * The code interpreter container. Can be a container ID or an object that specifies + * uploaded file IDs to make available to your code, along with an optional + * `memory_limit` setting. + */ + fun container(container: Container) = container(JsonField.of(container)) + + /** + * Sets [Builder.container] to an arbitrary JSON value. + * + * You should usually call [Builder.container] with a well-typed [Container] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun container(container: JsonField) = apply { + this.container = container + } + + /** Alias for calling [container] with `Container.ofString(string)`. */ + fun container(string: String) = container(Container.ofString(string)) + + /** + * Alias for calling [container] with + * `Container.ofCodeInterpreterToolAuto(codeInterpreterToolAuto)`. + */ + fun container(codeInterpreterToolAuto: Container.CodeInterpreterToolAuto) = + container(Container.ofCodeInterpreterToolAuto(codeInterpreterToolAuto)) + + /** + * Sets the field to an arbitrary JSON value. + * + * It is usually unnecessary to call this method because the field defaults to the + * following: + * ```java + * JsonValue.from("code_interpreter") + * ``` + * + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun type(type: JsonValue) = apply { this.type = type } + + /** The tool invocation context(s). */ + fun allowedCallers(allowedCallers: List?) = + allowedCallers(JsonField.ofNullable(allowedCallers)) + + /** + * Alias for calling [Builder.allowedCallers] with `allowedCallers.orElse(null)`. + */ + fun allowedCallers(allowedCallers: Optional>) = + allowedCallers(allowedCallers.getOrNull()) + + /** + * Sets [Builder.allowedCallers] to an arbitrary JSON value. + * + * You should usually call [Builder.allowedCallers] with a well-typed + * `List` value instead. This method is primarily for setting the + * field to an undocumented or not yet supported value. + */ + fun allowedCallers(allowedCallers: JsonField>) = apply { + this.allowedCallers = allowedCallers.map { it.toMutableList() } + } + + /** + * Adds a single [AllowedCaller] to [allowedCallers]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addAllowedCaller(allowedCaller: AllowedCaller) = apply { + allowedCallers = + (allowedCallers ?: JsonField.of(mutableListOf())).also { + checkKnown("allowedCallers", it).add(allowedCaller) + } + } + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = + apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { + additionalProperties.remove(key) + } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [CodeInterpreter]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .container() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): CodeInterpreter = + CodeInterpreter( + checkRequired("container", container), + type, + (allowedCallers ?: JsonMissing.of()).map { it.toImmutable() }, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws OpenAIInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): CodeInterpreter = apply { + if (validated) { + return@apply + } + + container().validate() + _type().let { + if (it != JsonValue.from("code_interpreter")) { + throw OpenAIInvalidDataException("'type' is invalid, received $it") + } + } + allowedCallers().ifPresent { it.forEach { it.validate() } } + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: OpenAIInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + (container.asKnown().getOrNull()?.validity() ?: 0) + + type.let { if (it == JsonValue.from("code_interpreter")) 1 else 0 } + + (allowedCallers.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + + /** + * The code interpreter container. Can be a container ID or an object that specifies + * uploaded file IDs to make available to your code, along with an optional + * `memory_limit` setting. + */ + @JsonDeserialize(using = Container.Deserializer::class) + @JsonSerialize(using = Container.Serializer::class) + class Container + private constructor( + private val string: String? = null, + private val codeInterpreterToolAuto: CodeInterpreterToolAuto? = null, + private val _json: JsonValue? = null, + ) { + + /** The container ID. */ + fun string(): Optional = Optional.ofNullable(string) + + /** + * Configuration for a code interpreter container. Optionally specify the IDs of the + * files to run the code on. + */ + fun codeInterpreterToolAuto(): Optional = + Optional.ofNullable(codeInterpreterToolAuto) + + fun isString(): Boolean = string != null + + fun isCodeInterpreterToolAuto(): Boolean = codeInterpreterToolAuto != null + + /** The container ID. */ + fun asString(): String = string.getOrThrow("string") + + /** + * Configuration for a code interpreter container. Optionally specify the IDs of the + * files to run the code on. + */ + fun asCodeInterpreterToolAuto(): CodeInterpreterToolAuto = + codeInterpreterToolAuto.getOrThrow("codeInterpreterToolAuto") + + fun _json(): Optional = Optional.ofNullable(_json) + + /** + * Maps this instance's current variant to a value of type [T] using the given + * [visitor]. + * + * Note that this method is _not_ forwards compatible with new variants from the + * API, unless [visitor] overrides [Visitor.unknown]. To handle variants not known + * to this version of the SDK gracefully, consider overriding [Visitor.unknown]: + * ```java + * import com.openai.core.JsonValue; + * import java.util.Optional; + * + * Optional result = container.accept(new Container.Visitor>() { + * @Override + * public Optional visitString(String string) { + * return Optional.of(string.toString()); + * } + * + * // ... + * + * @Override + * public Optional unknown(JsonValue json) { + * // Or inspect the `json`. + * return Optional.empty(); + * } + * }); + * ``` + * + * @throws OpenAIInvalidDataException if [Visitor.unknown] is not overridden in + * [visitor] and the current variant is unknown. + */ + fun accept(visitor: Visitor): T = + when { + string != null -> visitor.visitString(string) + codeInterpreterToolAuto != null -> + visitor.visitCodeInterpreterToolAuto(codeInterpreterToolAuto) + else -> visitor.unknown(_json) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws OpenAIInvalidDataException if any value type in this object doesn't match + * its expected type. + */ + fun validate(): Container = apply { + if (validated) { + return@apply + } + + accept( + object : Visitor { + override fun visitString(string: String) {} + + override fun visitCodeInterpreterToolAuto( + codeInterpreterToolAuto: CodeInterpreterToolAuto + ) { + codeInterpreterToolAuto.validate() + } + } + ) + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: OpenAIInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + accept( + object : Visitor { + override fun visitString(string: String) = 1 + + override fun visitCodeInterpreterToolAuto( + codeInterpreterToolAuto: CodeInterpreterToolAuto + ) = codeInterpreterToolAuto.validity() + + override fun unknown(json: JsonValue?) = 0 + } + ) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Container && + string == other.string && + codeInterpreterToolAuto == other.codeInterpreterToolAuto + } + + override fun hashCode(): Int = Objects.hash(string, codeInterpreterToolAuto) + + override fun toString(): String = + when { + string != null -> "Container{string=$string}" + codeInterpreterToolAuto != null -> + "Container{codeInterpreterToolAuto=$codeInterpreterToolAuto}" + _json != null -> "Container{_unknown=$_json}" + else -> throw IllegalStateException("Invalid Container") + } + + companion object { + + /** The container ID. */ + @JvmStatic fun ofString(string: String) = Container(string = string) + + /** + * Configuration for a code interpreter container. Optionally specify the IDs of + * the files to run the code on. + */ + @JvmStatic + fun ofCodeInterpreterToolAuto( + codeInterpreterToolAuto: CodeInterpreterToolAuto + ) = Container(codeInterpreterToolAuto = codeInterpreterToolAuto) + } + + /** + * An interface that defines how to map each variant of [Container] to a value of + * type [T]. + */ + interface Visitor { + + /** The container ID. */ + fun visitString(string: String): T + + /** + * Configuration for a code interpreter container. Optionally specify the IDs of + * the files to run the code on. + */ + fun visitCodeInterpreterToolAuto( + codeInterpreterToolAuto: CodeInterpreterToolAuto + ): T + + /** + * Maps an unknown variant of [Container] to a value of type [T]. + * + * An instance of [Container] can contain an unknown variant if it was + * deserialized from data that doesn't match any known variant. For example, if + * the SDK is on an older version than the API, then the API may respond with + * new variants that the SDK is unaware of. + * + * @throws OpenAIInvalidDataException in the default implementation. + */ + fun unknown(json: JsonValue?): T { + throw OpenAIInvalidDataException("Unknown Container") + } + } + + internal class Deserializer : BaseDeserializer(Container::class) { + + override fun ObjectCodec.deserialize(node: JsonNode): Container { + val json = JsonValue.fromJsonNode(node) + + val bestMatches = + sequenceOf( + tryDeserialize(node, jacksonTypeRef()) + ?.let { + Container(codeInterpreterToolAuto = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef())?.let { + Container(string = it, _json = json) + }, + ) + .filterNotNull() + .allMaxBy { it.validity() } + .toList() + return when (bestMatches.size) { + // This can happen if what we're deserializing is completely + // incompatible with all the possible variants (e.g. deserializing from + // boolean). + 0 -> Container(_json = json) + 1 -> bestMatches.single() + // If there's more than one match with the highest validity, then use + // the first completely valid match, or simply the first match if none + // are completely valid. + else -> bestMatches.firstOrNull { it.isValid() } ?: bestMatches.first() + } + } + } + + internal class Serializer : BaseSerializer(Container::class) { + + override fun serialize( + value: Container, + generator: JsonGenerator, + provider: SerializerProvider, + ) { + when { + value.string != null -> generator.writeObject(value.string) + value.codeInterpreterToolAuto != null -> + generator.writeObject(value.codeInterpreterToolAuto) + value._json != null -> generator.writeObject(value._json) + else -> throw IllegalStateException("Invalid Container") + } + } + } + + /** + * Configuration for a code interpreter container. Optionally specify the IDs of the + * files to run the code on. + */ + class CodeInterpreterToolAuto + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val type: JsonValue, + private val fileIds: JsonField>, + private val memoryLimit: JsonField, + private val networkPolicy: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("type") @ExcludeMissing type: JsonValue = JsonMissing.of(), + @JsonProperty("file_ids") + @ExcludeMissing + fileIds: JsonField> = JsonMissing.of(), + @JsonProperty("memory_limit") + @ExcludeMissing + memoryLimit: JsonField = JsonMissing.of(), + @JsonProperty("network_policy") + @ExcludeMissing + networkPolicy: JsonField = JsonMissing.of(), + ) : this(type, fileIds, memoryLimit, networkPolicy, mutableMapOf()) + + /** + * Always `auto`. + * + * Expected to always return the following: + * ```java + * JsonValue.from("auto") + * ``` + * + * However, this method can be useful for debugging and logging (e.g. if the + * server responded with an unexpected value). + */ + @JsonProperty("type") @ExcludeMissing fun _type(): JsonValue = type + + /** + * An optional list of uploaded files to make available to your code. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun fileIds(): Optional> = fileIds.getOptional("file_ids") + + /** + * The memory limit for the code interpreter container. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun memoryLimit(): Optional = + memoryLimit.getOptional("memory_limit") + + /** + * Network access policy for the container. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun networkPolicy(): Optional = + networkPolicy.getOptional("network_policy") + + /** + * Returns the raw JSON value of [fileIds]. + * + * Unlike [fileIds], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("file_ids") + @ExcludeMissing + fun _fileIds(): JsonField> = fileIds + + /** + * Returns the raw JSON value of [memoryLimit]. + * + * Unlike [memoryLimit], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("memory_limit") + @ExcludeMissing + fun _memoryLimit(): JsonField = memoryLimit + + /** + * Returns the raw JSON value of [networkPolicy]. + * + * Unlike [networkPolicy], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("network_policy") + @ExcludeMissing + fun _networkPolicy(): JsonField = networkPolicy + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of + * [CodeInterpreterToolAuto]. + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [CodeInterpreterToolAuto]. */ + class Builder internal constructor() { + + private var type: JsonValue = JsonValue.from("auto") + private var fileIds: JsonField>? = null + private var memoryLimit: JsonField = JsonMissing.of() + private var networkPolicy: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = + mutableMapOf() + + @JvmSynthetic + internal fun from(codeInterpreterToolAuto: CodeInterpreterToolAuto) = + apply { + type = codeInterpreterToolAuto.type + fileIds = codeInterpreterToolAuto.fileIds.map { it.toMutableList() } + memoryLimit = codeInterpreterToolAuto.memoryLimit + networkPolicy = codeInterpreterToolAuto.networkPolicy + additionalProperties = + codeInterpreterToolAuto.additionalProperties.toMutableMap() + } + + /** + * Sets the field to an arbitrary JSON value. + * + * It is usually unnecessary to call this method because the field defaults + * to the following: + * ```java + * JsonValue.from("auto") + * ``` + * + * This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun type(type: JsonValue) = apply { this.type = type } + + /** An optional list of uploaded files to make available to your code. */ + fun fileIds(fileIds: List) = fileIds(JsonField.of(fileIds)) + + /** + * Sets [Builder.fileIds] to an arbitrary JSON value. + * + * You should usually call [Builder.fileIds] with a well-typed + * `List` value instead. This method is primarily for setting the + * field to an undocumented or not yet supported value. + */ + fun fileIds(fileIds: JsonField>) = apply { + this.fileIds = fileIds.map { it.toMutableList() } + } + + /** + * Adds a single [String] to [fileIds]. + * + * @throws IllegalStateException if the field was previously set to a + * non-list. + */ + fun addFileId(fileId: String) = apply { + fileIds = + (fileIds ?: JsonField.of(mutableListOf())).also { + checkKnown("fileIds", it).add(fileId) + } + } + + /** The memory limit for the code interpreter container. */ + fun memoryLimit(memoryLimit: MemoryLimit?) = + memoryLimit(JsonField.ofNullable(memoryLimit)) + + /** + * Alias for calling [Builder.memoryLimit] with `memoryLimit.orElse(null)`. + */ + fun memoryLimit(memoryLimit: Optional) = + memoryLimit(memoryLimit.getOrNull()) + + /** + * Sets [Builder.memoryLimit] to an arbitrary JSON value. + * + * You should usually call [Builder.memoryLimit] with a well-typed + * [MemoryLimit] value instead. This method is primarily for setting the + * field to an undocumented or not yet supported value. + */ + fun memoryLimit(memoryLimit: JsonField) = apply { + this.memoryLimit = memoryLimit + } + + /** Network access policy for the container. */ + fun networkPolicy(networkPolicy: NetworkPolicy) = + networkPolicy(JsonField.of(networkPolicy)) + + /** + * Sets [Builder.networkPolicy] to an arbitrary JSON value. + * + * You should usually call [Builder.networkPolicy] with a well-typed + * [NetworkPolicy] value instead. This method is primarily for setting the + * field to an undocumented or not yet supported value. + */ + fun networkPolicy(networkPolicy: JsonField) = apply { + this.networkPolicy = networkPolicy + } + + /** + * Alias for calling [networkPolicy] with + * `NetworkPolicy.ofDisabled(disabled)`. + */ + fun networkPolicy(disabled: ContainerNetworkPolicyDisabled) = + networkPolicy(NetworkPolicy.ofDisabled(disabled)) + + /** + * Alias for calling [networkPolicy] with + * `NetworkPolicy.ofAllowlist(allowlist)`. + */ + fun networkPolicy(allowlist: ContainerNetworkPolicyAllowlist) = + networkPolicy(NetworkPolicy.ofAllowlist(allowlist)) + + /** + * Alias for calling [networkPolicy] with the following: + * ```java + * ContainerNetworkPolicyAllowlist.builder() + * .allowedDomains(allowedDomains) + * .build() + * ``` + */ + fun allowlistNetworkPolicy(allowedDomains: List) = + networkPolicy( + ContainerNetworkPolicyAllowlist.builder() + .allowedDomains(allowedDomains) + .build() + ) + + fun additionalProperties(additionalProperties: Map) = + apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties( + additionalProperties: Map + ) = apply { this.additionalProperties.putAll(additionalProperties) } + + fun removeAdditionalProperty(key: String) = apply { + additionalProperties.remove(key) + } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [CodeInterpreterToolAuto]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): CodeInterpreterToolAuto = + CodeInterpreterToolAuto( + type, + (fileIds ?: JsonMissing.of()).map { it.toImmutable() }, + memoryLimit, + networkPolicy, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected + * types recursively. + * + * This method is _not_ forwards compatible with new types from the API for + * existing fields. + * + * @throws OpenAIInvalidDataException if any value type in this object doesn't + * match its expected type. + */ + fun validate(): CodeInterpreterToolAuto = apply { + if (validated) { + return@apply + } + + _type().let { + if (it != JsonValue.from("auto")) { + throw OpenAIInvalidDataException("'type' is invalid, received $it") + } + } + fileIds() + memoryLimit().ifPresent { it.validate() } + networkPolicy().ifPresent { it.validate() } + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: OpenAIInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + type.let { if (it == JsonValue.from("auto")) 1 else 0 } + + (fileIds.asKnown().getOrNull()?.size ?: 0) + + (memoryLimit.asKnown().getOrNull()?.validity() ?: 0) + + (networkPolicy.asKnown().getOrNull()?.validity() ?: 0) + + /** The memory limit for the code interpreter container. */ + class MemoryLimit + @JsonCreator + private constructor(private val value: JsonField) : Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data + * that doesn't match any known member, and you want to know that value. For + * example, if the SDK is on an older version than the API, then the API may + * respond with new members that the SDK is unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue + fun _value(): JsonField = value + + companion object { + + @JvmField val _1G = of("1g") + + @JvmField val _4G = of("4g") + + @JvmField val _16G = of("16g") + + @JvmField val _64G = of("64g") + + @JvmStatic fun of(value: String) = MemoryLimit(JsonField.of(value)) + } + + /** An enum containing [MemoryLimit]'s known values. */ + enum class Known { + _1G, + _4G, + _16G, + _64G, + } + + /** + * An enum containing [MemoryLimit]'s known values, as well as an [_UNKNOWN] + * member. + * + * An instance of [MemoryLimit] can contain an unknown value in a couple of + * cases: + * - It was deserialized from data that doesn't match any known member. For + * example, if the SDK is on an older version than the API, then the API + * may respond with new members that the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + _1G, + _4G, + _16G, + _64G, + /** + * An enum member indicating that [MemoryLimit] was instantiated with an + * unknown value. + */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or + * [Value._UNKNOWN] if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always + * known or if you want to throw for the unknown case. + */ + fun value(): Value = + when (this) { + _1G -> Value._1G + _4G -> Value._4G + _16G -> Value._16G + _64G -> Value._64G + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always + * known and don't want to throw for the unknown case. + * + * @throws OpenAIInvalidDataException if this class instance's value is a + * not a known member. + */ + fun known(): Known = + when (this) { + _1G -> Known._1G + _4G -> Known._4G + _16G -> Known._16G + _64G -> Known._64G + else -> + throw OpenAIInvalidDataException("Unknown MemoryLimit: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily + * for debugging and generally doesn't throw. + * + * @throws OpenAIInvalidDataException if this class instance's value does + * not have the expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { + OpenAIInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their + * expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for + * existing fields. + * + * @throws OpenAIInvalidDataException if any value type in this object + * doesn't match its expected type. + */ + fun validate(): MemoryLimit = apply { + if (validated) { + return@apply + } + + known() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: OpenAIInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this + * object recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is MemoryLimit && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + /** Network access policy for the container. */ + @JsonDeserialize(using = NetworkPolicy.Deserializer::class) + @JsonSerialize(using = NetworkPolicy.Serializer::class) + class NetworkPolicy + private constructor( + private val disabled: ContainerNetworkPolicyDisabled? = null, + private val allowlist: ContainerNetworkPolicyAllowlist? = null, + private val _json: JsonValue? = null, + ) { + + fun disabled(): Optional = + Optional.ofNullable(disabled) + + fun allowlist(): Optional = + Optional.ofNullable(allowlist) + + fun isDisabled(): Boolean = disabled != null + + fun isAllowlist(): Boolean = allowlist != null + + fun asDisabled(): ContainerNetworkPolicyDisabled = + disabled.getOrThrow("disabled") + + fun asAllowlist(): ContainerNetworkPolicyAllowlist = + allowlist.getOrThrow("allowlist") + + fun _json(): Optional = Optional.ofNullable(_json) + + /** + * Maps this instance's current variant to a value of type [T] using the + * given [visitor]. + * + * Note that this method is _not_ forwards compatible with new variants from + * the API, unless [visitor] overrides [Visitor.unknown]. To handle variants + * not known to this version of the SDK gracefully, consider overriding + * [Visitor.unknown]: + * ```java + * import com.openai.core.JsonValue; + * import java.util.Optional; + * + * Optional result = networkPolicy.accept(new NetworkPolicy.Visitor>() { + * @Override + * public Optional visitDisabled(ContainerNetworkPolicyDisabled disabled) { + * return Optional.of(disabled.toString()); + * } + * + * // ... + * + * @Override + * public Optional unknown(JsonValue json) { + * // Or inspect the `json`. + * return Optional.empty(); + * } + * }); + * ``` + * + * @throws OpenAIInvalidDataException if [Visitor.unknown] is not overridden + * in [visitor] and the current variant is unknown. + */ + fun accept(visitor: Visitor): T = + when { + disabled != null -> visitor.visitDisabled(disabled) + allowlist != null -> visitor.visitAllowlist(allowlist) + else -> visitor.unknown(_json) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their + * expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for + * existing fields. + * + * @throws OpenAIInvalidDataException if any value type in this object + * doesn't match its expected type. + */ + fun validate(): NetworkPolicy = apply { + if (validated) { + return@apply + } + + accept( + object : Visitor { + override fun visitDisabled( + disabled: ContainerNetworkPolicyDisabled + ) { + disabled.validate() + } + + override fun visitAllowlist( + allowlist: ContainerNetworkPolicyAllowlist + ) { + allowlist.validate() + } + } + ) + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: OpenAIInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this + * object recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + accept( + object : Visitor { + override fun visitDisabled( + disabled: ContainerNetworkPolicyDisabled + ) = disabled.validity() + + override fun visitAllowlist( + allowlist: ContainerNetworkPolicyAllowlist + ) = allowlist.validity() + + override fun unknown(json: JsonValue?) = 0 + } + ) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is NetworkPolicy && + disabled == other.disabled && + allowlist == other.allowlist + } + + override fun hashCode(): Int = Objects.hash(disabled, allowlist) + + override fun toString(): String = + when { + disabled != null -> "NetworkPolicy{disabled=$disabled}" + allowlist != null -> "NetworkPolicy{allowlist=$allowlist}" + _json != null -> "NetworkPolicy{_unknown=$_json}" + else -> throw IllegalStateException("Invalid NetworkPolicy") + } + + companion object { + + @JvmStatic + fun ofDisabled(disabled: ContainerNetworkPolicyDisabled) = + NetworkPolicy(disabled = disabled) + + @JvmStatic + fun ofAllowlist(allowlist: ContainerNetworkPolicyAllowlist) = + NetworkPolicy(allowlist = allowlist) + } + + /** + * An interface that defines how to map each variant of [NetworkPolicy] to a + * value of type [T]. + */ + interface Visitor { + + fun visitDisabled(disabled: ContainerNetworkPolicyDisabled): T + + fun visitAllowlist(allowlist: ContainerNetworkPolicyAllowlist): T + + /** + * Maps an unknown variant of [NetworkPolicy] to a value of type [T]. + * + * An instance of [NetworkPolicy] can contain an unknown variant if it + * was deserialized from data that doesn't match any known variant. For + * example, if the SDK is on an older version than the API, then the API + * may respond with new variants that the SDK is unaware of. + * + * @throws OpenAIInvalidDataException in the default implementation. + */ + fun unknown(json: JsonValue?): T { + throw OpenAIInvalidDataException("Unknown NetworkPolicy") + } + } + + internal class Deserializer : + BaseDeserializer(NetworkPolicy::class) { + + override fun ObjectCodec.deserialize(node: JsonNode): NetworkPolicy { + val json = JsonValue.fromJsonNode(node) + val type = + json + .asObject() + .getOrNull() + ?.get("type") + ?.asString() + ?.getOrNull() + + when (type) { + "disabled" -> { + return tryDeserialize( + node, + jacksonTypeRef(), + ) + ?.let { NetworkPolicy(disabled = it, _json = json) } + ?: NetworkPolicy(_json = json) + } + "allowlist" -> { + return tryDeserialize( + node, + jacksonTypeRef(), + ) + ?.let { NetworkPolicy(allowlist = it, _json = json) } + ?: NetworkPolicy(_json = json) + } + } + + return NetworkPolicy(_json = json) + } + } + + internal class Serializer : + BaseSerializer(NetworkPolicy::class) { + + override fun serialize( + value: NetworkPolicy, + generator: JsonGenerator, + provider: SerializerProvider, + ) { + when { + value.disabled != null -> generator.writeObject(value.disabled) + value.allowlist != null -> + generator.writeObject(value.allowlist) + value._json != null -> generator.writeObject(value._json) + else -> throw IllegalStateException("Invalid NetworkPolicy") + } + } + } + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is CodeInterpreterToolAuto && + type == other.type && + fileIds == other.fileIds && + memoryLimit == other.memoryLimit && + networkPolicy == other.networkPolicy && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash( + type, + fileIds, + memoryLimit, + networkPolicy, + additionalProperties, + ) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "CodeInterpreterToolAuto{type=$type, fileIds=$fileIds, memoryLimit=$memoryLimit, networkPolicy=$networkPolicy, additionalProperties=$additionalProperties}" + } + } + + class AllowedCaller + @JsonCreator + private constructor(private val value: JsonField) : Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that + * doesn't match any known member, and you want to know that value. For example, if + * the SDK is on an older version than the API, then the API may respond with new + * members that the SDK is unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val DIRECT = of("direct") + + @JvmField val PROGRAMMATIC = of("programmatic") + + @JvmStatic fun of(value: String) = AllowedCaller(JsonField.of(value)) + } + + /** An enum containing [AllowedCaller]'s known values. */ + enum class Known { + DIRECT, + PROGRAMMATIC, + } + + /** + * An enum containing [AllowedCaller]'s known values, as well as an [_UNKNOWN] + * member. + * + * An instance of [AllowedCaller] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, + * if the SDK is on an older version than the API, then the API may respond with + * new members that the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + DIRECT, + PROGRAMMATIC, + /** + * An enum member indicating that [AllowedCaller] was instantiated with an + * unknown value. + */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or + * [Value._UNKNOWN] if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if + * you want to throw for the unknown case. + */ + fun value(): Value = + when (this) { + DIRECT -> Value.DIRECT + PROGRAMMATIC -> Value.PROGRAMMATIC + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and + * don't want to throw for the unknown case. + * + * @throws OpenAIInvalidDataException if this class instance's value is a not a + * known member. + */ + fun known(): Known = + when (this) { + DIRECT -> Known.DIRECT + PROGRAMMATIC -> Known.PROGRAMMATIC + else -> throw OpenAIInvalidDataException("Unknown AllowedCaller: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for + * debugging and generally doesn't throw. + * + * @throws OpenAIInvalidDataException if this class instance's value does not have + * the expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { + OpenAIInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws OpenAIInvalidDataException if any value type in this object doesn't match + * its expected type. + */ + fun validate(): AllowedCaller = apply { + if (validated) { + return@apply + } + + known() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: OpenAIInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is AllowedCaller && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is CodeInterpreter && + container == other.container && + type == other.type && + allowedCallers == other.allowedCallers && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(container, type, allowedCallers, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "CodeInterpreter{container=$container, type=$type, allowedCallers=$allowedCallers, additionalProperties=$additionalProperties}" + } + + /** A tool that generates images using the GPT image models. */ + class ImageGeneration + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val type: JsonValue, + private val action: JsonField, + private val background: JsonField, + private val inputFidelity: JsonField, + private val inputImageMask: JsonField, + private val model: JsonField, + private val moderation: JsonField, + private val outputCompression: JsonField, + private val outputFormat: JsonField, + private val partialImages: JsonField, + private val quality: JsonField, + private val size: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("type") @ExcludeMissing type: JsonValue = JsonMissing.of(), + @JsonProperty("action") + @ExcludeMissing + action: JsonField = JsonMissing.of(), + @JsonProperty("background") + @ExcludeMissing + background: JsonField = JsonMissing.of(), + @JsonProperty("input_fidelity") + @ExcludeMissing + inputFidelity: JsonField = JsonMissing.of(), + @JsonProperty("input_image_mask") + @ExcludeMissing + inputImageMask: JsonField = JsonMissing.of(), + @JsonProperty("model") @ExcludeMissing model: JsonField = JsonMissing.of(), + @JsonProperty("moderation") + @ExcludeMissing + moderation: JsonField = JsonMissing.of(), + @JsonProperty("output_compression") + @ExcludeMissing + outputCompression: JsonField = JsonMissing.of(), + @JsonProperty("output_format") + @ExcludeMissing + outputFormat: JsonField = JsonMissing.of(), + @JsonProperty("partial_images") + @ExcludeMissing + partialImages: JsonField = JsonMissing.of(), + @JsonProperty("quality") + @ExcludeMissing + quality: JsonField = JsonMissing.of(), + @JsonProperty("size") @ExcludeMissing size: JsonField = JsonMissing.of(), + ) : this( + type, + action, + background, + inputFidelity, + inputImageMask, + model, + moderation, + outputCompression, + outputFormat, + partialImages, + quality, + size, + mutableMapOf(), + ) + + /** + * The type of the image generation tool. Always `image_generation`. + * + * Expected to always return the following: + * ```java + * JsonValue.from("image_generation") + * ``` + * + * However, this method can be useful for debugging and logging (e.g. if the server + * responded with an unexpected value). + */ + @JsonProperty("type") @ExcludeMissing fun _type(): JsonValue = type + + /** + * Whether to generate a new image or edit an existing image. Default: `auto`. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun action(): Optional = action.getOptional("action") + + /** + * Allows to set transparency for the background of the generated image(s). Must be one + * of `transparent`, `opaque`, or `auto` (default value). When `auto` is used, the model + * will automatically determine the best background for the image. + * + * `gpt-image-2.5-sunburst` and `gpt-image-2.5-flare`, including their `2026-09-08` + * snapshots, support `opaque` and `transparent` backgrounds. Transparent backgrounds + * are available for supported GPT Image models. For `gpt-image-2` and + * `gpt-image-2-2026-04-21`, this support is in preview. When using `transparent`, set + * the output format to `png` or `webp`. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun background(): Optional = background.getOptional("background") + + /** + * Control how much effort the model will exert to match the style and features, + * especially facial features, of input images. Supports `high` and `low` on + * `gpt-image-1` and `gpt-image-1.5`; `gpt-image-1-mini` supports only `low`. For + * `gpt-image-2`, omit this parameter. Defaults to `low` on supported models. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun inputFidelity(): Optional = + inputFidelity.getOptional("input_fidelity") + + /** + * Optional mask for inpainting. Contains `image_url` (string, optional) and `file_id` + * (string, optional). + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun inputImageMask(): Optional = + inputImageMask.getOptional("input_image_mask") + + /** + * The image generation model to use. One of `gpt-image-1`, `gpt-image-1-mini`, + * `gpt-image-1.5`, `gpt-image-2`, `gpt-image-2-2026-04-21`, `gpt-image-2.5-sunburst`, + * `gpt-image-2.5-sunburst-2026-09-08`, `gpt-image-2.5-flare`, + * `gpt-image-2.5-flare-2026-09-08`, or `chatgpt-image-latest`. Default: `gpt-image-1`. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun model(): Optional = model.getOptional("model") + + /** + * Moderation level for the generated image. Default: `auto`. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun moderation(): Optional = moderation.getOptional("moderation") + + /** + * Compression level for the output image. Default: 100. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun outputCompression(): Optional = + outputCompression.getOptional("output_compression") + + /** + * The output format of the generated image. One of `png`, `webp`, or `jpeg`. Default: + * `png`. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun outputFormat(): Optional = outputFormat.getOptional("output_format") + + /** + * Number of partial images to generate in streaming mode, from 0 (default value) to 3. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun partialImages(): Optional = partialImages.getOptional("partial_images") + + /** + * The quality of the generated image. The GPT image models support `low`, `medium`, and + * `high`. `gpt-image-2.5-sunburst` and `gpt-image-2.5-flare`, including their + * `2026-09-08` snapshots, also support `xhigh` and `max`. Default: `auto`. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun quality(): Optional = quality.getOptional("quality") + + /** + * The size of the generated images. For `gpt-image-2`, `gpt-image-2-2026-04-21`, + * `gpt-image-2.5-sunburst`, `gpt-image-2.5-sunburst-2026-09-08`, `gpt-image-2.5-flare`, + * and `gpt-image-2.5-flare-2026-09-08`, arbitrary resolutions are supported as + * `WIDTHxHEIGHT` strings, for example `1536x864`. Width and height must both be + * divisible by 16 and the requested aspect ratio must be between 1:3 and 3:1. + * Resolutions above `2560x1440` are experimental, and the maximum supported resolution + * is `3840x2160`. The requested size must also satisfy the model's current pixel and + * edge limits. The standard sizes `1024x1024`, `1536x1024`, and `1024x1536` are + * supported by the GPT image models; `auto` is supported for models that allow + * automatic sizing. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun size(): Optional = size.getOptional("size") + + /** + * Returns the raw JSON value of [action]. + * + * Unlike [action], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("action") @ExcludeMissing fun _action(): JsonField = action + + /** + * Returns the raw JSON value of [background]. + * + * Unlike [background], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("background") + @ExcludeMissing + fun _background(): JsonField = background + + /** + * Returns the raw JSON value of [inputFidelity]. + * + * Unlike [inputFidelity], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("input_fidelity") + @ExcludeMissing + fun _inputFidelity(): JsonField = inputFidelity + + /** + * Returns the raw JSON value of [inputImageMask]. + * + * Unlike [inputImageMask], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("input_image_mask") + @ExcludeMissing + fun _inputImageMask(): JsonField = inputImageMask + + /** + * Returns the raw JSON value of [model]. + * + * Unlike [model], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("model") @ExcludeMissing fun _model(): JsonField = model + + /** + * Returns the raw JSON value of [moderation]. + * + * Unlike [moderation], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("moderation") + @ExcludeMissing + fun _moderation(): JsonField = moderation + + /** + * Returns the raw JSON value of [outputCompression]. + * + * Unlike [outputCompression], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("output_compression") + @ExcludeMissing + fun _outputCompression(): JsonField = outputCompression + + /** + * Returns the raw JSON value of [outputFormat]. + * + * Unlike [outputFormat], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("output_format") + @ExcludeMissing + fun _outputFormat(): JsonField = outputFormat + + /** + * Returns the raw JSON value of [partialImages]. + * + * Unlike [partialImages], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("partial_images") + @ExcludeMissing + fun _partialImages(): JsonField = partialImages + + /** + * Returns the raw JSON value of [quality]. + * + * Unlike [quality], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("quality") @ExcludeMissing fun _quality(): JsonField = quality + + /** + * Returns the raw JSON value of [size]. + * + * Unlike [size], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("size") @ExcludeMissing fun _size(): JsonField = size + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** Returns a mutable builder for constructing an instance of [ImageGeneration]. */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [ImageGeneration]. */ + class Builder internal constructor() { + + private var type: JsonValue = JsonValue.from("image_generation") + private var action: JsonField = JsonMissing.of() + private var background: JsonField = JsonMissing.of() + private var inputFidelity: JsonField = JsonMissing.of() + private var inputImageMask: JsonField = JsonMissing.of() + private var model: JsonField = JsonMissing.of() + private var moderation: JsonField = JsonMissing.of() + private var outputCompression: JsonField = JsonMissing.of() + private var outputFormat: JsonField = JsonMissing.of() + private var partialImages: JsonField = JsonMissing.of() + private var quality: JsonField = JsonMissing.of() + private var size: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(imageGeneration: ImageGeneration) = apply { + type = imageGeneration.type + action = imageGeneration.action + background = imageGeneration.background + inputFidelity = imageGeneration.inputFidelity + inputImageMask = imageGeneration.inputImageMask + model = imageGeneration.model + moderation = imageGeneration.moderation + outputCompression = imageGeneration.outputCompression + outputFormat = imageGeneration.outputFormat + partialImages = imageGeneration.partialImages + quality = imageGeneration.quality + size = imageGeneration.size + additionalProperties = imageGeneration.additionalProperties.toMutableMap() + } + + /** + * Sets the field to an arbitrary JSON value. + * + * It is usually unnecessary to call this method because the field defaults to the + * following: + * ```java + * JsonValue.from("image_generation") + * ``` + * + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun type(type: JsonValue) = apply { this.type = type } + + /** Whether to generate a new image or edit an existing image. Default: `auto`. */ + fun action(action: Action) = action(JsonField.of(action)) + + /** + * Sets [Builder.action] to an arbitrary JSON value. + * + * You should usually call [Builder.action] with a well-typed [Action] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun action(action: JsonField) = apply { this.action = action } + + /** + * Allows to set transparency for the background of the generated image(s). Must be + * one of `transparent`, `opaque`, or `auto` (default value). When `auto` is used, + * the model will automatically determine the best background for the image. + * + * `gpt-image-2.5-sunburst` and `gpt-image-2.5-flare`, including their `2026-09-08` + * snapshots, support `opaque` and `transparent` backgrounds. Transparent + * backgrounds are available for supported GPT Image models. For `gpt-image-2` and + * `gpt-image-2-2026-04-21`, this support is in preview. When using `transparent`, + * set the output format to `png` or `webp`. + */ + fun background(background: Background) = background(JsonField.of(background)) + + /** + * Sets [Builder.background] to an arbitrary JSON value. + * + * You should usually call [Builder.background] with a well-typed [Background] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun background(background: JsonField) = apply { + this.background = background + } + + /** + * Control how much effort the model will exert to match the style and features, + * especially facial features, of input images. Supports `high` and `low` on + * `gpt-image-1` and `gpt-image-1.5`; `gpt-image-1-mini` supports only `low`. For + * `gpt-image-2`, omit this parameter. Defaults to `low` on supported models. + */ + fun inputFidelity(inputFidelity: InputFidelity?) = + inputFidelity(JsonField.ofNullable(inputFidelity)) + + /** Alias for calling [Builder.inputFidelity] with `inputFidelity.orElse(null)`. */ + fun inputFidelity(inputFidelity: Optional) = + inputFidelity(inputFidelity.getOrNull()) + + /** + * Sets [Builder.inputFidelity] to an arbitrary JSON value. + * + * You should usually call [Builder.inputFidelity] with a well-typed [InputFidelity] + * value instead. This method is primarily for setting the field to an undocumented + * or not yet supported value. + */ + fun inputFidelity(inputFidelity: JsonField) = apply { + this.inputFidelity = inputFidelity + } + + /** + * Optional mask for inpainting. Contains `image_url` (string, optional) and + * `file_id` (string, optional). + */ + fun inputImageMask(inputImageMask: InputImageMask) = + inputImageMask(JsonField.of(inputImageMask)) + + /** + * Sets [Builder.inputImageMask] to an arbitrary JSON value. + * + * You should usually call [Builder.inputImageMask] with a well-typed + * [InputImageMask] value instead. This method is primarily for setting the field to + * an undocumented or not yet supported value. + */ + fun inputImageMask(inputImageMask: JsonField) = apply { + this.inputImageMask = inputImageMask + } + + /** + * The image generation model to use. One of `gpt-image-1`, `gpt-image-1-mini`, + * `gpt-image-1.5`, `gpt-image-2`, `gpt-image-2-2026-04-21`, + * `gpt-image-2.5-sunburst`, `gpt-image-2.5-sunburst-2026-09-08`, + * `gpt-image-2.5-flare`, `gpt-image-2.5-flare-2026-09-08`, or + * `chatgpt-image-latest`. Default: `gpt-image-1`. + */ + fun model(model: Model) = model(JsonField.of(model)) + + /** + * Sets [Builder.model] to an arbitrary JSON value. + * + * You should usually call [Builder.model] with a well-typed [Model] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun model(model: JsonField) = apply { this.model = model } + + /** + * Sets [model] to an arbitrary [String]. + * + * You should usually call [model] with a well-typed [Model] constant instead. This + * method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun model(value: String) = model(Model.of(value)) + + /** Moderation level for the generated image. Default: `auto`. */ + fun moderation(moderation: Moderation) = moderation(JsonField.of(moderation)) + + /** + * Sets [Builder.moderation] to an arbitrary JSON value. + * + * You should usually call [Builder.moderation] with a well-typed [Moderation] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun moderation(moderation: JsonField) = apply { + this.moderation = moderation + } + + /** Compression level for the output image. Default: 100. */ + fun outputCompression(outputCompression: Long) = + outputCompression(JsonField.of(outputCompression)) + + /** + * Sets [Builder.outputCompression] to an arbitrary JSON value. + * + * You should usually call [Builder.outputCompression] with a well-typed [Long] + * value instead. This method is primarily for setting the field to an undocumented + * or not yet supported value. + */ + fun outputCompression(outputCompression: JsonField) = apply { + this.outputCompression = outputCompression + } + + /** + * The output format of the generated image. One of `png`, `webp`, or `jpeg`. + * Default: `png`. + */ + fun outputFormat(outputFormat: OutputFormat) = + outputFormat(JsonField.of(outputFormat)) + + /** + * Sets [Builder.outputFormat] to an arbitrary JSON value. + * + * You should usually call [Builder.outputFormat] with a well-typed [OutputFormat] + * value instead. This method is primarily for setting the field to an undocumented + * or not yet supported value. + */ + fun outputFormat(outputFormat: JsonField) = apply { + this.outputFormat = outputFormat + } + + /** + * Number of partial images to generate in streaming mode, from 0 (default value) + * to 3. + */ + fun partialImages(partialImages: Long) = partialImages(JsonField.of(partialImages)) + + /** + * Sets [Builder.partialImages] to an arbitrary JSON value. + * + * You should usually call [Builder.partialImages] with a well-typed [Long] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun partialImages(partialImages: JsonField) = apply { + this.partialImages = partialImages + } + + /** + * The quality of the generated image. The GPT image models support `low`, `medium`, + * and `high`. `gpt-image-2.5-sunburst` and `gpt-image-2.5-flare`, including their + * `2026-09-08` snapshots, also support `xhigh` and `max`. Default: `auto`. + */ + fun quality(quality: Quality) = quality(JsonField.of(quality)) + + /** + * Sets [Builder.quality] to an arbitrary JSON value. + * + * You should usually call [Builder.quality] with a well-typed [Quality] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun quality(quality: JsonField) = apply { this.quality = quality } + + /** + * The size of the generated images. For `gpt-image-2`, `gpt-image-2-2026-04-21`, + * `gpt-image-2.5-sunburst`, `gpt-image-2.5-sunburst-2026-09-08`, + * `gpt-image-2.5-flare`, and `gpt-image-2.5-flare-2026-09-08`, arbitrary + * resolutions are supported as `WIDTHxHEIGHT` strings, for example `1536x864`. + * Width and height must both be divisible by 16 and the requested aspect ratio must + * be between 1:3 and 3:1. Resolutions above `2560x1440` are experimental, and the + * maximum supported resolution is `3840x2160`. The requested size must also satisfy + * the model's current pixel and edge limits. The standard sizes `1024x1024`, + * `1536x1024`, and `1024x1536` are supported by the GPT image models; `auto` is + * supported for models that allow automatic sizing. + */ + fun size(size: Size) = size(JsonField.of(size)) + + /** + * Sets [Builder.size] to an arbitrary JSON value. + * + * You should usually call [Builder.size] with a well-typed [Size] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun size(size: JsonField) = apply { this.size = size } + + /** + * Sets [size] to an arbitrary [String]. + * + * You should usually call [size] with a well-typed [Size] constant instead. This + * method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun size(value: String) = size(Size.of(value)) + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = + apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { + additionalProperties.remove(key) + } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [ImageGeneration]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): ImageGeneration = + ImageGeneration( + type, + action, + background, + inputFidelity, + inputImageMask, + model, + moderation, + outputCompression, + outputFormat, + partialImages, + quality, + size, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws OpenAIInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): ImageGeneration = apply { + if (validated) { + return@apply + } + + _type().let { + if (it != JsonValue.from("image_generation")) { + throw OpenAIInvalidDataException("'type' is invalid, received $it") + } + } + action().ifPresent { it.validate() } + background().ifPresent { it.validate() } + inputFidelity().ifPresent { it.validate() } + inputImageMask().ifPresent { it.validate() } + model() + moderation().ifPresent { it.validate() } + outputCompression() + outputFormat().ifPresent { it.validate() } + partialImages() + quality().ifPresent { it.validate() } + size() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: OpenAIInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + type.let { if (it == JsonValue.from("image_generation")) 1 else 0 } + + (action.asKnown().getOrNull()?.validity() ?: 0) + + (background.asKnown().getOrNull()?.validity() ?: 0) + + (inputFidelity.asKnown().getOrNull()?.validity() ?: 0) + + (inputImageMask.asKnown().getOrNull()?.validity() ?: 0) + + (if (model.asKnown().isPresent) 1 else 0) + + (moderation.asKnown().getOrNull()?.validity() ?: 0) + + (if (outputCompression.asKnown().isPresent) 1 else 0) + + (outputFormat.asKnown().getOrNull()?.validity() ?: 0) + + (if (partialImages.asKnown().isPresent) 1 else 0) + + (quality.asKnown().getOrNull()?.validity() ?: 0) + + (if (size.asKnown().isPresent) 1 else 0) + + /** Whether to generate a new image or edit an existing image. Default: `auto`. */ + class Action @JsonCreator private constructor(private val value: JsonField) : + Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that + * doesn't match any known member, and you want to know that value. For example, if + * the SDK is on an older version than the API, then the API may respond with new + * members that the SDK is unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val GENERATE = of("generate") + + @JvmField val EDIT = of("edit") + + @JvmField val AUTO = of("auto") + + @JvmStatic fun of(value: String) = Action(JsonField.of(value)) + } + + /** An enum containing [Action]'s known values. */ + enum class Known { + GENERATE, + EDIT, + AUTO, + } + + /** + * An enum containing [Action]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [Action] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, + * if the SDK is on an older version than the API, then the API may respond with + * new members that the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + GENERATE, + EDIT, + AUTO, + /** + * An enum member indicating that [Action] was instantiated with an unknown + * value. + */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or + * [Value._UNKNOWN] if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if + * you want to throw for the unknown case. + */ + fun value(): Value = + when (this) { + GENERATE -> Value.GENERATE + EDIT -> Value.EDIT + AUTO -> Value.AUTO + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and + * don't want to throw for the unknown case. + * + * @throws OpenAIInvalidDataException if this class instance's value is a not a + * known member. + */ + fun known(): Known = + when (this) { + GENERATE -> Known.GENERATE + EDIT -> Known.EDIT + AUTO -> Known.AUTO + else -> throw OpenAIInvalidDataException("Unknown Action: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for + * debugging and generally doesn't throw. + * + * @throws OpenAIInvalidDataException if this class instance's value does not have + * the expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { + OpenAIInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws OpenAIInvalidDataException if any value type in this object doesn't match + * its expected type. + */ + fun validate(): Action = apply { + if (validated) { + return@apply + } + + known() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: OpenAIInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Action && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + /** + * Allows to set transparency for the background of the generated image(s). Must be one + * of `transparent`, `opaque`, or `auto` (default value). When `auto` is used, the model + * will automatically determine the best background for the image. + * + * `gpt-image-2.5-sunburst` and `gpt-image-2.5-flare`, including their `2026-09-08` + * snapshots, support `opaque` and `transparent` backgrounds. Transparent backgrounds + * are available for supported GPT Image models. For `gpt-image-2` and + * `gpt-image-2-2026-04-21`, this support is in preview. When using `transparent`, set + * the output format to `png` or `webp`. + */ + class Background + @JsonCreator + private constructor(private val value: JsonField) : Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that + * doesn't match any known member, and you want to know that value. For example, if + * the SDK is on an older version than the API, then the API may respond with new + * members that the SDK is unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val TRANSPARENT = of("transparent") + + @JvmField val OPAQUE = of("opaque") + + @JvmField val AUTO = of("auto") + + @JvmStatic fun of(value: String) = Background(JsonField.of(value)) + } + + /** An enum containing [Background]'s known values. */ + enum class Known { + TRANSPARENT, + OPAQUE, + AUTO, + } + + /** + * An enum containing [Background]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [Background] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, + * if the SDK is on an older version than the API, then the API may respond with + * new members that the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + TRANSPARENT, + OPAQUE, + AUTO, + /** + * An enum member indicating that [Background] was instantiated with an unknown + * value. + */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or + * [Value._UNKNOWN] if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if + * you want to throw for the unknown case. + */ + fun value(): Value = + when (this) { + TRANSPARENT -> Value.TRANSPARENT + OPAQUE -> Value.OPAQUE + AUTO -> Value.AUTO + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and + * don't want to throw for the unknown case. + * + * @throws OpenAIInvalidDataException if this class instance's value is a not a + * known member. + */ + fun known(): Known = + when (this) { + TRANSPARENT -> Known.TRANSPARENT + OPAQUE -> Known.OPAQUE + AUTO -> Known.AUTO + else -> throw OpenAIInvalidDataException("Unknown Background: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for + * debugging and generally doesn't throw. + * + * @throws OpenAIInvalidDataException if this class instance's value does not have + * the expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { + OpenAIInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws OpenAIInvalidDataException if any value type in this object doesn't match + * its expected type. + */ + fun validate(): Background = apply { + if (validated) { + return@apply + } + + known() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: OpenAIInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Background && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + /** + * Control how much effort the model will exert to match the style and features, + * especially facial features, of input images. Supports `high` and `low` on + * `gpt-image-1` and `gpt-image-1.5`; `gpt-image-1-mini` supports only `low`. For + * `gpt-image-2`, omit this parameter. Defaults to `low` on supported models. + */ + class InputFidelity + @JsonCreator + private constructor(private val value: JsonField) : Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that + * doesn't match any known member, and you want to know that value. For example, if + * the SDK is on an older version than the API, then the API may respond with new + * members that the SDK is unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val HIGH = of("high") + + @JvmField val LOW = of("low") + + @JvmStatic fun of(value: String) = InputFidelity(JsonField.of(value)) + } + + /** An enum containing [InputFidelity]'s known values. */ + enum class Known { + HIGH, + LOW, + } + + /** + * An enum containing [InputFidelity]'s known values, as well as an [_UNKNOWN] + * member. + * + * An instance of [InputFidelity] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, + * if the SDK is on an older version than the API, then the API may respond with + * new members that the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + HIGH, + LOW, + /** + * An enum member indicating that [InputFidelity] was instantiated with an + * unknown value. + */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or + * [Value._UNKNOWN] if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if + * you want to throw for the unknown case. + */ + fun value(): Value = + when (this) { + HIGH -> Value.HIGH + LOW -> Value.LOW + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and + * don't want to throw for the unknown case. + * + * @throws OpenAIInvalidDataException if this class instance's value is a not a + * known member. + */ + fun known(): Known = + when (this) { + HIGH -> Known.HIGH + LOW -> Known.LOW + else -> throw OpenAIInvalidDataException("Unknown InputFidelity: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for + * debugging and generally doesn't throw. + * + * @throws OpenAIInvalidDataException if this class instance's value does not have + * the expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { + OpenAIInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws OpenAIInvalidDataException if any value type in this object doesn't match + * its expected type. + */ + fun validate(): InputFidelity = apply { + if (validated) { + return@apply + } + + known() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: OpenAIInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is InputFidelity && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + /** + * Optional mask for inpainting. Contains `image_url` (string, optional) and `file_id` + * (string, optional). + */ + class InputImageMask + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val fileId: JsonField, + private val imageUrl: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("file_id") + @ExcludeMissing + fileId: JsonField = JsonMissing.of(), + @JsonProperty("image_url") + @ExcludeMissing + imageUrl: JsonField = JsonMissing.of(), + ) : this(fileId, imageUrl, mutableMapOf()) + + /** + * File ID for the mask image. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. + * if the server responded with an unexpected value). + */ + fun fileId(): Optional = fileId.getOptional("file_id") + + /** + * Base64-encoded mask image. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. + * if the server responded with an unexpected value). + */ + fun imageUrl(): Optional = imageUrl.getOptional("image_url") + + /** + * Returns the raw JSON value of [fileId]. + * + * Unlike [fileId], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("file_id") @ExcludeMissing fun _fileId(): JsonField = fileId + + /** + * Returns the raw JSON value of [imageUrl]. + * + * Unlike [imageUrl], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("image_url") + @ExcludeMissing + fun _imageUrl(): JsonField = imageUrl + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [InputImageMask]. + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [InputImageMask]. */ + class Builder internal constructor() { + + private var fileId: JsonField = JsonMissing.of() + private var imageUrl: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(inputImageMask: InputImageMask) = apply { + fileId = inputImageMask.fileId + imageUrl = inputImageMask.imageUrl + additionalProperties = inputImageMask.additionalProperties.toMutableMap() + } + + /** File ID for the mask image. */ + fun fileId(fileId: String) = fileId(JsonField.of(fileId)) + + /** + * Sets [Builder.fileId] to an arbitrary JSON value. + * + * You should usually call [Builder.fileId] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or + * not yet supported value. + */ + fun fileId(fileId: JsonField) = apply { this.fileId = fileId } + + /** Base64-encoded mask image. */ + fun imageUrl(imageUrl: String) = imageUrl(JsonField.of(imageUrl)) + + /** + * Sets [Builder.imageUrl] to an arbitrary JSON value. + * + * You should usually call [Builder.imageUrl] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or + * not yet supported value. + */ + fun imageUrl(imageUrl: JsonField) = apply { this.imageUrl = imageUrl } + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = + apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { + additionalProperties.remove(key) + } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [InputImageMask]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): InputImageMask = + InputImageMask(fileId, imageUrl, additionalProperties.toMutableMap()) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws OpenAIInvalidDataException if any value type in this object doesn't match + * its expected type. + */ + fun validate(): InputImageMask = apply { + if (validated) { + return@apply + } + + fileId() + imageUrl() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: OpenAIInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + (if (fileId.asKnown().isPresent) 1 else 0) + + (if (imageUrl.asKnown().isPresent) 1 else 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is InputImageMask && + fileId == other.fileId && + imageUrl == other.imageUrl && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(fileId, imageUrl, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "InputImageMask{fileId=$fileId, imageUrl=$imageUrl, additionalProperties=$additionalProperties}" + } + + /** + * The image generation model to use. One of `gpt-image-1`, `gpt-image-1-mini`, + * `gpt-image-1.5`, `gpt-image-2`, `gpt-image-2-2026-04-21`, `gpt-image-2.5-sunburst`, + * `gpt-image-2.5-sunburst-2026-09-08`, `gpt-image-2.5-flare`, + * `gpt-image-2.5-flare-2026-09-08`, or `chatgpt-image-latest`. Default: `gpt-image-1`. + */ + class Model @JsonCreator private constructor(private val value: JsonField) : + Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that + * doesn't match any known member, and you want to know that value. For example, if + * the SDK is on an older version than the API, then the API may respond with new + * members that the SDK is unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val GPT_IMAGE_1 = of("gpt-image-1") + + @JvmField val GPT_IMAGE_1_MINI = of("gpt-image-1-mini") + + @JvmField val GPT_IMAGE_2 = of("gpt-image-2") + + @JvmField val GPT_IMAGE_2_2026_04_21 = of("gpt-image-2-2026-04-21") + + @JvmField val GPT_IMAGE_2_5_SUNBURST = of("gpt-image-2.5-sunburst") + + @JvmField + val GPT_IMAGE_2_5_SUNBURST_2026_09_08 = of("gpt-image-2.5-sunburst-2026-09-08") + + @JvmField val GPT_IMAGE_2_5_FLARE = of("gpt-image-2.5-flare") + + @JvmField + val GPT_IMAGE_2_5_FLARE_2026_09_08 = of("gpt-image-2.5-flare-2026-09-08") + + @JvmField val GPT_IMAGE_1_5 = of("gpt-image-1.5") + + @JvmField val CHATGPT_IMAGE_LATEST = of("chatgpt-image-latest") + + @JvmStatic fun of(value: String) = Model(JsonField.of(value)) + } + + /** An enum containing [Model]'s known values. */ + enum class Known { + GPT_IMAGE_1, + GPT_IMAGE_1_MINI, + GPT_IMAGE_2, + GPT_IMAGE_2_2026_04_21, + GPT_IMAGE_2_5_SUNBURST, + GPT_IMAGE_2_5_SUNBURST_2026_09_08, + GPT_IMAGE_2_5_FLARE, + GPT_IMAGE_2_5_FLARE_2026_09_08, + GPT_IMAGE_1_5, + CHATGPT_IMAGE_LATEST, + } + + /** + * An enum containing [Model]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [Model] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, + * if the SDK is on an older version than the API, then the API may respond with + * new members that the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + GPT_IMAGE_1, + GPT_IMAGE_1_MINI, + GPT_IMAGE_2, + GPT_IMAGE_2_2026_04_21, + GPT_IMAGE_2_5_SUNBURST, + GPT_IMAGE_2_5_SUNBURST_2026_09_08, + GPT_IMAGE_2_5_FLARE, + GPT_IMAGE_2_5_FLARE_2026_09_08, + GPT_IMAGE_1_5, + CHATGPT_IMAGE_LATEST, + /** + * An enum member indicating that [Model] was instantiated with an unknown + * value. + */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or + * [Value._UNKNOWN] if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if + * you want to throw for the unknown case. + */ + fun value(): Value = + when (this) { + GPT_IMAGE_1 -> Value.GPT_IMAGE_1 + GPT_IMAGE_1_MINI -> Value.GPT_IMAGE_1_MINI + GPT_IMAGE_2 -> Value.GPT_IMAGE_2 + GPT_IMAGE_2_2026_04_21 -> Value.GPT_IMAGE_2_2026_04_21 + GPT_IMAGE_2_5_SUNBURST -> Value.GPT_IMAGE_2_5_SUNBURST + GPT_IMAGE_2_5_SUNBURST_2026_09_08 -> Value.GPT_IMAGE_2_5_SUNBURST_2026_09_08 + GPT_IMAGE_2_5_FLARE -> Value.GPT_IMAGE_2_5_FLARE + GPT_IMAGE_2_5_FLARE_2026_09_08 -> Value.GPT_IMAGE_2_5_FLARE_2026_09_08 + GPT_IMAGE_1_5 -> Value.GPT_IMAGE_1_5 + CHATGPT_IMAGE_LATEST -> Value.CHATGPT_IMAGE_LATEST + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and + * don't want to throw for the unknown case. + * + * @throws OpenAIInvalidDataException if this class instance's value is a not a + * known member. + */ + fun known(): Known = + when (this) { + GPT_IMAGE_1 -> Known.GPT_IMAGE_1 + GPT_IMAGE_1_MINI -> Known.GPT_IMAGE_1_MINI + GPT_IMAGE_2 -> Known.GPT_IMAGE_2 + GPT_IMAGE_2_2026_04_21 -> Known.GPT_IMAGE_2_2026_04_21 + GPT_IMAGE_2_5_SUNBURST -> Known.GPT_IMAGE_2_5_SUNBURST + GPT_IMAGE_2_5_SUNBURST_2026_09_08 -> Known.GPT_IMAGE_2_5_SUNBURST_2026_09_08 + GPT_IMAGE_2_5_FLARE -> Known.GPT_IMAGE_2_5_FLARE + GPT_IMAGE_2_5_FLARE_2026_09_08 -> Known.GPT_IMAGE_2_5_FLARE_2026_09_08 + GPT_IMAGE_1_5 -> Known.GPT_IMAGE_1_5 + CHATGPT_IMAGE_LATEST -> Known.CHATGPT_IMAGE_LATEST + else -> throw OpenAIInvalidDataException("Unknown Model: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for + * debugging and generally doesn't throw. + * + * @throws OpenAIInvalidDataException if this class instance's value does not have + * the expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { + OpenAIInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws OpenAIInvalidDataException if any value type in this object doesn't match + * its expected type. + */ + fun validate(): Model = apply { + if (validated) { + return@apply + } + + known() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: OpenAIInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Model && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + /** Moderation level for the generated image. Default: `auto`. */ + class Moderation + @JsonCreator + private constructor(private val value: JsonField) : Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that + * doesn't match any known member, and you want to know that value. For example, if + * the SDK is on an older version than the API, then the API may respond with new + * members that the SDK is unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val AUTO = of("auto") + + @JvmField val LOW = of("low") + + @JvmStatic fun of(value: String) = Moderation(JsonField.of(value)) + } + + /** An enum containing [Moderation]'s known values. */ + enum class Known { + AUTO, + LOW, + } + + /** + * An enum containing [Moderation]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [Moderation] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, + * if the SDK is on an older version than the API, then the API may respond with + * new members that the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + AUTO, + LOW, + /** + * An enum member indicating that [Moderation] was instantiated with an unknown + * value. + */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or + * [Value._UNKNOWN] if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if + * you want to throw for the unknown case. + */ + fun value(): Value = + when (this) { + AUTO -> Value.AUTO + LOW -> Value.LOW + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and + * don't want to throw for the unknown case. + * + * @throws OpenAIInvalidDataException if this class instance's value is a not a + * known member. + */ + fun known(): Known = + when (this) { + AUTO -> Known.AUTO + LOW -> Known.LOW + else -> throw OpenAIInvalidDataException("Unknown Moderation: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for + * debugging and generally doesn't throw. + * + * @throws OpenAIInvalidDataException if this class instance's value does not have + * the expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { + OpenAIInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws OpenAIInvalidDataException if any value type in this object doesn't match + * its expected type. + */ + fun validate(): Moderation = apply { + if (validated) { + return@apply + } + + known() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: OpenAIInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Moderation && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + /** + * The output format of the generated image. One of `png`, `webp`, or `jpeg`. Default: + * `png`. + */ + class OutputFormat + @JsonCreator + private constructor(private val value: JsonField) : Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that + * doesn't match any known member, and you want to know that value. For example, if + * the SDK is on an older version than the API, then the API may respond with new + * members that the SDK is unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val PNG = of("png") + + @JvmField val WEBP = of("webp") + + @JvmField val JPEG = of("jpeg") + + @JvmStatic fun of(value: String) = OutputFormat(JsonField.of(value)) + } + + /** An enum containing [OutputFormat]'s known values. */ + enum class Known { + PNG, + WEBP, + JPEG, + } + + /** + * An enum containing [OutputFormat]'s known values, as well as an [_UNKNOWN] + * member. + * + * An instance of [OutputFormat] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, + * if the SDK is on an older version than the API, then the API may respond with + * new members that the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + PNG, + WEBP, + JPEG, + /** + * An enum member indicating that [OutputFormat] was instantiated with an + * unknown value. + */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or + * [Value._UNKNOWN] if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if + * you want to throw for the unknown case. + */ + fun value(): Value = + when (this) { + PNG -> Value.PNG + WEBP -> Value.WEBP + JPEG -> Value.JPEG + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and + * don't want to throw for the unknown case. + * + * @throws OpenAIInvalidDataException if this class instance's value is a not a + * known member. + */ + fun known(): Known = + when (this) { + PNG -> Known.PNG + WEBP -> Known.WEBP + JPEG -> Known.JPEG + else -> throw OpenAIInvalidDataException("Unknown OutputFormat: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for + * debugging and generally doesn't throw. + * + * @throws OpenAIInvalidDataException if this class instance's value does not have + * the expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { + OpenAIInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws OpenAIInvalidDataException if any value type in this object doesn't match + * its expected type. + */ + fun validate(): OutputFormat = apply { + if (validated) { + return@apply + } + + known() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: OpenAIInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is OutputFormat && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + /** + * The quality of the generated image. The GPT image models support `low`, `medium`, and + * `high`. `gpt-image-2.5-sunburst` and `gpt-image-2.5-flare`, including their + * `2026-09-08` snapshots, also support `xhigh` and `max`. Default: `auto`. + */ + class Quality @JsonCreator private constructor(private val value: JsonField) : + Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that + * doesn't match any known member, and you want to know that value. For example, if + * the SDK is on an older version than the API, then the API may respond with new + * members that the SDK is unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val LOW = of("low") + + @JvmField val MEDIUM = of("medium") + + @JvmField val HIGH = of("high") + + @JvmField val XHIGH = of("xhigh") + + @JvmField val MAX = of("max") + + @JvmField val AUTO = of("auto") + + @JvmStatic fun of(value: String) = Quality(JsonField.of(value)) + } + + /** An enum containing [Quality]'s known values. */ + enum class Known { + LOW, + MEDIUM, + HIGH, + XHIGH, + MAX, + AUTO, + } + + /** + * An enum containing [Quality]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [Quality] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, + * if the SDK is on an older version than the API, then the API may respond with + * new members that the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + LOW, + MEDIUM, + HIGH, + XHIGH, + MAX, + AUTO, + /** + * An enum member indicating that [Quality] was instantiated with an unknown + * value. + */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or + * [Value._UNKNOWN] if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if + * you want to throw for the unknown case. + */ + fun value(): Value = + when (this) { + LOW -> Value.LOW + MEDIUM -> Value.MEDIUM + HIGH -> Value.HIGH + XHIGH -> Value.XHIGH + MAX -> Value.MAX + AUTO -> Value.AUTO + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and + * don't want to throw for the unknown case. + * + * @throws OpenAIInvalidDataException if this class instance's value is a not a + * known member. + */ + fun known(): Known = + when (this) { + LOW -> Known.LOW + MEDIUM -> Known.MEDIUM + HIGH -> Known.HIGH + XHIGH -> Known.XHIGH + MAX -> Known.MAX + AUTO -> Known.AUTO + else -> throw OpenAIInvalidDataException("Unknown Quality: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for + * debugging and generally doesn't throw. + * + * @throws OpenAIInvalidDataException if this class instance's value does not have + * the expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { + OpenAIInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws OpenAIInvalidDataException if any value type in this object doesn't match + * its expected type. + */ + fun validate(): Quality = apply { + if (validated) { + return@apply + } + + known() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: OpenAIInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Quality && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + /** + * The size of the generated images. For `gpt-image-2`, `gpt-image-2-2026-04-21`, + * `gpt-image-2.5-sunburst`, `gpt-image-2.5-sunburst-2026-09-08`, `gpt-image-2.5-flare`, + * and `gpt-image-2.5-flare-2026-09-08`, arbitrary resolutions are supported as + * `WIDTHxHEIGHT` strings, for example `1536x864`. Width and height must both be + * divisible by 16 and the requested aspect ratio must be between 1:3 and 3:1. + * Resolutions above `2560x1440` are experimental, and the maximum supported resolution + * is `3840x2160`. The requested size must also satisfy the model's current pixel and + * edge limits. The standard sizes `1024x1024`, `1536x1024`, and `1024x1536` are + * supported by the GPT image models; `auto` is supported for models that allow + * automatic sizing. + */ + class Size @JsonCreator private constructor(private val value: JsonField) : + Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that + * doesn't match any known member, and you want to know that value. For example, if + * the SDK is on an older version than the API, then the API may respond with new + * members that the SDK is unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val _1024X1024 = of("1024x1024") + + @JvmField val _1024X1536 = of("1024x1536") + + @JvmField val _1536X1024 = of("1536x1024") + + @JvmField val AUTO = of("auto") + + @JvmStatic fun of(value: String) = Size(JsonField.of(value)) + } + + /** An enum containing [Size]'s known values. */ + enum class Known { + _1024X1024, + _1024X1536, + _1536X1024, + AUTO, + } + + /** + * An enum containing [Size]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [Size] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, + * if the SDK is on an older version than the API, then the API may respond with + * new members that the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + _1024X1024, + _1024X1536, + _1536X1024, + AUTO, + /** + * An enum member indicating that [Size] was instantiated with an unknown value. + */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or + * [Value._UNKNOWN] if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if + * you want to throw for the unknown case. + */ + fun value(): Value = + when (this) { + _1024X1024 -> Value._1024X1024 + _1024X1536 -> Value._1024X1536 + _1536X1024 -> Value._1536X1024 + AUTO -> Value.AUTO + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and + * don't want to throw for the unknown case. + * + * @throws OpenAIInvalidDataException if this class instance's value is a not a + * known member. + */ + fun known(): Known = + when (this) { + _1024X1024 -> Known._1024X1024 + _1024X1536 -> Known._1024X1536 + _1536X1024 -> Known._1536X1024 + AUTO -> Known.AUTO + else -> throw OpenAIInvalidDataException("Unknown Size: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for + * debugging and generally doesn't throw. + * + * @throws OpenAIInvalidDataException if this class instance's value does not have + * the expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { + OpenAIInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws OpenAIInvalidDataException if any value type in this object doesn't match + * its expected type. + */ + fun validate(): Size = apply { + if (validated) { + return@apply + } + + known() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: OpenAIInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Size && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is ImageGeneration && + type == other.type && + action == other.action && + background == other.background && + inputFidelity == other.inputFidelity && + inputImageMask == other.inputImageMask && + model == other.model && + moderation == other.moderation && + outputCompression == other.outputCompression && + outputFormat == other.outputFormat && + partialImages == other.partialImages && + quality == other.quality && + size == other.size && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash( + type, + action, + background, + inputFidelity, + inputImageMask, + model, + moderation, + outputCompression, + outputFormat, + partialImages, + quality, + size, + additionalProperties, + ) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "ImageGeneration{type=$type, action=$action, background=$background, inputFidelity=$inputFidelity, inputImageMask=$inputImageMask, model=$model, moderation=$moderation, outputCompression=$outputCompression, outputFormat=$outputFormat, partialImages=$partialImages, quality=$quality, size=$size, additionalProperties=$additionalProperties}" + } + } + /** Whether tool search was executed by the server or by the client. */ class Execution @JsonCreator private constructor(private val value: JsonField) : Enum { diff --git a/openai-java-core/src/main/kotlin/com/openai/models/responses/ToolSearchOutputNamespaceTool.kt b/openai-java-core/src/main/kotlin/com/openai/models/responses/ToolSearchOutputNamespaceTool.kt new file mode 100644 index 000000000..281202a8e --- /dev/null +++ b/openai-java-core/src/main/kotlin/com/openai/models/responses/ToolSearchOutputNamespaceTool.kt @@ -0,0 +1,1381 @@ +// File generated from our OpenAPI spec by Castiron. See CONTRIBUTING.md for details. + +package com.openai.models.responses + +import com.fasterxml.jackson.annotation.JsonAnyGetter +import com.fasterxml.jackson.annotation.JsonAnySetter +import com.fasterxml.jackson.annotation.JsonCreator +import com.fasterxml.jackson.annotation.JsonProperty +import com.fasterxml.jackson.core.JsonGenerator +import com.fasterxml.jackson.core.ObjectCodec +import com.fasterxml.jackson.databind.JsonNode +import com.fasterxml.jackson.databind.SerializerProvider +import com.fasterxml.jackson.databind.annotation.JsonDeserialize +import com.fasterxml.jackson.databind.annotation.JsonSerialize +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import com.openai.core.BaseDeserializer +import com.openai.core.BaseSerializer +import com.openai.core.Enum +import com.openai.core.ExcludeMissing +import com.openai.core.JsonField +import com.openai.core.JsonMissing +import com.openai.core.JsonValue +import com.openai.core.checkKnown +import com.openai.core.checkRequired +import com.openai.core.getOrThrow +import com.openai.core.toImmutable +import com.openai.errors.OpenAIInvalidDataException +import java.util.Collections +import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +/** Groups function/custom tools under a shared namespace. */ +class ToolSearchOutputNamespaceTool +@JsonCreator(mode = JsonCreator.Mode.DISABLED) +private constructor( + private val description: JsonField, + private val name: JsonField, + private val tools: JsonField>, + private val type: JsonValue, + private val additionalProperties: MutableMap, +) { + + @JsonCreator + private constructor( + @JsonProperty("description") + @ExcludeMissing + description: JsonField = JsonMissing.of(), + @JsonProperty("name") @ExcludeMissing name: JsonField = JsonMissing.of(), + @JsonProperty("tools") @ExcludeMissing tools: JsonField> = JsonMissing.of(), + @JsonProperty("type") @ExcludeMissing type: JsonValue = JsonMissing.of(), + ) : this(description, name, tools, type, mutableMapOf()) + + /** + * A description of the namespace shown to the model. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun description(): String = description.getRequired("description") + + /** + * The namespace name used in tool calls (for example, `crm`). + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun name(): String = name.getRequired("name") + + /** + * The function/custom tools loaded inside this namespace. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun tools(): List = tools.getRequired("tools") + + /** + * The type of the tool. Always `namespace`. + * + * Expected to always return the following: + * ```java + * JsonValue.from("namespace") + * ``` + * + * However, this method can be useful for debugging and logging (e.g. if the server responded + * with an unexpected value). + */ + @JsonProperty("type") @ExcludeMissing fun _type(): JsonValue = type + + /** + * Returns the raw JSON value of [description]. + * + * Unlike [description], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("description") @ExcludeMissing fun _description(): JsonField = description + + /** + * Returns the raw JSON value of [name]. + * + * Unlike [name], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("name") @ExcludeMissing fun _name(): JsonField = name + + /** + * Returns the raw JSON value of [tools]. + * + * Unlike [tools], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("tools") @ExcludeMissing fun _tools(): JsonField> = tools + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of + * [ToolSearchOutputNamespaceTool]. + * + * The following fields are required: + * ```java + * .description() + * .name() + * .tools() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [ToolSearchOutputNamespaceTool]. */ + class Builder internal constructor() { + + private var description: JsonField? = null + private var name: JsonField? = null + private var tools: JsonField>? = null + private var type: JsonValue = JsonValue.from("namespace") + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(toolSearchOutputNamespaceTool: ToolSearchOutputNamespaceTool) = apply { + description = toolSearchOutputNamespaceTool.description + name = toolSearchOutputNamespaceTool.name + tools = toolSearchOutputNamespaceTool.tools.map { it.toMutableList() } + type = toolSearchOutputNamespaceTool.type + additionalProperties = toolSearchOutputNamespaceTool.additionalProperties.toMutableMap() + } + + /** A description of the namespace shown to the model. */ + fun description(description: String) = description(JsonField.of(description)) + + /** + * Sets [Builder.description] to an arbitrary JSON value. + * + * You should usually call [Builder.description] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun description(description: JsonField) = apply { this.description = description } + + /** The namespace name used in tool calls (for example, `crm`). */ + fun name(name: String) = name(JsonField.of(name)) + + /** + * Sets [Builder.name] to an arbitrary JSON value. + * + * You should usually call [Builder.name] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun name(name: JsonField) = apply { this.name = name } + + /** The function/custom tools loaded inside this namespace. */ + fun tools(tools: List) = tools(JsonField.of(tools)) + + /** + * Sets [Builder.tools] to an arbitrary JSON value. + * + * You should usually call [Builder.tools] with a well-typed `List` value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun tools(tools: JsonField>) = apply { + this.tools = tools.map { it.toMutableList() } + } + + /** + * Adds a single [Tool] to [tools]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addTool(tool: Tool) = apply { + tools = + (tools ?: JsonField.of(mutableListOf())).also { checkKnown("tools", it).add(tool) } + } + + /** Alias for calling [addTool] with `Tool.ofFunction(function)`. */ + fun addTool(function: Tool.Function) = addTool(Tool.ofFunction(function)) + + /** + * Alias for calling [addTool] with the following: + * ```java + * Tool.Function.builder() + * .name(name) + * .build() + * ``` + */ + fun addFunctionTool(name: String) = addTool(Tool.Function.builder().name(name).build()) + + /** Alias for calling [addTool] with `Tool.ofCustom(custom)`. */ + fun addTool(custom: CustomTool) = addTool(Tool.ofCustom(custom)) + + /** + * Alias for calling [addTool] with the following: + * ```java + * CustomTool.builder() + * .name(name) + * .build() + * ``` + */ + fun addCustomTool(name: String) = addTool(CustomTool.builder().name(name).build()) + + /** + * Sets the field to an arbitrary JSON value. + * + * It is usually unnecessary to call this method because the field defaults to the + * following: + * ```java + * JsonValue.from("namespace") + * ``` + * + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun type(type: JsonValue) = apply { this.type = type } + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { additionalProperties.remove(key) } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [ToolSearchOutputNamespaceTool]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .description() + * .name() + * .tools() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): ToolSearchOutputNamespaceTool = + ToolSearchOutputNamespaceTool( + checkRequired("description", description), + checkRequired("name", name), + checkRequired("tools", tools).map { it.toImmutable() }, + type, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws OpenAIInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): ToolSearchOutputNamespaceTool = apply { + if (validated) { + return@apply + } + + description() + name() + tools().forEach { it.validate() } + _type().let { + if (it != JsonValue.from("namespace")) { + throw OpenAIInvalidDataException("'type' is invalid, received $it") + } + } + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: OpenAIInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + (if (description.asKnown().isPresent) 1 else 0) + + (if (name.asKnown().isPresent) 1 else 0) + + (tools.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + + type.let { if (it == JsonValue.from("namespace")) 1 else 0 } + + /** A function or custom tool loaded into a namespace by tool search. */ + @JsonDeserialize(using = Tool.Deserializer::class) + @JsonSerialize(using = Tool.Serializer::class) + class Tool + private constructor( + private val function: Function? = null, + private val custom: CustomTool? = null, + private val _json: JsonValue? = null, + ) { + + fun function(): Optional = Optional.ofNullable(function) + + /** + * A custom tool that processes input using a specified format. Learn more about + * [custom tools](https://developers.openai.com/api/docs/guides/function-calling#custom-tools) + */ + fun custom(): Optional = Optional.ofNullable(custom) + + fun isFunction(): Boolean = function != null + + fun isCustom(): Boolean = custom != null + + fun asFunction(): Function = function.getOrThrow("function") + + /** + * A custom tool that processes input using a specified format. Learn more about + * [custom tools](https://developers.openai.com/api/docs/guides/function-calling#custom-tools) + */ + fun asCustom(): CustomTool = custom.getOrThrow("custom") + + fun _json(): Optional = Optional.ofNullable(_json) + + /** + * Maps this instance's current variant to a value of type [T] using the given [visitor]. + * + * Note that this method is _not_ forwards compatible with new variants from the API, unless + * [visitor] overrides [Visitor.unknown]. To handle variants not known to this version of + * the SDK gracefully, consider overriding [Visitor.unknown]: + * ```java + * import com.openai.core.JsonValue; + * import java.util.Optional; + * + * Optional result = tool.accept(new Tool.Visitor>() { + * @Override + * public Optional visitFunction(Function function) { + * return Optional.of(function.toString()); + * } + * + * // ... + * + * @Override + * public Optional unknown(JsonValue json) { + * // Or inspect the `json`. + * return Optional.empty(); + * } + * }); + * ``` + * + * @throws OpenAIInvalidDataException if [Visitor.unknown] is not overridden in [visitor] + * and the current variant is unknown. + */ + fun accept(visitor: Visitor): T = + when { + function != null -> visitor.visitFunction(function) + custom != null -> visitor.visitCustom(custom) + else -> visitor.unknown(_json) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws OpenAIInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): Tool = apply { + if (validated) { + return@apply + } + + accept( + object : Visitor { + override fun visitFunction(function: Function) { + function.validate() + } + + override fun visitCustom(custom: CustomTool) { + custom.validate() + } + } + ) + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: OpenAIInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + accept( + object : Visitor { + override fun visitFunction(function: Function) = function.validity() + + override fun visitCustom(custom: CustomTool) = custom.validity() + + override fun unknown(json: JsonValue?) = 0 + } + ) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Tool && function == other.function && custom == other.custom + } + + override fun hashCode(): Int = Objects.hash(function, custom) + + override fun toString(): String = + when { + function != null -> "Tool{function=$function}" + custom != null -> "Tool{custom=$custom}" + _json != null -> "Tool{_unknown=$_json}" + else -> throw IllegalStateException("Invalid Tool") + } + + companion object { + + @JvmStatic fun ofFunction(function: Function) = Tool(function = function) + + /** + * A custom tool that processes input using a specified format. Learn more about + * [custom tools](https://developers.openai.com/api/docs/guides/function-calling#custom-tools) + */ + @JvmStatic fun ofCustom(custom: CustomTool) = Tool(custom = custom) + } + + /** An interface that defines how to map each variant of [Tool] to a value of type [T]. */ + interface Visitor { + + fun visitFunction(function: Function): T + + /** + * A custom tool that processes input using a specified format. Learn more about + * [custom tools](https://developers.openai.com/api/docs/guides/function-calling#custom-tools) + */ + fun visitCustom(custom: CustomTool): T + + /** + * Maps an unknown variant of [Tool] to a value of type [T]. + * + * An instance of [Tool] can contain an unknown variant if it was deserialized from data + * that doesn't match any known variant. For example, if the SDK is on an older version + * than the API, then the API may respond with new variants that the SDK is unaware of. + * + * @throws OpenAIInvalidDataException in the default implementation. + */ + fun unknown(json: JsonValue?): T { + throw OpenAIInvalidDataException("Unknown Tool") + } + } + + internal class Deserializer : BaseDeserializer(Tool::class) { + + override fun ObjectCodec.deserialize(node: JsonNode): Tool { + val json = JsonValue.fromJsonNode(node) + val type = json.asObject().getOrNull()?.get("type")?.asString()?.getOrNull() + + when (type) { + "function" -> { + return tryDeserialize(node, jacksonTypeRef())?.let { + Tool(function = it, _json = json) + } ?: Tool(_json = json) + } + "custom" -> { + return tryDeserialize(node, jacksonTypeRef())?.let { + Tool(custom = it, _json = json) + } ?: Tool(_json = json) + } + } + + return Tool(_json = json) + } + } + + internal class Serializer : BaseSerializer(Tool::class) { + + override fun serialize( + value: Tool, + generator: JsonGenerator, + provider: SerializerProvider, + ) { + when { + value.function != null -> generator.writeObject(value.function) + value.custom != null -> generator.writeObject(value.custom) + value._json != null -> generator.writeObject(value._json) + else -> throw IllegalStateException("Invalid Tool") + } + } + } + + class Function + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val name: JsonField, + private val type: JsonValue, + private val allowedCallers: JsonField>, + private val async: JsonField, + private val deferLoading: JsonField, + private val description: JsonField, + private val outputSchema: JsonField, + private val parameters: JsonValue, + private val strict: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("name") @ExcludeMissing name: JsonField = JsonMissing.of(), + @JsonProperty("type") @ExcludeMissing type: JsonValue = JsonMissing.of(), + @JsonProperty("allowed_callers") + @ExcludeMissing + allowedCallers: JsonField> = JsonMissing.of(), + @JsonProperty("async") @ExcludeMissing async: JsonField = JsonMissing.of(), + @JsonProperty("defer_loading") + @ExcludeMissing + deferLoading: JsonField = JsonMissing.of(), + @JsonProperty("description") + @ExcludeMissing + description: JsonField = JsonMissing.of(), + @JsonProperty("output_schema") + @ExcludeMissing + outputSchema: JsonField = JsonMissing.of(), + @JsonProperty("parameters") + @ExcludeMissing + parameters: JsonValue = JsonMissing.of(), + @JsonProperty("strict") + @ExcludeMissing + strict: JsonField = JsonMissing.of(), + ) : this( + name, + type, + allowedCallers, + async, + deferLoading, + description, + outputSchema, + parameters, + strict, + mutableMapOf(), + ) + + /** + * The name of the loaded function tool. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected + * value). + */ + fun name(): String = name.getRequired("name") + + /** + * Expected to always return the following: + * ```java + * JsonValue.from("function") + * ``` + * + * However, this method can be useful for debugging and logging (e.g. if the server + * responded with an unexpected value). + */ + @JsonProperty("type") @ExcludeMissing fun _type(): JsonValue = type + + /** + * The tool invocation context(s). + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun allowedCallers(): Optional> = + allowedCallers.getOptional("allowed_callers") + + /** + * Whether the tool response can be returned asynchronously versus immediately returned + * on next response creation. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun async(): Optional = async.getOptional("async") + + /** + * Whether this function should be deferred and discovered via tool search. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun deferLoading(): Optional = deferLoading.getOptional("defer_loading") + + /** + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun description(): Optional = description.getOptional("description") + + /** + * A JSON Schema describing the JSON value encoded in string outputs for this function + * tool. This does not describe content-array outputs. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun outputSchema(): Optional = outputSchema.getOptional("output_schema") + + /** + * This arbitrary value can be deserialized into a custom type using the `convert` + * method: + * ```java + * MyClass myObject = function.parameters().convert(MyClass.class); + * ``` + */ + @JsonProperty("parameters") @ExcludeMissing fun _parameters(): JsonValue = parameters + + /** + * Whether to enforce strict parameter validation. If omitted, Responses attempts to use + * strict validation when the schema is compatible, and falls back to non-strict + * validation otherwise. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun strict(): Optional = strict.getOptional("strict") + + /** + * Returns the raw JSON value of [name]. + * + * Unlike [name], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("name") @ExcludeMissing fun _name(): JsonField = name + + /** + * Returns the raw JSON value of [allowedCallers]. + * + * Unlike [allowedCallers], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("allowed_callers") + @ExcludeMissing + fun _allowedCallers(): JsonField> = allowedCallers + + /** + * Returns the raw JSON value of [async]. + * + * Unlike [async], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("async") @ExcludeMissing fun _async(): JsonField = async + + /** + * Returns the raw JSON value of [deferLoading]. + * + * Unlike [deferLoading], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("defer_loading") + @ExcludeMissing + fun _deferLoading(): JsonField = deferLoading + + /** + * Returns the raw JSON value of [description]. + * + * Unlike [description], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("description") + @ExcludeMissing + fun _description(): JsonField = description + + /** + * Returns the raw JSON value of [outputSchema]. + * + * Unlike [outputSchema], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("output_schema") + @ExcludeMissing + fun _outputSchema(): JsonField = outputSchema + + /** + * Returns the raw JSON value of [strict]. + * + * Unlike [strict], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("strict") @ExcludeMissing fun _strict(): JsonField = strict + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [Function]. + * + * The following fields are required: + * ```java + * .name() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Function]. */ + class Builder internal constructor() { + + private var name: JsonField? = null + private var type: JsonValue = JsonValue.from("function") + private var allowedCallers: JsonField>? = null + private var async: JsonField = JsonMissing.of() + private var deferLoading: JsonField = JsonMissing.of() + private var description: JsonField = JsonMissing.of() + private var outputSchema: JsonField = JsonMissing.of() + private var parameters: JsonValue = JsonMissing.of() + private var strict: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(function: Function) = apply { + name = function.name + type = function.type + allowedCallers = function.allowedCallers.map { it.toMutableList() } + async = function.async + deferLoading = function.deferLoading + description = function.description + outputSchema = function.outputSchema + parameters = function.parameters + strict = function.strict + additionalProperties = function.additionalProperties.toMutableMap() + } + + /** The name of the loaded function tool. */ + fun name(name: String) = name(JsonField.of(name)) + + /** + * Sets [Builder.name] to an arbitrary JSON value. + * + * You should usually call [Builder.name] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun name(name: JsonField) = apply { this.name = name } + + /** + * Sets the field to an arbitrary JSON value. + * + * It is usually unnecessary to call this method because the field defaults to the + * following: + * ```java + * JsonValue.from("function") + * ``` + * + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun type(type: JsonValue) = apply { this.type = type } + + /** The tool invocation context(s). */ + fun allowedCallers(allowedCallers: List?) = + allowedCallers(JsonField.ofNullable(allowedCallers)) + + /** + * Alias for calling [Builder.allowedCallers] with `allowedCallers.orElse(null)`. + */ + fun allowedCallers(allowedCallers: Optional>) = + allowedCallers(allowedCallers.getOrNull()) + + /** + * Sets [Builder.allowedCallers] to an arbitrary JSON value. + * + * You should usually call [Builder.allowedCallers] with a well-typed + * `List` value instead. This method is primarily for setting the + * field to an undocumented or not yet supported value. + */ + fun allowedCallers(allowedCallers: JsonField>) = apply { + this.allowedCallers = allowedCallers.map { it.toMutableList() } + } + + /** + * Adds a single [AllowedCaller] to [allowedCallers]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addAllowedCaller(allowedCaller: AllowedCaller) = apply { + allowedCallers = + (allowedCallers ?: JsonField.of(mutableListOf())).also { + checkKnown("allowedCallers", it).add(allowedCaller) + } + } + + /** + * Whether the tool response can be returned asynchronously versus immediately + * returned on next response creation. + */ + fun async(async: Boolean) = async(JsonField.of(async)) + + /** + * Sets [Builder.async] to an arbitrary JSON value. + * + * You should usually call [Builder.async] with a well-typed [Boolean] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun async(async: JsonField) = apply { this.async = async } + + /** Whether this function should be deferred and discovered via tool search. */ + fun deferLoading(deferLoading: Boolean) = deferLoading(JsonField.of(deferLoading)) + + /** + * Sets [Builder.deferLoading] to an arbitrary JSON value. + * + * You should usually call [Builder.deferLoading] with a well-typed [Boolean] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun deferLoading(deferLoading: JsonField) = apply { + this.deferLoading = deferLoading + } + + fun description(description: String?) = + description(JsonField.ofNullable(description)) + + /** Alias for calling [Builder.description] with `description.orElse(null)`. */ + fun description(description: Optional) = + description(description.getOrNull()) + + /** + * Sets [Builder.description] to an arbitrary JSON value. + * + * You should usually call [Builder.description] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun description(description: JsonField) = apply { + this.description = description + } + + /** + * A JSON Schema describing the JSON value encoded in string outputs for this + * function tool. This does not describe content-array outputs. + */ + fun outputSchema(outputSchema: OutputSchema?) = + outputSchema(JsonField.ofNullable(outputSchema)) + + /** Alias for calling [Builder.outputSchema] with `outputSchema.orElse(null)`. */ + fun outputSchema(outputSchema: Optional) = + outputSchema(outputSchema.getOrNull()) + + /** + * Sets [Builder.outputSchema] to an arbitrary JSON value. + * + * You should usually call [Builder.outputSchema] with a well-typed [OutputSchema] + * value instead. This method is primarily for setting the field to an undocumented + * or not yet supported value. + */ + fun outputSchema(outputSchema: JsonField) = apply { + this.outputSchema = outputSchema + } + + fun parameters(parameters: JsonValue) = apply { this.parameters = parameters } + + /** + * Whether to enforce strict parameter validation. If omitted, Responses attempts to + * use strict validation when the schema is compatible, and falls back to non-strict + * validation otherwise. + */ + fun strict(strict: Boolean?) = strict(JsonField.ofNullable(strict)) + + /** + * Alias for [Builder.strict]. + * + * This unboxed primitive overload exists for backwards compatibility. + */ + fun strict(strict: Boolean) = strict(strict as Boolean?) + + /** Alias for calling [Builder.strict] with `strict.orElse(null)`. */ + fun strict(strict: Optional) = strict(strict.getOrNull()) + + /** + * Sets [Builder.strict] to an arbitrary JSON value. + * + * You should usually call [Builder.strict] with a well-typed [Boolean] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun strict(strict: JsonField) = apply { this.strict = strict } + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = + apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { + additionalProperties.remove(key) + } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [Function]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .name() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): Function = + Function( + checkRequired("name", name), + type, + (allowedCallers ?: JsonMissing.of()).map { it.toImmutable() }, + async, + deferLoading, + description, + outputSchema, + parameters, + strict, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws OpenAIInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): Function = apply { + if (validated) { + return@apply + } + + name() + _type().let { + if (it != JsonValue.from("function")) { + throw OpenAIInvalidDataException("'type' is invalid, received $it") + } + } + allowedCallers().ifPresent { it.forEach { it.validate() } } + async() + deferLoading() + description() + outputSchema().ifPresent { it.validate() } + strict() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: OpenAIInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + (if (name.asKnown().isPresent) 1 else 0) + + type.let { if (it == JsonValue.from("function")) 1 else 0 } + + (allowedCallers.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + + (if (async.asKnown().isPresent) 1 else 0) + + (if (deferLoading.asKnown().isPresent) 1 else 0) + + (if (description.asKnown().isPresent) 1 else 0) + + (outputSchema.asKnown().getOrNull()?.validity() ?: 0) + + (if (strict.asKnown().isPresent) 1 else 0) + + class AllowedCaller + @JsonCreator + private constructor(private val value: JsonField) : Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that + * doesn't match any known member, and you want to know that value. For example, if + * the SDK is on an older version than the API, then the API may respond with new + * members that the SDK is unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val DIRECT = of("direct") + + @JvmField val PROGRAMMATIC = of("programmatic") + + @JvmStatic fun of(value: String) = AllowedCaller(JsonField.of(value)) + } + + /** An enum containing [AllowedCaller]'s known values. */ + enum class Known { + DIRECT, + PROGRAMMATIC, + } + + /** + * An enum containing [AllowedCaller]'s known values, as well as an [_UNKNOWN] + * member. + * + * An instance of [AllowedCaller] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, + * if the SDK is on an older version than the API, then the API may respond with + * new members that the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + DIRECT, + PROGRAMMATIC, + /** + * An enum member indicating that [AllowedCaller] was instantiated with an + * unknown value. + */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or + * [Value._UNKNOWN] if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if + * you want to throw for the unknown case. + */ + fun value(): Value = + when (this) { + DIRECT -> Value.DIRECT + PROGRAMMATIC -> Value.PROGRAMMATIC + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and + * don't want to throw for the unknown case. + * + * @throws OpenAIInvalidDataException if this class instance's value is a not a + * known member. + */ + fun known(): Known = + when (this) { + DIRECT -> Known.DIRECT + PROGRAMMATIC -> Known.PROGRAMMATIC + else -> throw OpenAIInvalidDataException("Unknown AllowedCaller: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for + * debugging and generally doesn't throw. + * + * @throws OpenAIInvalidDataException if this class instance's value does not have + * the expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { + OpenAIInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws OpenAIInvalidDataException if any value type in this object doesn't match + * its expected type. + */ + fun validate(): AllowedCaller = apply { + if (validated) { + return@apply + } + + known() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: OpenAIInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is AllowedCaller && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + /** + * A JSON Schema describing the JSON value encoded in string outputs for this function + * tool. This does not describe content-array outputs. + */ + class OutputSchema + @JsonCreator + private constructor( + @com.fasterxml.jackson.annotation.JsonValue + private val additionalProperties: Map + ) { + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = additionalProperties + + fun toBuilder() = Builder().from(this) + + companion object { + + /** Returns a mutable builder for constructing an instance of [OutputSchema]. */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [OutputSchema]. */ + class Builder internal constructor() { + + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(outputSchema: OutputSchema) = apply { + additionalProperties = outputSchema.additionalProperties.toMutableMap() + } + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = + apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { + additionalProperties.remove(key) + } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [OutputSchema]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): OutputSchema = OutputSchema(additionalProperties.toImmutable()) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws OpenAIInvalidDataException if any value type in this object doesn't match + * its expected type. + */ + fun validate(): OutputSchema = apply { + if (validated) { + return@apply + } + + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: OpenAIInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + additionalProperties.count { (_, value) -> + !value.isNull() && !value.isMissing() + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is OutputSchema && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(additionalProperties) } + + override fun hashCode(): Int = hashCode + + override fun toString() = "OutputSchema{additionalProperties=$additionalProperties}" + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Function && + name == other.name && + type == other.type && + allowedCallers == other.allowedCallers && + async == other.async && + deferLoading == other.deferLoading && + description == other.description && + outputSchema == other.outputSchema && + parameters == other.parameters && + strict == other.strict && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash( + name, + type, + allowedCallers, + async, + deferLoading, + description, + outputSchema, + parameters, + strict, + additionalProperties, + ) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Function{name=$name, type=$type, allowedCallers=$allowedCallers, async=$async, deferLoading=$deferLoading, description=$description, outputSchema=$outputSchema, parameters=$parameters, strict=$strict, additionalProperties=$additionalProperties}" + } + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is ToolSearchOutputNamespaceTool && + description == other.description && + name == other.name && + tools == other.tools && + type == other.type && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(description, name, tools, type, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "ToolSearchOutputNamespaceTool{description=$description, name=$name, tools=$tools, type=$type, additionalProperties=$additionalProperties}" +} diff --git a/openai-java-core/src/main/kotlin/com/openai/services/async/DecisionServiceAsync.kt b/openai-java-core/src/main/kotlin/com/openai/services/async/DecisionServiceAsync.kt new file mode 100644 index 000000000..afb9d33cd --- /dev/null +++ b/openai-java-core/src/main/kotlin/com/openai/services/async/DecisionServiceAsync.kt @@ -0,0 +1,75 @@ +// File generated from our OpenAPI spec by Castiron. See CONTRIBUTING.md for details. + +package com.openai.services.async + +import com.openai.core.ClientOptions +import com.openai.core.RequestOptions +import com.openai.core.http.HttpResponseFor +import com.openai.models.decisions.Decision +import com.openai.models.decisions.DecisionCreateParams +import java.util.concurrent.CompletableFuture +import java.util.function.Consumer + +interface DecisionServiceAsync { + + /** + * Returns a view of this service that provides access to raw HTTP responses for each method. + */ + fun withRawResponse(): WithRawResponse + + /** + * Returns a view of this service with the given option modifications applied. + * + * The original service is not modified. + */ + fun withOptions(modifier: Consumer): DecisionServiceAsync + + /** + * Evaluate ordered classification and scoring questions against shared input. Answers are + * returned in question order. + * + * Supply input as a string or user messages containing text and inline images. Only user + * messages with `input_text` and `input_image` parts are supported; non-user roles, function + * calls, files, audio, and item references are not supported. Images require a data URL, not an + * external URL or file ID. At most 128 images are allowed across the request. + * + * Each question can return a refusal instead of a scored answer. A refusal has type `refusal` + * and the corresponding question name, or null if unnamed. + */ + fun create(params: DecisionCreateParams): CompletableFuture = + create(params, RequestOptions.none()) + + /** @see create */ + fun create( + params: DecisionCreateParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture + + /** + * A view of [DecisionServiceAsync] that provides access to raw HTTP responses for each method. + */ + interface WithRawResponse { + + /** + * Returns a view of this service with the given option modifications applied. + * + * The original service is not modified. + */ + fun withOptions( + modifier: Consumer + ): DecisionServiceAsync.WithRawResponse + + /** + * Returns a raw HTTP response for `post /decisions`, but is otherwise the same as + * [DecisionServiceAsync.create]. + */ + fun create(params: DecisionCreateParams): CompletableFuture> = + create(params, RequestOptions.none()) + + /** @see create */ + fun create( + params: DecisionCreateParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture> + } +} diff --git a/openai-java-core/src/main/kotlin/com/openai/services/async/DecisionServiceAsyncImpl.kt b/openai-java-core/src/main/kotlin/com/openai/services/async/DecisionServiceAsyncImpl.kt new file mode 100644 index 000000000..076b3ae97 --- /dev/null +++ b/openai-java-core/src/main/kotlin/com/openai/services/async/DecisionServiceAsyncImpl.kt @@ -0,0 +1,91 @@ +// File generated from our OpenAPI spec by Castiron. See CONTRIBUTING.md for details. + +package com.openai.services.async + +import com.openai.core.ClientOptions +import com.openai.core.RequestOptions +import com.openai.core.SecurityOptions +import com.openai.core.handlers.errorBodyHandler +import com.openai.core.handlers.errorHandler +import com.openai.core.handlers.jsonHandler +import com.openai.core.http.HttpMethod +import com.openai.core.http.HttpRequest +import com.openai.core.http.HttpResponse +import com.openai.core.http.HttpResponse.Handler +import com.openai.core.http.HttpResponseFor +import com.openai.core.http.json +import com.openai.core.http.parseable +import com.openai.core.prepareAsync +import com.openai.models.decisions.Decision +import com.openai.models.decisions.DecisionCreateParams +import java.util.concurrent.CompletableFuture +import java.util.function.Consumer + +class DecisionServiceAsyncImpl internal constructor(private val clientOptions: ClientOptions) : + DecisionServiceAsync { + + private val withRawResponse: DecisionServiceAsync.WithRawResponse by lazy { + WithRawResponseImpl(clientOptions) + } + + override fun withRawResponse(): DecisionServiceAsync.WithRawResponse = withRawResponse + + override fun withOptions(modifier: Consumer): DecisionServiceAsync = + DecisionServiceAsyncImpl(clientOptions.toBuilder().apply(modifier::accept).build()) + + override fun create( + params: DecisionCreateParams, + requestOptions: RequestOptions, + ): CompletableFuture = + // post /decisions + withRawResponse().create(params, requestOptions).thenApply { it.parse() } + + class WithRawResponseImpl internal constructor(private val clientOptions: ClientOptions) : + DecisionServiceAsync.WithRawResponse { + + private val errorHandler: Handler = + errorHandler(errorBodyHandler(clientOptions.jsonMapper)) + + override fun withOptions( + modifier: Consumer + ): DecisionServiceAsync.WithRawResponse = + DecisionServiceAsyncImpl.WithRawResponseImpl( + clientOptions.toBuilder().apply(modifier::accept).build() + ) + + private val createHandler: Handler = + jsonHandler(clientOptions.jsonMapper) + + override fun create( + params: DecisionCreateParams, + requestOptions: RequestOptions, + ): CompletableFuture> { + val request = + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("decisions") + .body(json(clientOptions.jsonMapper, params._body())) + .build() + .prepareAsync( + clientOptions, + params, + SecurityOptions.builder().bearerAuth(true).build(), + ) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + return request + .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } + .thenApply { response -> + errorHandler.handle(response).parseable { + response + .use { createHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + } + } +} diff --git a/openai-java-core/src/main/kotlin/com/openai/services/blocking/DecisionService.kt b/openai-java-core/src/main/kotlin/com/openai/services/blocking/DecisionService.kt new file mode 100644 index 000000000..237dac611 --- /dev/null +++ b/openai-java-core/src/main/kotlin/com/openai/services/blocking/DecisionService.kt @@ -0,0 +1,72 @@ +// File generated from our OpenAPI spec by Castiron. See CONTRIBUTING.md for details. + +package com.openai.services.blocking + +import com.google.errorprone.annotations.MustBeClosed +import com.openai.core.ClientOptions +import com.openai.core.RequestOptions +import com.openai.core.http.HttpResponseFor +import com.openai.models.decisions.Decision +import com.openai.models.decisions.DecisionCreateParams +import java.util.function.Consumer + +interface DecisionService { + + /** + * Returns a view of this service that provides access to raw HTTP responses for each method. + */ + fun withRawResponse(): WithRawResponse + + /** + * Returns a view of this service with the given option modifications applied. + * + * The original service is not modified. + */ + fun withOptions(modifier: Consumer): DecisionService + + /** + * Evaluate ordered classification and scoring questions against shared input. Answers are + * returned in question order. + * + * Supply input as a string or user messages containing text and inline images. Only user + * messages with `input_text` and `input_image` parts are supported; non-user roles, function + * calls, files, audio, and item references are not supported. Images require a data URL, not an + * external URL or file ID. At most 128 images are allowed across the request. + * + * Each question can return a refusal instead of a scored answer. A refusal has type `refusal` + * and the corresponding question name, or null if unnamed. + */ + fun create(params: DecisionCreateParams): Decision = create(params, RequestOptions.none()) + + /** @see create */ + fun create( + params: DecisionCreateParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): Decision + + /** A view of [DecisionService] that provides access to raw HTTP responses for each method. */ + interface WithRawResponse { + + /** + * Returns a view of this service with the given option modifications applied. + * + * The original service is not modified. + */ + fun withOptions(modifier: Consumer): DecisionService.WithRawResponse + + /** + * Returns a raw HTTP response for `post /decisions`, but is otherwise the same as + * [DecisionService.create]. + */ + @MustBeClosed + fun create(params: DecisionCreateParams): HttpResponseFor = + create(params, RequestOptions.none()) + + /** @see create */ + @MustBeClosed + fun create( + params: DecisionCreateParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor + } +} diff --git a/openai-java-core/src/main/kotlin/com/openai/services/blocking/DecisionServiceImpl.kt b/openai-java-core/src/main/kotlin/com/openai/services/blocking/DecisionServiceImpl.kt new file mode 100644 index 000000000..a96aee254 --- /dev/null +++ b/openai-java-core/src/main/kotlin/com/openai/services/blocking/DecisionServiceImpl.kt @@ -0,0 +1,84 @@ +// File generated from our OpenAPI spec by Castiron. See CONTRIBUTING.md for details. + +package com.openai.services.blocking + +import com.openai.core.ClientOptions +import com.openai.core.RequestOptions +import com.openai.core.SecurityOptions +import com.openai.core.handlers.errorBodyHandler +import com.openai.core.handlers.errorHandler +import com.openai.core.handlers.jsonHandler +import com.openai.core.http.HttpMethod +import com.openai.core.http.HttpRequest +import com.openai.core.http.HttpResponse +import com.openai.core.http.HttpResponse.Handler +import com.openai.core.http.HttpResponseFor +import com.openai.core.http.json +import com.openai.core.http.parseable +import com.openai.core.prepare +import com.openai.models.decisions.Decision +import com.openai.models.decisions.DecisionCreateParams +import java.util.function.Consumer + +class DecisionServiceImpl internal constructor(private val clientOptions: ClientOptions) : + DecisionService { + + private val withRawResponse: DecisionService.WithRawResponse by lazy { + WithRawResponseImpl(clientOptions) + } + + override fun withRawResponse(): DecisionService.WithRawResponse = withRawResponse + + override fun withOptions(modifier: Consumer): DecisionService = + DecisionServiceImpl(clientOptions.toBuilder().apply(modifier::accept).build()) + + override fun create(params: DecisionCreateParams, requestOptions: RequestOptions): Decision = + // post /decisions + withRawResponse().create(params, requestOptions).parse() + + class WithRawResponseImpl internal constructor(private val clientOptions: ClientOptions) : + DecisionService.WithRawResponse { + + private val errorHandler: Handler = + errorHandler(errorBodyHandler(clientOptions.jsonMapper)) + + override fun withOptions( + modifier: Consumer + ): DecisionService.WithRawResponse = + DecisionServiceImpl.WithRawResponseImpl( + clientOptions.toBuilder().apply(modifier::accept).build() + ) + + private val createHandler: Handler = + jsonHandler(clientOptions.jsonMapper) + + override fun create( + params: DecisionCreateParams, + requestOptions: RequestOptions, + ): HttpResponseFor { + val request = + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("decisions") + .body(json(clientOptions.jsonMapper, params._body())) + .build() + .prepare( + clientOptions, + params, + SecurityOptions.builder().bearerAuth(true).build(), + ) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.execute(request, requestOptions) + return errorHandler.handle(response).parseable { + response + .use { createHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + } +} diff --git a/openai-java-core/src/test/kotlin/com/openai/models/beta/responses/BetaResponseToolSearchOutputItemParamTest.kt b/openai-java-core/src/test/kotlin/com/openai/models/beta/responses/BetaResponseToolSearchOutputItemParamTest.kt index 3a2891e76..1450596e8 100644 --- a/openai-java-core/src/test/kotlin/com/openai/models/beta/responses/BetaResponseToolSearchOutputItemParamTest.kt +++ b/openai-java-core/src/test/kotlin/com/openai/models/beta/responses/BetaResponseToolSearchOutputItemParamTest.kt @@ -47,7 +47,7 @@ internal class BetaResponseToolSearchOutputItemParamTest { assertThat(betaResponseToolSearchOutputItemParam.tools()) .containsExactly( - BetaTool.ofFunction( + BetaResponseToolSearchOutputItemParam.Tool.ofFunction( BetaFunctionTool.builder() .name("name") .parameters( diff --git a/openai-java-core/src/test/kotlin/com/openai/models/beta/responses/BetaToolSearchOutputNamespaceToolTest.kt b/openai-java-core/src/test/kotlin/com/openai/models/beta/responses/BetaToolSearchOutputNamespaceToolTest.kt new file mode 100644 index 000000000..0454a96e5 --- /dev/null +++ b/openai-java-core/src/test/kotlin/com/openai/models/beta/responses/BetaToolSearchOutputNamespaceToolTest.kt @@ -0,0 +1,100 @@ +// File generated from our OpenAPI spec by Castiron. See CONTRIBUTING.md for details. + +package com.openai.models.beta.responses + +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import com.openai.core.JsonValue +import com.openai.core.jsonMapper +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class BetaToolSearchOutputNamespaceToolTest { + + @Test + fun create() { + val betaToolSearchOutputNamespaceTool = + BetaToolSearchOutputNamespaceTool.builder() + .description("description") + .name("x") + .addTool( + BetaToolSearchOutputNamespaceTool.Tool.Function.builder() + .name("x") + .addAllowedCaller( + BetaToolSearchOutputNamespaceTool.Tool.Function.AllowedCaller.DIRECT + ) + .async(true) + .deferLoading(true) + .description("description") + .outputSchema( + BetaToolSearchOutputNamespaceTool.Tool.Function.OutputSchema.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .parameters(JsonValue.from(mapOf())) + .strict(true) + .build() + ) + .build() + + assertThat(betaToolSearchOutputNamespaceTool.description()).isEqualTo("description") + assertThat(betaToolSearchOutputNamespaceTool.name()).isEqualTo("x") + assertThat(betaToolSearchOutputNamespaceTool.tools()) + .containsExactly( + BetaToolSearchOutputNamespaceTool.Tool.ofFunction( + BetaToolSearchOutputNamespaceTool.Tool.Function.builder() + .name("x") + .addAllowedCaller( + BetaToolSearchOutputNamespaceTool.Tool.Function.AllowedCaller.DIRECT + ) + .async(true) + .deferLoading(true) + .description("description") + .outputSchema( + BetaToolSearchOutputNamespaceTool.Tool.Function.OutputSchema.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .parameters(JsonValue.from(mapOf())) + .strict(true) + .build() + ) + ) + } + + @Test + fun roundtrip() { + val jsonMapper = jsonMapper() + val betaToolSearchOutputNamespaceTool = + BetaToolSearchOutputNamespaceTool.builder() + .description("description") + .name("x") + .addTool( + BetaToolSearchOutputNamespaceTool.Tool.Function.builder() + .name("x") + .addAllowedCaller( + BetaToolSearchOutputNamespaceTool.Tool.Function.AllowedCaller.DIRECT + ) + .async(true) + .deferLoading(true) + .description("description") + .outputSchema( + BetaToolSearchOutputNamespaceTool.Tool.Function.OutputSchema.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .parameters(JsonValue.from(mapOf())) + .strict(true) + .build() + ) + .build() + + val roundtrippedBetaToolSearchOutputNamespaceTool = + jsonMapper.readValue( + jsonMapper.writeValueAsString(betaToolSearchOutputNamespaceTool), + jacksonTypeRef(), + ) + + assertThat(roundtrippedBetaToolSearchOutputNamespaceTool) + .isEqualTo(betaToolSearchOutputNamespaceTool) + } +} diff --git a/openai-java-core/src/test/kotlin/com/openai/models/decisions/DecisionChoiceOptionTest.kt b/openai-java-core/src/test/kotlin/com/openai/models/decisions/DecisionChoiceOptionTest.kt new file mode 100644 index 000000000..5dd74d08c --- /dev/null +++ b/openai-java-core/src/test/kotlin/com/openai/models/decisions/DecisionChoiceOptionTest.kt @@ -0,0 +1,36 @@ +// File generated from our OpenAPI spec by Castiron. See CONTRIBUTING.md for details. + +package com.openai.models.decisions + +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import com.openai.core.jsonMapper +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class DecisionChoiceOptionTest { + + @Test + fun create() { + val decisionChoiceOption = + DecisionChoiceOption.builder().value("string").description("description").build() + + assertThat(decisionChoiceOption.value()) + .isEqualTo(DecisionChoiceOption.Value.ofString("string")) + assertThat(decisionChoiceOption.description()).contains("description") + } + + @Test + fun roundtrip() { + val jsonMapper = jsonMapper() + val decisionChoiceOption = + DecisionChoiceOption.builder().value("string").description("description").build() + + val roundtrippedDecisionChoiceOption = + jsonMapper.readValue( + jsonMapper.writeValueAsString(decisionChoiceOption), + jacksonTypeRef(), + ) + + assertThat(roundtrippedDecisionChoiceOption).isEqualTo(decisionChoiceOption) + } +} diff --git a/openai-java-core/src/test/kotlin/com/openai/models/decisions/DecisionChoiceValueTest.kt b/openai-java-core/src/test/kotlin/com/openai/models/decisions/DecisionChoiceValueTest.kt new file mode 100644 index 000000000..2b125d2d9 --- /dev/null +++ b/openai-java-core/src/test/kotlin/com/openai/models/decisions/DecisionChoiceValueTest.kt @@ -0,0 +1,81 @@ +// File generated from our OpenAPI spec by Castiron. See CONTRIBUTING.md for details. + +package com.openai.models.decisions + +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import com.openai.core.JsonValue +import com.openai.core.jsonMapper +import com.openai.errors.OpenAIInvalidDataException +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.assertThrows +import org.junit.jupiter.params.ParameterizedTest +import org.junit.jupiter.params.provider.EnumSource + +internal class DecisionChoiceValueTest { + + @Test + fun ofString() { + val string = "string" + + val decisionChoiceValue = DecisionChoiceValue.ofString(string) + + assertThat(decisionChoiceValue.string()).contains(string) + assertThat(decisionChoiceValue.bool()).isEmpty + } + + @Test + fun ofStringRoundtrip() { + val jsonMapper = jsonMapper() + val decisionChoiceValue = DecisionChoiceValue.ofString("string") + + val roundtrippedDecisionChoiceValue = + jsonMapper.readValue( + jsonMapper.writeValueAsString(decisionChoiceValue), + jacksonTypeRef(), + ) + + assertThat(roundtrippedDecisionChoiceValue).isEqualTo(decisionChoiceValue) + } + + @Test + fun ofBool() { + val bool = true + + val decisionChoiceValue = DecisionChoiceValue.ofBool(bool) + + assertThat(decisionChoiceValue.string()).isEmpty + assertThat(decisionChoiceValue.bool()).contains(bool) + } + + @Test + fun ofBoolRoundtrip() { + val jsonMapper = jsonMapper() + val decisionChoiceValue = DecisionChoiceValue.ofBool(true) + + val roundtrippedDecisionChoiceValue = + jsonMapper.readValue( + jsonMapper.writeValueAsString(decisionChoiceValue), + jacksonTypeRef(), + ) + + assertThat(roundtrippedDecisionChoiceValue).isEqualTo(decisionChoiceValue) + } + + enum class IncompatibleJsonShapeTestCase(val value: JsonValue) { + INTEGER(JsonValue.from(-1)), + FLOAT(JsonValue.from(3.14)), + OBJECT(JsonValue.from(mapOf("invalid" to "object"))), + ARRAY(JsonValue.from(listOf("invalid", "array"))), + } + + @ParameterizedTest + @EnumSource + fun incompatibleJsonShapeDeserializesToUnknown(testCase: IncompatibleJsonShapeTestCase) { + val decisionChoiceValue = + jsonMapper().convertValue(testCase.value, jacksonTypeRef()) + + val e = assertThrows { decisionChoiceValue.validate() } + assertThat(e).hasMessageStartingWith("Unknown ") + } +} diff --git a/openai-java-core/src/test/kotlin/com/openai/models/decisions/DecisionCreateParamsTest.kt b/openai-java-core/src/test/kotlin/com/openai/models/decisions/DecisionCreateParamsTest.kt new file mode 100644 index 000000000..f3143641f --- /dev/null +++ b/openai-java-core/src/test/kotlin/com/openai/models/decisions/DecisionCreateParamsTest.kt @@ -0,0 +1,78 @@ +// File generated from our OpenAPI spec by Castiron. See CONTRIBUTING.md for details. + +package com.openai.models.decisions + +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class DecisionCreateParamsTest { + + @Test + fun create() { + DecisionCreateParams.builder() + .input("string") + .model("model") + .addQuestion( + DecisionCreateParams.Question.Predicate.builder() + .instructions("instructions") + .name("name") + .build() + ) + .safetyIdentifier("safety_identifier") + .build() + } + + @Test + fun body() { + val params = + DecisionCreateParams.builder() + .input("string") + .model("model") + .addQuestion( + DecisionCreateParams.Question.Predicate.builder() + .instructions("instructions") + .name("name") + .build() + ) + .safetyIdentifier("safety_identifier") + .build() + + val body = params._body() + + assertThat(body.input()).isEqualTo(DecisionCreateParams.Input.ofString("string")) + assertThat(body.model()).isEqualTo("model") + assertThat(body.questions()) + .containsExactly( + DecisionCreateParams.Question.ofPredicate( + DecisionCreateParams.Question.Predicate.builder() + .instructions("instructions") + .name("name") + .build() + ) + ) + assertThat(body.safetyIdentifier()).contains("safety_identifier") + } + + @Test + fun bodyWithoutOptionalFields() { + val params = + DecisionCreateParams.builder() + .input("string") + .model("model") + .addPredicateQuestion("instructions") + .build() + + val body = params._body() + + assertThat(body.input()).isEqualTo(DecisionCreateParams.Input.ofString("string")) + assertThat(body.model()).isEqualTo("model") + assertThat(body.questions()) + .containsExactly( + DecisionCreateParams.Question.ofPredicate( + DecisionCreateParams.Question.Predicate.builder() + .instructions("instructions") + .build() + ) + ) + } +} diff --git a/openai-java-core/src/test/kotlin/com/openai/models/decisions/DecisionInputImageTest.kt b/openai-java-core/src/test/kotlin/com/openai/models/decisions/DecisionInputImageTest.kt new file mode 100644 index 000000000..5ba26f1e2 --- /dev/null +++ b/openai-java-core/src/test/kotlin/com/openai/models/decisions/DecisionInputImageTest.kt @@ -0,0 +1,41 @@ +// File generated from our OpenAPI spec by Castiron. See CONTRIBUTING.md for details. + +package com.openai.models.decisions + +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import com.openai.core.jsonMapper +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class DecisionInputImageTest { + + @Test + fun create() { + val decisionInputImage = + DecisionInputImage.builder() + .imageUrl("data:") + .detail(DecisionInputImage.Detail.LOW) + .build() + + assertThat(decisionInputImage.imageUrl()).isEqualTo("data:") + assertThat(decisionInputImage.detail()).contains(DecisionInputImage.Detail.LOW) + } + + @Test + fun roundtrip() { + val jsonMapper = jsonMapper() + val decisionInputImage = + DecisionInputImage.builder() + .imageUrl("data:") + .detail(DecisionInputImage.Detail.LOW) + .build() + + val roundtrippedDecisionInputImage = + jsonMapper.readValue( + jsonMapper.writeValueAsString(decisionInputImage), + jacksonTypeRef(), + ) + + assertThat(roundtrippedDecisionInputImage).isEqualTo(decisionInputImage) + } +} diff --git a/openai-java-core/src/test/kotlin/com/openai/models/decisions/DecisionInputMessageTest.kt b/openai-java-core/src/test/kotlin/com/openai/models/decisions/DecisionInputMessageTest.kt new file mode 100644 index 000000000..2df3ed8a6 --- /dev/null +++ b/openai-java-core/src/test/kotlin/com/openai/models/decisions/DecisionInputMessageTest.kt @@ -0,0 +1,42 @@ +// File generated from our OpenAPI spec by Castiron. See CONTRIBUTING.md for details. + +package com.openai.models.decisions + +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import com.openai.core.jsonMapper +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class DecisionInputMessageTest { + + @Test + fun create() { + val decisionInputMessage = + DecisionInputMessage.builder() + .content("string") + .type(DecisionInputMessage.Type.MESSAGE) + .build() + + assertThat(decisionInputMessage.content()) + .isEqualTo(DecisionInputMessage.Content.ofString("string")) + assertThat(decisionInputMessage.type()).contains(DecisionInputMessage.Type.MESSAGE) + } + + @Test + fun roundtrip() { + val jsonMapper = jsonMapper() + val decisionInputMessage = + DecisionInputMessage.builder() + .content("string") + .type(DecisionInputMessage.Type.MESSAGE) + .build() + + val roundtrippedDecisionInputMessage = + jsonMapper.readValue( + jsonMapper.writeValueAsString(decisionInputMessage), + jacksonTypeRef(), + ) + + assertThat(roundtrippedDecisionInputMessage).isEqualTo(decisionInputMessage) + } +} diff --git a/openai-java-core/src/test/kotlin/com/openai/models/decisions/DecisionInputPartTest.kt b/openai-java-core/src/test/kotlin/com/openai/models/decisions/DecisionInputPartTest.kt new file mode 100644 index 000000000..b1e491c51 --- /dev/null +++ b/openai-java-core/src/test/kotlin/com/openai/models/decisions/DecisionInputPartTest.kt @@ -0,0 +1,93 @@ +// File generated from our OpenAPI spec by Castiron. See CONTRIBUTING.md for details. + +package com.openai.models.decisions + +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import com.openai.core.JsonValue +import com.openai.core.jsonMapper +import com.openai.errors.OpenAIInvalidDataException +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.assertThrows +import org.junit.jupiter.params.ParameterizedTest +import org.junit.jupiter.params.provider.EnumSource + +internal class DecisionInputPartTest { + + @Test + fun ofInputText() { + val inputText = DecisionInputText.builder().text("text").build() + + val decisionInputPart = DecisionInputPart.ofInputText(inputText) + + assertThat(decisionInputPart.inputText()).contains(inputText) + assertThat(decisionInputPart.inputImage()).isEmpty + } + + @Test + fun ofInputTextRoundtrip() { + val jsonMapper = jsonMapper() + val decisionInputPart = + DecisionInputPart.ofInputText(DecisionInputText.builder().text("text").build()) + + val roundtrippedDecisionInputPart = + jsonMapper.readValue( + jsonMapper.writeValueAsString(decisionInputPart), + jacksonTypeRef(), + ) + + assertThat(roundtrippedDecisionInputPart).isEqualTo(decisionInputPart) + } + + @Test + fun ofInputImage() { + val inputImage = + DecisionInputImage.builder() + .imageUrl("data:") + .detail(DecisionInputImage.Detail.LOW) + .build() + + val decisionInputPart = DecisionInputPart.ofInputImage(inputImage) + + assertThat(decisionInputPart.inputText()).isEmpty + assertThat(decisionInputPart.inputImage()).contains(inputImage) + } + + @Test + fun ofInputImageRoundtrip() { + val jsonMapper = jsonMapper() + val decisionInputPart = + DecisionInputPart.ofInputImage( + DecisionInputImage.builder() + .imageUrl("data:") + .detail(DecisionInputImage.Detail.LOW) + .build() + ) + + val roundtrippedDecisionInputPart = + jsonMapper.readValue( + jsonMapper.writeValueAsString(decisionInputPart), + jacksonTypeRef(), + ) + + assertThat(roundtrippedDecisionInputPart).isEqualTo(decisionInputPart) + } + + enum class IncompatibleJsonShapeTestCase(val value: JsonValue) { + BOOLEAN(JsonValue.from(false)), + STRING(JsonValue.from("invalid")), + INTEGER(JsonValue.from(-1)), + FLOAT(JsonValue.from(3.14)), + ARRAY(JsonValue.from(listOf("invalid", "array"))), + } + + @ParameterizedTest + @EnumSource + fun incompatibleJsonShapeDeserializesToUnknown(testCase: IncompatibleJsonShapeTestCase) { + val decisionInputPart = + jsonMapper().convertValue(testCase.value, jacksonTypeRef()) + + val e = assertThrows { decisionInputPart.validate() } + assertThat(e).hasMessageStartingWith("Unknown ") + } +} diff --git a/openai-java-core/src/test/kotlin/com/openai/models/decisions/DecisionInputTextTest.kt b/openai-java-core/src/test/kotlin/com/openai/models/decisions/DecisionInputTextTest.kt new file mode 100644 index 000000000..c57a7bd86 --- /dev/null +++ b/openai-java-core/src/test/kotlin/com/openai/models/decisions/DecisionInputTextTest.kt @@ -0,0 +1,32 @@ +// File generated from our OpenAPI spec by Castiron. See CONTRIBUTING.md for details. + +package com.openai.models.decisions + +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import com.openai.core.jsonMapper +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class DecisionInputTextTest { + + @Test + fun create() { + val decisionInputText = DecisionInputText.builder().text("text").build() + + assertThat(decisionInputText.text()).isEqualTo("text") + } + + @Test + fun roundtrip() { + val jsonMapper = jsonMapper() + val decisionInputText = DecisionInputText.builder().text("text").build() + + val roundtrippedDecisionInputText = + jsonMapper.readValue( + jsonMapper.writeValueAsString(decisionInputText), + jacksonTypeRef(), + ) + + assertThat(roundtrippedDecisionInputText).isEqualTo(decisionInputText) + } +} diff --git a/openai-java-core/src/test/kotlin/com/openai/models/decisions/DecisionTest.kt b/openai-java-core/src/test/kotlin/com/openai/models/decisions/DecisionTest.kt new file mode 100644 index 000000000..e569f84e6 --- /dev/null +++ b/openai-java-core/src/test/kotlin/com/openai/models/decisions/DecisionTest.kt @@ -0,0 +1,105 @@ +// File generated from our OpenAPI spec by Castiron. See CONTRIBUTING.md for details. + +package com.openai.models.decisions + +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import com.openai.core.jsonMapper +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class DecisionTest { + + @Test + fun create() { + val decision = + Decision.builder() + .addAnswer( + Decision.Answer.Predicate.builder().name("name").probability(0.0).build() + ) + .model("model") + .usage( + Decision.Usage.builder() + .inputTokens(-2147483648L) + .inputTokensDetails( + Decision.Usage.InputTokensDetails.builder() + .cacheWriteTokens(-2147483648L) + .cachedTokens(-2147483648L) + .build() + ) + .outputTokens(-2147483648L) + .outputTokensDetails( + Decision.Usage.OutputTokensDetails.builder() + .reasoningTokens(-2147483648L) + .build() + ) + .totalTokens(-2147483648L) + .build() + ) + .build() + + assertThat(decision.answers()) + .containsExactly( + Decision.Answer.ofPredicate( + Decision.Answer.Predicate.builder().name("name").probability(0.0).build() + ) + ) + assertThat(decision.model()).isEqualTo("model") + assertThat(decision.usage()) + .isEqualTo( + Decision.Usage.builder() + .inputTokens(-2147483648L) + .inputTokensDetails( + Decision.Usage.InputTokensDetails.builder() + .cacheWriteTokens(-2147483648L) + .cachedTokens(-2147483648L) + .build() + ) + .outputTokens(-2147483648L) + .outputTokensDetails( + Decision.Usage.OutputTokensDetails.builder() + .reasoningTokens(-2147483648L) + .build() + ) + .totalTokens(-2147483648L) + .build() + ) + } + + @Test + fun roundtrip() { + val jsonMapper = jsonMapper() + val decision = + Decision.builder() + .addAnswer( + Decision.Answer.Predicate.builder().name("name").probability(0.0).build() + ) + .model("model") + .usage( + Decision.Usage.builder() + .inputTokens(-2147483648L) + .inputTokensDetails( + Decision.Usage.InputTokensDetails.builder() + .cacheWriteTokens(-2147483648L) + .cachedTokens(-2147483648L) + .build() + ) + .outputTokens(-2147483648L) + .outputTokensDetails( + Decision.Usage.OutputTokensDetails.builder() + .reasoningTokens(-2147483648L) + .build() + ) + .totalTokens(-2147483648L) + .build() + ) + .build() + + val roundtrippedDecision = + jsonMapper.readValue( + jsonMapper.writeValueAsString(decision), + jacksonTypeRef(), + ) + + assertThat(roundtrippedDecision).isEqualTo(decision) + } +} diff --git a/openai-java-core/src/test/kotlin/com/openai/models/responses/ResponseToolSearchOutputItemParamTest.kt b/openai-java-core/src/test/kotlin/com/openai/models/responses/ResponseToolSearchOutputItemParamTest.kt index f5d1f6644..2c77f8c1a 100644 --- a/openai-java-core/src/test/kotlin/com/openai/models/responses/ResponseToolSearchOutputItemParamTest.kt +++ b/openai-java-core/src/test/kotlin/com/openai/models/responses/ResponseToolSearchOutputItemParamTest.kt @@ -42,7 +42,7 @@ internal class ResponseToolSearchOutputItemParamTest { assertThat(responseToolSearchOutputItemParam.tools()) .containsExactly( - Tool.ofFunction( + ResponseToolSearchOutputItemParam.Tool.ofFunction( FunctionTool.builder() .name("name") .parameters( diff --git a/openai-java-core/src/test/kotlin/com/openai/models/responses/ToolSearchOutputNamespaceToolTest.kt b/openai-java-core/src/test/kotlin/com/openai/models/responses/ToolSearchOutputNamespaceToolTest.kt new file mode 100644 index 000000000..724a660f3 --- /dev/null +++ b/openai-java-core/src/test/kotlin/com/openai/models/responses/ToolSearchOutputNamespaceToolTest.kt @@ -0,0 +1,100 @@ +// File generated from our OpenAPI spec by Castiron. See CONTRIBUTING.md for details. + +package com.openai.models.responses + +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import com.openai.core.JsonValue +import com.openai.core.jsonMapper +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class ToolSearchOutputNamespaceToolTest { + + @Test + fun create() { + val toolSearchOutputNamespaceTool = + ToolSearchOutputNamespaceTool.builder() + .description("description") + .name("x") + .addTool( + ToolSearchOutputNamespaceTool.Tool.Function.builder() + .name("x") + .addAllowedCaller( + ToolSearchOutputNamespaceTool.Tool.Function.AllowedCaller.DIRECT + ) + .async(true) + .deferLoading(true) + .description("description") + .outputSchema( + ToolSearchOutputNamespaceTool.Tool.Function.OutputSchema.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .parameters(JsonValue.from(mapOf())) + .strict(true) + .build() + ) + .build() + + assertThat(toolSearchOutputNamespaceTool.description()).isEqualTo("description") + assertThat(toolSearchOutputNamespaceTool.name()).isEqualTo("x") + assertThat(toolSearchOutputNamespaceTool.tools()) + .containsExactly( + ToolSearchOutputNamespaceTool.Tool.ofFunction( + ToolSearchOutputNamespaceTool.Tool.Function.builder() + .name("x") + .addAllowedCaller( + ToolSearchOutputNamespaceTool.Tool.Function.AllowedCaller.DIRECT + ) + .async(true) + .deferLoading(true) + .description("description") + .outputSchema( + ToolSearchOutputNamespaceTool.Tool.Function.OutputSchema.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .parameters(JsonValue.from(mapOf())) + .strict(true) + .build() + ) + ) + } + + @Test + fun roundtrip() { + val jsonMapper = jsonMapper() + val toolSearchOutputNamespaceTool = + ToolSearchOutputNamespaceTool.builder() + .description("description") + .name("x") + .addTool( + ToolSearchOutputNamespaceTool.Tool.Function.builder() + .name("x") + .addAllowedCaller( + ToolSearchOutputNamespaceTool.Tool.Function.AllowedCaller.DIRECT + ) + .async(true) + .deferLoading(true) + .description("description") + .outputSchema( + ToolSearchOutputNamespaceTool.Tool.Function.OutputSchema.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .parameters(JsonValue.from(mapOf())) + .strict(true) + .build() + ) + .build() + + val roundtrippedToolSearchOutputNamespaceTool = + jsonMapper.readValue( + jsonMapper.writeValueAsString(toolSearchOutputNamespaceTool), + jacksonTypeRef(), + ) + + assertThat(roundtrippedToolSearchOutputNamespaceTool) + .isEqualTo(toolSearchOutputNamespaceTool) + } +} diff --git a/openai-java-core/src/test/kotlin/com/openai/services/async/DecisionServiceAsyncTest.kt b/openai-java-core/src/test/kotlin/com/openai/services/async/DecisionServiceAsyncTest.kt new file mode 100644 index 000000000..fb1b5d536 --- /dev/null +++ b/openai-java-core/src/test/kotlin/com/openai/services/async/DecisionServiceAsyncTest.kt @@ -0,0 +1,42 @@ +// File generated from our OpenAPI spec by Castiron. See CONTRIBUTING.md for details. + +package com.openai.services.async + +import com.openai.TestServerExtension +import com.openai.client.okhttp.OpenAIOkHttpClientAsync +import com.openai.models.decisions.DecisionCreateParams +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith + +@ExtendWith(TestServerExtension::class) +internal class DecisionServiceAsyncTest { + + @Test + fun create() { + val client = + OpenAIOkHttpClientAsync.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .adminApiKey("My Admin API Key") + .build() + val decisionServiceAsync = client.decisions() + + val decisionFuture = + decisionServiceAsync.create( + DecisionCreateParams.builder() + .input("string") + .model("model") + .addQuestion( + DecisionCreateParams.Question.Predicate.builder() + .instructions("instructions") + .name("name") + .build() + ) + .safetyIdentifier("safety_identifier") + .build() + ) + + val decision = decisionFuture.get() + decision.validate() + } +} diff --git a/openai-java-core/src/test/kotlin/com/openai/services/blocking/DecisionServiceTest.kt b/openai-java-core/src/test/kotlin/com/openai/services/blocking/DecisionServiceTest.kt new file mode 100644 index 000000000..a936908d6 --- /dev/null +++ b/openai-java-core/src/test/kotlin/com/openai/services/blocking/DecisionServiceTest.kt @@ -0,0 +1,41 @@ +// File generated from our OpenAPI spec by Castiron. See CONTRIBUTING.md for details. + +package com.openai.services.blocking + +import com.openai.TestServerExtension +import com.openai.client.okhttp.OpenAIOkHttpClient +import com.openai.models.decisions.DecisionCreateParams +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith + +@ExtendWith(TestServerExtension::class) +internal class DecisionServiceTest { + + @Test + fun create() { + val client = + OpenAIOkHttpClient.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .adminApiKey("My Admin API Key") + .build() + val decisionService = client.decisions() + + val decision = + decisionService.create( + DecisionCreateParams.builder() + .input("string") + .model("model") + .addQuestion( + DecisionCreateParams.Question.Predicate.builder() + .instructions("instructions") + .name("name") + .build() + ) + .safetyIdentifier("safety_identifier") + .build() + ) + + decision.validate() + } +} From 7ba474e133316eef657de67c76180817cbf441ac Mon Sep 17 00:00:00 2001 From: Daniel Piet Date: Tue, 6 Oct 2026 18:02:12 -0400 Subject: [PATCH 2/2] fix: preserve Responses tool-search output API compatibility --- .../beta/responses/BetaResponseInjectEvent.kt | 2 +- .../BetaResponseInjectFailedEvent.kt | 2 +- .../BetaResponseToolSearchOutputItemParam.kt | 113 ++++++++--------- .../conversations/ConversationCreateParams.kt | 4 +- .../conversations/items/ItemCreateParams.kt | 4 +- .../models/live/ResponseItemCreateEvent.kt | 2 +- .../ResponseToolSearchOutputItemParam.kt | 119 +++++++++--------- ...taResponseToolSearchOutputItemParamTest.kt | 2 +- .../ResponseToolSearchOutputItemParamTest.kt | 2 +- 9 files changed, 129 insertions(+), 121 deletions(-) diff --git a/openai-java-core/src/main/kotlin/com/openai/models/beta/responses/BetaResponseInjectEvent.kt b/openai-java-core/src/main/kotlin/com/openai/models/beta/responses/BetaResponseInjectEvent.kt index 9bf1eec58..5444da48c 100644 --- a/openai-java-core/src/main/kotlin/com/openai/models/beta/responses/BetaResponseInjectEvent.kt +++ b/openai-java-core/src/main/kotlin/com/openai/models/beta/responses/BetaResponseInjectEvent.kt @@ -300,7 +300,7 @@ private constructor( * .build() * ``` */ - fun addToolSearchOutputInput(tools: List) = + fun addToolSearchOutputInput(tools: List) = addInput(BetaResponseToolSearchOutputItemParam.builder().tools(tools).build()) /** diff --git a/openai-java-core/src/main/kotlin/com/openai/models/beta/responses/BetaResponseInjectFailedEvent.kt b/openai-java-core/src/main/kotlin/com/openai/models/beta/responses/BetaResponseInjectFailedEvent.kt index d9f727bf0..659ac23b5 100644 --- a/openai-java-core/src/main/kotlin/com/openai/models/beta/responses/BetaResponseInjectFailedEvent.kt +++ b/openai-java-core/src/main/kotlin/com/openai/models/beta/responses/BetaResponseInjectFailedEvent.kt @@ -377,7 +377,7 @@ private constructor( * .build() * ``` */ - fun addToolSearchOutputInput(tools: List) = + fun addToolSearchOutputInput(tools: List) = addInput(BetaResponseToolSearchOutputItemParam.builder().tools(tools).build()) /** diff --git a/openai-java-core/src/main/kotlin/com/openai/models/beta/responses/BetaResponseToolSearchOutputItemParam.kt b/openai-java-core/src/main/kotlin/com/openai/models/beta/responses/BetaResponseToolSearchOutputItemParam.kt index 748e3f82e..77ec59e5a 100644 --- a/openai-java-core/src/main/kotlin/com/openai/models/beta/responses/BetaResponseToolSearchOutputItemParam.kt +++ b/openai-java-core/src/main/kotlin/com/openai/models/beta/responses/BetaResponseToolSearchOutputItemParam.kt @@ -34,7 +34,7 @@ import kotlin.jvm.optionals.getOrNull class BetaResponseToolSearchOutputItemParam @JsonCreator(mode = JsonCreator.Mode.DISABLED) private constructor( - private val tools: JsonField>, + private val tools: JsonField>, private val type: JsonValue, private val id: JsonField, private val agent: JsonField, @@ -46,7 +46,7 @@ private constructor( @JsonCreator private constructor( - @JsonProperty("tools") @ExcludeMissing tools: JsonField> = JsonMissing.of(), + @JsonProperty("tools") @ExcludeMissing tools: JsonField> = JsonMissing.of(), @JsonProperty("type") @ExcludeMissing type: JsonValue = JsonMissing.of(), @JsonProperty("id") @ExcludeMissing id: JsonField = JsonMissing.of(), @JsonProperty("agent") @ExcludeMissing agent: JsonField = JsonMissing.of(), @@ -63,7 +63,7 @@ private constructor( * @throws OpenAIInvalidDataException if the JSON field has an unexpected type or is * unexpectedly missing or null (e.g. if the server responded with an unexpected value). */ - fun tools(): List = tools.getRequired("tools") + fun tools(): List = tools.getRequired("tools") /** * The item type. Always `tool_search_output`. @@ -123,7 +123,7 @@ private constructor( * * Unlike [tools], this method doesn't throw if the JSON field has an unexpected type. */ - @JsonProperty("tools") @ExcludeMissing fun _tools(): JsonField> = tools + @JsonProperty("tools") @ExcludeMissing fun _tools(): JsonField> = tools /** * Returns the raw JSON value of [id]. @@ -189,7 +189,7 @@ private constructor( /** A builder for [BetaResponseToolSearchOutputItemParam]. */ class Builder internal constructor() { - private var tools: JsonField>? = null + private var tools: JsonField>? = null private var type: JsonValue = JsonValue.from("tool_search_output") private var id: JsonField = JsonMissing.of() private var agent: JsonField = JsonMissing.of() @@ -214,34 +214,34 @@ private constructor( } /** The loaded tool definitions returned by the tool search output. */ - fun tools(tools: List) = tools(JsonField.of(tools)) + fun tools(tools: List) = tools(JsonField.of(tools)) /** * Sets [Builder.tools] to an arbitrary JSON value. * - * You should usually call [Builder.tools] with a well-typed `List` value instead. + * You should usually call [Builder.tools] with a well-typed `List` value instead. * This method is primarily for setting the field to an undocumented or not yet supported * value. */ - fun tools(tools: JsonField>) = apply { + fun tools(tools: JsonField>) = apply { this.tools = tools.map { it.toMutableList() } } /** - * Adds a single [Tool] to [tools]. + * Adds a single [BetaTool] to [tools]. * * @throws IllegalStateException if the field was previously set to a non-list. */ - fun addTool(tool: Tool) = apply { + fun addTool(tool: BetaTool) = apply { tools = (tools ?: JsonField.of(mutableListOf())).also { checkKnown("tools", it).add(tool) } } - /** Alias for calling [addTool] with `Tool.ofFunction(function)`. */ - fun addTool(function: BetaFunctionTool) = addTool(Tool.ofFunction(function)) + /** Alias for calling [addTool] with `BetaTool.ofFunction(function)`. */ + fun addTool(function: BetaFunctionTool) = addTool(BetaTool.ofFunction(function)) - /** Alias for calling [addTool] with `Tool.ofFileSearch(fileSearch)`. */ - fun addTool(fileSearch: BetaFileSearchTool) = addTool(Tool.ofFileSearch(fileSearch)) + /** Alias for calling [addTool] with `BetaTool.ofFileSearch(fileSearch)`. */ + fun addTool(fileSearch: BetaFileSearchTool) = addTool(BetaTool.ofFileSearch(fileSearch)) /** * Alias for calling [addTool] with the following: @@ -254,78 +254,80 @@ private constructor( fun addFileSearchTool(vectorStoreIds: List) = addTool(BetaFileSearchTool.builder().vectorStoreIds(vectorStoreIds).build()) - /** Alias for calling [addTool] with `Tool.ofComputer(computer)`. */ - fun addTool(computer: BetaComputerTool) = addTool(Tool.ofComputer(computer)) + /** Alias for calling [addTool] with `BetaTool.ofComputer(computer)`. */ + fun addTool(computer: BetaComputerTool) = addTool(BetaTool.ofComputer(computer)) - /** Alias for calling [addTool] with `Tool.ofComputerUsePreview(computerUsePreview)`. */ + /** Alias for calling [addTool] with `BetaTool.ofComputerUsePreview(computerUsePreview)`. */ fun addTool(computerUsePreview: BetaComputerUsePreviewTool) = - addTool(Tool.ofComputerUsePreview(computerUsePreview)) + addTool(BetaTool.ofComputerUsePreview(computerUsePreview)) - /** Alias for calling [addTool] with `Tool.ofBetaWebSearch(betaWebSearch)`. */ - fun addTool(betaWebSearch: BetaWebSearchTool) = addTool(Tool.ofBetaWebSearch(betaWebSearch)) + /** Alias for calling [addTool] with `BetaTool.ofWebSearch(webSearch)`. */ + fun addTool(webSearch: BetaWebSearchTool) = addTool(BetaTool.ofWebSearch(webSearch)) - /** Alias for calling [addTool] with `Tool.ofMcp(mcp)`. */ - fun addTool(mcp: Tool.Mcp) = addTool(Tool.ofMcp(mcp)) + /** Alias for calling [addTool] with `BetaTool.ofMcp(mcp)`. */ + fun addTool(mcp: BetaTool.Mcp) = addTool(BetaTool.ofMcp(mcp)) /** * Alias for calling [addTool] with the following: * ```java - * Tool.Mcp.builder() + * BetaTool.Mcp.builder() * .serverLabel(serverLabel) * .build() * ``` */ fun addMcpTool(serverLabel: String) = - addTool(Tool.Mcp.builder().serverLabel(serverLabel).build()) + addTool(BetaTool.Mcp.builder().serverLabel(serverLabel).build()) - /** Alias for calling [addTool] with `Tool.ofCodeInterpreter(codeInterpreter)`. */ - fun addTool(codeInterpreter: Tool.CodeInterpreter) = - addTool(Tool.ofCodeInterpreter(codeInterpreter)) + /** Alias for calling [addTool] with `BetaTool.ofCodeInterpreter(codeInterpreter)`. */ + fun addTool(codeInterpreter: BetaTool.CodeInterpreter) = + addTool(BetaTool.ofCodeInterpreter(codeInterpreter)) /** * Alias for calling [addTool] with the following: * ```java - * Tool.CodeInterpreter.builder() + * BetaTool.CodeInterpreter.builder() * .container(container) * .build() * ``` */ - fun addCodeInterpreterTool(container: Tool.CodeInterpreter.Container) = - addTool(Tool.CodeInterpreter.builder().container(container).build()) + fun addCodeInterpreterTool(container: BetaTool.CodeInterpreter.Container) = + addTool(BetaTool.CodeInterpreter.builder().container(container).build()) /** * Alias for calling [addCodeInterpreterTool] with - * `Tool.CodeInterpreter.Container.ofString(string)`. + * `BetaTool.CodeInterpreter.Container.ofString(string)`. */ fun addCodeInterpreterTool(string: String) = - addCodeInterpreterTool(Tool.CodeInterpreter.Container.ofString(string)) + addCodeInterpreterTool(BetaTool.CodeInterpreter.Container.ofString(string)) /** * Alias for calling [addCodeInterpreterTool] with - * `Tool.CodeInterpreter.Container.ofCodeInterpreterToolAuto(codeInterpreterToolAuto)`. + * `BetaTool.CodeInterpreter.Container.ofCodeInterpreterToolAuto(codeInterpreterToolAuto)`. */ fun addCodeInterpreterTool( - codeInterpreterToolAuto: Tool.CodeInterpreter.Container.CodeInterpreterToolAuto + codeInterpreterToolAuto: BetaTool.CodeInterpreter.Container.CodeInterpreterToolAuto ) = addCodeInterpreterTool( - Tool.CodeInterpreter.Container.ofCodeInterpreterToolAuto(codeInterpreterToolAuto) + BetaTool.CodeInterpreter.Container.ofCodeInterpreterToolAuto( + codeInterpreterToolAuto + ) ) - /** Alias for calling [addTool] with `Tool.ofProgrammaticToolCalling()`. */ - fun addToolProgrammaticToolCalling() = addTool(Tool.ofProgrammaticToolCalling()) + /** Alias for calling [addTool] with `BetaTool.ofProgrammaticToolCalling()`. */ + fun addToolProgrammaticToolCalling() = addTool(BetaTool.ofProgrammaticToolCalling()) - /** Alias for calling [addTool] with `Tool.ofImageGeneration(imageGeneration)`. */ - fun addTool(imageGeneration: Tool.ImageGeneration) = - addTool(Tool.ofImageGeneration(imageGeneration)) + /** Alias for calling [addTool] with `BetaTool.ofImageGeneration(imageGeneration)`. */ + fun addTool(imageGeneration: BetaTool.ImageGeneration) = + addTool(BetaTool.ofImageGeneration(imageGeneration)) - /** Alias for calling [addTool] with `Tool.ofLocalShell()`. */ - fun addToolLocalShell() = addTool(Tool.ofLocalShell()) + /** Alias for calling [addTool] with `BetaTool.ofLocalShell()`. */ + fun addToolLocalShell() = addTool(BetaTool.ofLocalShell()) - /** Alias for calling [addTool] with `Tool.ofShell(shell)`. */ - fun addTool(shell: BetaFunctionShellTool) = addTool(Tool.ofShell(shell)) + /** Alias for calling [addTool] with `BetaTool.ofShell(shell)`. */ + fun addTool(shell: BetaFunctionShellTool) = addTool(BetaTool.ofShell(shell)) - /** Alias for calling [addTool] with `Tool.ofCustom(custom)`. */ - fun addTool(custom: BetaCustomTool) = addTool(Tool.ofCustom(custom)) + /** Alias for calling [addTool] with `BetaTool.ofCustom(custom)`. */ + fun addTool(custom: BetaCustomTool) = addTool(BetaTool.ofCustom(custom)) /** * Alias for calling [addTool] with the following: @@ -337,19 +339,18 @@ private constructor( */ fun addCustomTool(name: String) = addTool(BetaCustomTool.builder().name(name).build()) - /** Alias for calling [addTool] with `Tool.ofNamespace(namespace)`. */ - fun addTool(namespace: BetaToolSearchOutputNamespaceTool) = - addTool(Tool.ofNamespace(namespace)) + /** Alias for calling [addTool] with `BetaTool.ofNamespace(namespace)`. */ + fun addTool(namespace: BetaNamespaceTool) = addTool(BetaTool.ofNamespace(namespace)) - /** Alias for calling [addTool] with `Tool.ofSearch(search)`. */ - fun addTool(search: BetaToolSearchTool) = addTool(Tool.ofSearch(search)) + /** Alias for calling [addTool] with `BetaTool.ofToolSearch(toolSearch)`. */ + fun addTool(toolSearch: BetaToolSearchTool) = addTool(BetaTool.ofToolSearch(toolSearch)) - /** Alias for calling [addTool] with `Tool.ofBetaWebSearchPreview(betaWebSearchPreview)`. */ - fun addTool(betaWebSearchPreview: BetaWebSearchPreviewTool) = - addTool(Tool.ofBetaWebSearchPreview(betaWebSearchPreview)) + /** Alias for calling [addTool] with `BetaTool.ofWebSearchPreview(webSearchPreview)`. */ + fun addTool(webSearchPreview: BetaWebSearchPreviewTool) = + addTool(BetaTool.ofWebSearchPreview(webSearchPreview)) - /** Alias for calling [addTool] with `Tool.ofApplyPatch(applyPatch)`. */ - fun addTool(applyPatch: BetaApplyPatchTool) = addTool(Tool.ofApplyPatch(applyPatch)) + /** Alias for calling [addTool] with `BetaTool.ofApplyPatch(applyPatch)`. */ + fun addTool(applyPatch: BetaApplyPatchTool) = addTool(BetaTool.ofApplyPatch(applyPatch)) /** * Sets the field to an arbitrary JSON value. diff --git a/openai-java-core/src/main/kotlin/com/openai/models/conversations/ConversationCreateParams.kt b/openai-java-core/src/main/kotlin/com/openai/models/conversations/ConversationCreateParams.kt index 9d9dec3f3..19098f4ad 100644 --- a/openai-java-core/src/main/kotlin/com/openai/models/conversations/ConversationCreateParams.kt +++ b/openai-java-core/src/main/kotlin/com/openai/models/conversations/ConversationCreateParams.kt @@ -265,7 +265,7 @@ private constructor( * .build() * ``` */ - fun addToolSearchOutputItem(tools: List) = apply { + fun addToolSearchOutputItem(tools: List) = apply { body.addToolSearchOutputItem(tools) } @@ -832,7 +832,7 @@ private constructor( * .build() * ``` */ - fun addToolSearchOutputItem(tools: List) = + fun addToolSearchOutputItem(tools: List) = addItem(ResponseToolSearchOutputItemParam.builder().tools(tools).build()) /** diff --git a/openai-java-core/src/main/kotlin/com/openai/models/conversations/items/ItemCreateParams.kt b/openai-java-core/src/main/kotlin/com/openai/models/conversations/items/ItemCreateParams.kt index 7a9ecc038..9ae674206 100644 --- a/openai-java-core/src/main/kotlin/com/openai/models/conversations/items/ItemCreateParams.kt +++ b/openai-java-core/src/main/kotlin/com/openai/models/conversations/items/ItemCreateParams.kt @@ -287,7 +287,7 @@ private constructor( * .build() * ``` */ - fun addToolSearchOutputItem(tools: List) = apply { + fun addToolSearchOutputItem(tools: List) = apply { body.addToolSearchOutputItem(tools) } @@ -827,7 +827,7 @@ private constructor( * .build() * ``` */ - fun addToolSearchOutputItem(tools: List) = + fun addToolSearchOutputItem(tools: List) = addItem(ResponseToolSearchOutputItemParam.builder().tools(tools).build()) /** diff --git a/openai-java-core/src/main/kotlin/com/openai/models/live/ResponseItemCreateEvent.kt b/openai-java-core/src/main/kotlin/com/openai/models/live/ResponseItemCreateEvent.kt index d95933660..fd2d1361a 100644 --- a/openai-java-core/src/main/kotlin/com/openai/models/live/ResponseItemCreateEvent.kt +++ b/openai-java-core/src/main/kotlin/com/openai/models/live/ResponseItemCreateEvent.kt @@ -260,7 +260,7 @@ private constructor( * .build() * ``` */ - fun toolSearchOutputItem(tools: List) = + fun toolSearchOutputItem(tools: List) = item(ResponseToolSearchOutputItemParam.builder().tools(tools).build()) /** Alias for calling [item] with `ResponseInputItem.ofAdditionalTools(additionalTools)`. */ diff --git a/openai-java-core/src/main/kotlin/com/openai/models/responses/ResponseToolSearchOutputItemParam.kt b/openai-java-core/src/main/kotlin/com/openai/models/responses/ResponseToolSearchOutputItemParam.kt index 89fbecd79..249d1b2f5 100644 --- a/openai-java-core/src/main/kotlin/com/openai/models/responses/ResponseToolSearchOutputItemParam.kt +++ b/openai-java-core/src/main/kotlin/com/openai/models/responses/ResponseToolSearchOutputItemParam.kt @@ -26,6 +26,7 @@ import com.openai.core.checkRequired import com.openai.core.getOrThrow import com.openai.core.toImmutable import com.openai.errors.OpenAIInvalidDataException +import com.openai.models.responses.Tool as ResponseTool import java.util.Collections import java.util.Objects import java.util.Optional @@ -34,7 +35,7 @@ import kotlin.jvm.optionals.getOrNull class ResponseToolSearchOutputItemParam @JsonCreator(mode = JsonCreator.Mode.DISABLED) private constructor( - private val tools: JsonField>, + private val tools: JsonField>, private val type: JsonValue, private val id: JsonField, private val callId: JsonField, @@ -45,7 +46,9 @@ private constructor( @JsonCreator private constructor( - @JsonProperty("tools") @ExcludeMissing tools: JsonField> = JsonMissing.of(), + @JsonProperty("tools") + @ExcludeMissing + tools: JsonField> = JsonMissing.of(), @JsonProperty("type") @ExcludeMissing type: JsonValue = JsonMissing.of(), @JsonProperty("id") @ExcludeMissing id: JsonField = JsonMissing.of(), @JsonProperty("call_id") @ExcludeMissing callId: JsonField = JsonMissing.of(), @@ -61,7 +64,7 @@ private constructor( * @throws OpenAIInvalidDataException if the JSON field has an unexpected type or is * unexpectedly missing or null (e.g. if the server responded with an unexpected value). */ - fun tools(): List = tools.getRequired("tools") + fun tools(): List = tools.getRequired("tools") /** * The item type. Always `tool_search_output`. @@ -113,7 +116,7 @@ private constructor( * * Unlike [tools], this method doesn't throw if the JSON field has an unexpected type. */ - @JsonProperty("tools") @ExcludeMissing fun _tools(): JsonField> = tools + @JsonProperty("tools") @ExcludeMissing fun _tools(): JsonField> = tools /** * Returns the raw JSON value of [id]. @@ -172,7 +175,7 @@ private constructor( /** A builder for [ResponseToolSearchOutputItemParam]. */ class Builder internal constructor() { - private var tools: JsonField>? = null + private var tools: JsonField>? = null private var type: JsonValue = JsonValue.from("tool_search_output") private var id: JsonField = JsonMissing.of() private var callId: JsonField = JsonMissing.of() @@ -194,34 +197,34 @@ private constructor( } /** The loaded tool definitions returned by the tool search output. */ - fun tools(tools: List) = tools(JsonField.of(tools)) + fun tools(tools: List) = tools(JsonField.of(tools)) /** * Sets [Builder.tools] to an arbitrary JSON value. * - * You should usually call [Builder.tools] with a well-typed `List` value instead. - * This method is primarily for setting the field to an undocumented or not yet supported - * value. + * You should usually call [Builder.tools] with a well-typed `List` value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. */ - fun tools(tools: JsonField>) = apply { + fun tools(tools: JsonField>) = apply { this.tools = tools.map { it.toMutableList() } } /** - * Adds a single [Tool] to [tools]. + * Adds a single [ResponseTool] to [tools]. * * @throws IllegalStateException if the field was previously set to a non-list. */ - fun addTool(tool: Tool) = apply { + fun addTool(tool: ResponseTool) = apply { tools = (tools ?: JsonField.of(mutableListOf())).also { checkKnown("tools", it).add(tool) } } - /** Alias for calling [addTool] with `Tool.ofFunction(function)`. */ - fun addTool(function: FunctionTool) = addTool(Tool.ofFunction(function)) + /** Alias for calling [addTool] with `ResponseTool.ofFunction(function)`. */ + fun addTool(function: FunctionTool) = addTool(ResponseTool.ofFunction(function)) - /** Alias for calling [addTool] with `Tool.ofFileSearch(fileSearch)`. */ - fun addTool(fileSearch: FileSearchTool) = addTool(Tool.ofFileSearch(fileSearch)) + /** Alias for calling [addTool] with `ResponseTool.ofFileSearch(fileSearch)`. */ + fun addTool(fileSearch: FileSearchTool) = addTool(ResponseTool.ofFileSearch(fileSearch)) /** * Alias for calling [addTool] with the following: @@ -234,78 +237,82 @@ private constructor( fun addFileSearchTool(vectorStoreIds: List) = addTool(FileSearchTool.builder().vectorStoreIds(vectorStoreIds).build()) - /** Alias for calling [addTool] with `Tool.ofComputer(computer)`. */ - fun addTool(computer: ComputerTool) = addTool(Tool.ofComputer(computer)) + /** Alias for calling [addTool] with `ResponseTool.ofComputer(computer)`. */ + fun addTool(computer: ComputerTool) = addTool(ResponseTool.ofComputer(computer)) - /** Alias for calling [addTool] with `Tool.ofComputerUsePreview(computerUsePreview)`. */ + /** + * Alias for calling [addTool] with `ResponseTool.ofComputerUsePreview(computerUsePreview)`. + */ fun addTool(computerUsePreview: ComputerUsePreviewTool) = - addTool(Tool.ofComputerUsePreview(computerUsePreview)) + addTool(ResponseTool.ofComputerUsePreview(computerUsePreview)) - /** Alias for calling [addTool] with `Tool.ofWebSearch(webSearch)`. */ - fun addTool(webSearch: WebSearchTool) = addTool(Tool.ofWebSearch(webSearch)) + /** Alias for calling [addTool] with `ResponseTool.ofWebSearch(webSearch)`. */ + fun addTool(webSearch: WebSearchTool) = addTool(ResponseTool.ofWebSearch(webSearch)) - /** Alias for calling [addTool] with `Tool.ofMcp(mcp)`. */ - fun addTool(mcp: Tool.Mcp) = addTool(Tool.ofMcp(mcp)) + /** Alias for calling [addTool] with `ResponseTool.ofMcp(mcp)`. */ + fun addTool(mcp: ResponseTool.Mcp) = addTool(ResponseTool.ofMcp(mcp)) /** * Alias for calling [addTool] with the following: * ```java - * Tool.Mcp.builder() + * ResponseTool.Mcp.builder() * .serverLabel(serverLabel) * .build() * ``` */ fun addMcpTool(serverLabel: String) = - addTool(Tool.Mcp.builder().serverLabel(serverLabel).build()) + addTool(ResponseTool.Mcp.builder().serverLabel(serverLabel).build()) - /** Alias for calling [addTool] with `Tool.ofCodeInterpreter(codeInterpreter)`. */ - fun addTool(codeInterpreter: Tool.CodeInterpreter) = - addTool(Tool.ofCodeInterpreter(codeInterpreter)) + /** Alias for calling [addTool] with `ResponseTool.ofCodeInterpreter(codeInterpreter)`. */ + fun addTool(codeInterpreter: ResponseTool.CodeInterpreter) = + addTool(ResponseTool.ofCodeInterpreter(codeInterpreter)) /** * Alias for calling [addTool] with the following: * ```java - * Tool.CodeInterpreter.builder() + * ResponseTool.CodeInterpreter.builder() * .container(container) * .build() * ``` */ - fun addCodeInterpreterTool(container: Tool.CodeInterpreter.Container) = - addTool(Tool.CodeInterpreter.builder().container(container).build()) + fun addCodeInterpreterTool(container: ResponseTool.CodeInterpreter.Container) = + addTool(ResponseTool.CodeInterpreter.builder().container(container).build()) /** * Alias for calling [addCodeInterpreterTool] with - * `Tool.CodeInterpreter.Container.ofString(string)`. + * `ResponseTool.CodeInterpreter.Container.ofString(string)`. */ fun addCodeInterpreterTool(string: String) = - addCodeInterpreterTool(Tool.CodeInterpreter.Container.ofString(string)) + addCodeInterpreterTool(ResponseTool.CodeInterpreter.Container.ofString(string)) /** * Alias for calling [addCodeInterpreterTool] with - * `Tool.CodeInterpreter.Container.ofCodeInterpreterToolAuto(codeInterpreterToolAuto)`. + * `ResponseTool.CodeInterpreter.Container.ofCodeInterpreterToolAuto(codeInterpreterToolAuto)`. */ fun addCodeInterpreterTool( - codeInterpreterToolAuto: Tool.CodeInterpreter.Container.CodeInterpreterToolAuto + codeInterpreterToolAuto: ResponseTool.CodeInterpreter.Container.CodeInterpreterToolAuto ) = addCodeInterpreterTool( - Tool.CodeInterpreter.Container.ofCodeInterpreterToolAuto(codeInterpreterToolAuto) + ResponseTool.CodeInterpreter.Container.ofCodeInterpreterToolAuto( + codeInterpreterToolAuto + ) ) - /** Alias for calling [addTool] with `Tool.ofProgrammaticToolCalling()`. */ - fun addToolProgrammaticToolCalling() = addTool(Tool.ofProgrammaticToolCalling()) + /** Alias for calling [addTool] with `ResponseTool.ofProgrammaticToolCalling()`. */ + fun addToolProgrammaticToolCalling() = addTool(ResponseTool.ofProgrammaticToolCalling()) - /** Alias for calling [addTool] with `Tool.ofImageGeneration(imageGeneration)`. */ - fun addTool(imageGeneration: Tool.ImageGeneration) = - addTool(Tool.ofImageGeneration(imageGeneration)) + /** Alias for calling [addTool] with `ResponseTool.ofImageGeneration(imageGeneration)`. */ + fun addTool(imageGeneration: ResponseTool.ImageGeneration) = + addTool(ResponseTool.ofImageGeneration(imageGeneration)) - /** Alias for calling [addTool] with `Tool.ofLocalShell()`. */ - fun addToolLocalShell() = addTool(Tool.ofLocalShell()) + /** Alias for calling [addTool] with `ResponseTool.ofLocalShell()`. */ + fun addToolLocalShell() = addTool(ResponseTool.ofLocalShell()) - /** Alias for calling [addTool] with `Tool.ofShell(shell)`. */ - fun addTool(shell: FunctionShellTool) = addTool(Tool.ofShell(shell)) + /** Alias for calling [addTool] with `ResponseTool.ofShell(shell)`. */ + fun addTool(shell: FunctionShellTool) = addTool(ResponseTool.ofShell(shell)) - /** Alias for calling [addTool] with `Tool.ofCustom(custom)`. */ - fun addTool(custom: CustomTool) = addTool(Tool.ofCustom(custom)) + /** Alias for calling [addTool] with `ResponseTool.ofCustom(custom)`. */ + fun addTool(custom: CustomTool) = addTool(ResponseTool.ofCustom(custom)) /** * Alias for calling [addTool] with the following: @@ -317,18 +324,18 @@ private constructor( */ fun addCustomTool(name: String) = addTool(CustomTool.builder().name(name).build()) - /** Alias for calling [addTool] with `Tool.ofNamespace(namespace)`. */ - fun addTool(namespace: ToolSearchOutputNamespaceTool) = addTool(Tool.ofNamespace(namespace)) + /** Alias for calling [addTool] with `ResponseTool.ofNamespace(namespace)`. */ + fun addTool(namespace: NamespaceTool) = addTool(ResponseTool.ofNamespace(namespace)) - /** Alias for calling [addTool] with `Tool.ofSearch(search)`. */ - fun addTool(search: ToolSearchTool) = addTool(Tool.ofSearch(search)) + /** Alias for calling [addTool] with `ResponseTool.ofSearch(search)`. */ + fun addTool(search: ToolSearchTool) = addTool(ResponseTool.ofSearch(search)) - /** Alias for calling [addTool] with `Tool.ofWebSearchPreview(webSearchPreview)`. */ + /** Alias for calling [addTool] with `ResponseTool.ofWebSearchPreview(webSearchPreview)`. */ fun addTool(webSearchPreview: WebSearchPreviewTool) = - addTool(Tool.ofWebSearchPreview(webSearchPreview)) + addTool(ResponseTool.ofWebSearchPreview(webSearchPreview)) - /** Alias for calling [addTool] with `Tool.ofApplyPatch(applyPatch)`. */ - fun addTool(applyPatch: ApplyPatchTool) = addTool(Tool.ofApplyPatch(applyPatch)) + /** Alias for calling [addTool] with `ResponseTool.ofApplyPatch(applyPatch)`. */ + fun addTool(applyPatch: ApplyPatchTool) = addTool(ResponseTool.ofApplyPatch(applyPatch)) /** * Sets the field to an arbitrary JSON value. diff --git a/openai-java-core/src/test/kotlin/com/openai/models/beta/responses/BetaResponseToolSearchOutputItemParamTest.kt b/openai-java-core/src/test/kotlin/com/openai/models/beta/responses/BetaResponseToolSearchOutputItemParamTest.kt index 1450596e8..3a2891e76 100644 --- a/openai-java-core/src/test/kotlin/com/openai/models/beta/responses/BetaResponseToolSearchOutputItemParamTest.kt +++ b/openai-java-core/src/test/kotlin/com/openai/models/beta/responses/BetaResponseToolSearchOutputItemParamTest.kt @@ -47,7 +47,7 @@ internal class BetaResponseToolSearchOutputItemParamTest { assertThat(betaResponseToolSearchOutputItemParam.tools()) .containsExactly( - BetaResponseToolSearchOutputItemParam.Tool.ofFunction( + BetaTool.ofFunction( BetaFunctionTool.builder() .name("name") .parameters( diff --git a/openai-java-core/src/test/kotlin/com/openai/models/responses/ResponseToolSearchOutputItemParamTest.kt b/openai-java-core/src/test/kotlin/com/openai/models/responses/ResponseToolSearchOutputItemParamTest.kt index 2c77f8c1a..f5d1f6644 100644 --- a/openai-java-core/src/test/kotlin/com/openai/models/responses/ResponseToolSearchOutputItemParamTest.kt +++ b/openai-java-core/src/test/kotlin/com/openai/models/responses/ResponseToolSearchOutputItemParamTest.kt @@ -42,7 +42,7 @@ internal class ResponseToolSearchOutputItemParamTest { assertThat(responseToolSearchOutputItemParam.tools()) .containsExactly( - ResponseToolSearchOutputItemParam.Tool.ofFunction( + Tool.ofFunction( FunctionTool.builder() .name("name") .parameters(