diff --git a/.castiron.stats.yml b/.castiron.stats.yml index 37c050684..1397c84cf 100644 --- a/.castiron.stats.yml +++ b/.castiron.stats.yml @@ -1,8 +1,8 @@ schema_version: 1 -generation_id: e941c680-c608-4142-9d0f-873195d8ea87 -openapi_spec_hash: ff5fdbe2c1e455ca55c9c427b5bbec0c -openapi_transformed_spec_hash: 0f3ba6dad63aafb94f36e9d01dfb4fb7 -config_hash: d20eb52e22a3974a6dd96fc43ad2e9ff -codegen_sha: c94f6cbff012cd6f6deefaf8f299c3c2a9ebb900 -codegen_hash: 499a1af2d6a943ad368749fe812c4e6b29057ee0e9154cfcb35de0c2343bbcf8 -public_codegen_sha: f79d8ab2183768db64a55a0318bf62e4b7963acf +generation_id: 8c9e3897-4c48-4c26-86df-bd59444b2fec +openapi_spec_hash: ecacd6dd6ab0f674b9f28ceb4112d474 +openapi_transformed_spec_hash: deffabb76b77bcd99281cc77230009fc +config_hash: 54096ce9d49f88b28e0dff9df4b451a5 +codegen_sha: 793b4f33c4125f91b695b7f79805e36b453a32f6 +codegen_hash: 9389a1e825f83f0cfb49adf5bc002930c5c47c9db4000407f27f5a8094e0afdd +public_codegen_sha: 514e3eae6f109f73581c4f852111cf8a73e216d5 diff --git a/api_reference/openapi.transformed.yml b/api_reference/openapi.transformed.yml index e2f9fe313..d2e3fb3fe 100644 --- a/api_reference/openapi.transformed.yml +++ b/api_reference/openapi.transformed.yml @@ -50,6 +50,188 @@ tags: - name: Audit Logs description: List user actions and configuration changes within this organization. paths: + /organization/usage/decisions: + get: + summary: Decisions + description: Get Decisions API usage details for the organization. + operationId: OrganizationDecisionsusage + parameters: + - name: start_time + in: query + description: Start time (Unix seconds) of the query time range, inclusive. + required: true + schema: + type: integer + - name: end_time + in: query + description: End time (Unix seconds) of the query time range, exclusive. + required: false + schema: + anyOf: + - type: integer + - type: 'null' + - name: bucket_width + in: query + description: Width of each time bucket in response. Currently `1m`, `1h` and `1d` are supported, default to `1d`. + required: false + schema: + anyOf: + - description: Width of each time bucket in response. Currently `1m`, `1h` and `1d` are supported, default to `1d`. + anyOf: + - $ref: '#/components/schemas/DecisionsUsageBucketWidth' + - type: 'null' + - name: limit + in: query + description: |- + Specifies the number of buckets to return. + - `bucket_width=1d`: default: 7, max: 31 + - `bucket_width=1h`: default: 24, max: 168 + - `bucket_width=1m`: default: 60, max: 1440 + required: false + schema: + anyOf: + - type: integer + - type: 'null' + - name: page + in: query + description: A cursor for use in pagination. Corresponding to the `next_page` field from the previous response. + required: false + schema: + anyOf: + - description: A cursor for use in pagination. Corresponding to the `next_page` field from the previous response. + type: string + - type: 'null' + - name: project_ids + in: query + description: Return only usage for these projects. + required: false + schema: + anyOf: + - description: Return only usage for these projects. + anyOf: + - type: array + items: + type: string + - type: 'null' + - name: group_by + in: query + description: Group the usage data by the specified fields. Support fields include `project_id`, `user_id`, `api_key_id`, `model`, `batch`, `service_tier`, `api_source` or any combination of them. When grouped by `api_source`, results use `agents_api` for attributed Agents API activity and `unlabeled` for all other activity. Without source grouping, `api_source` is null. + required: false + schema: + anyOf: + - description: Group the usage data by the specified fields. Support fields include `project_id`, `user_id`, `api_key_id`, `model`, `batch`, `service_tier`, `api_source` or any combination of them. When grouped by `api_source`, results use `agents_api` for attributed Agents API activity and `unlabeled` for all other activity. Without source grouping, `api_source` is null. + anyOf: + - type: array + items: + $ref: '#/components/schemas/DecisionsUsageGroupBy' + - type: 'null' + - name: user_ids + in: query + description: Return only usage for these users. + required: false + schema: + anyOf: + - description: Return only usage for these users. + anyOf: + - type: array + items: + type: string + - type: 'null' + - name: api_key_ids + in: query + description: Return only usage for these API keys. + required: false + schema: + anyOf: + - description: Return only usage for these API keys. + anyOf: + - type: array + items: + type: string + - type: 'null' + - name: models + in: query + description: Return only usage for these models. + required: false + schema: + anyOf: + - description: Return only usage for these models. + anyOf: + - type: array + items: + type: string + - type: 'null' + - name: batch + in: query + description: If `true`, return batch jobs only. If `false`, return non-batch jobs only. By default, return both. + required: false + schema: + anyOf: + - type: boolean + - type: 'null' + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/PublicDecisionsUsageResponseResource' + '400': + description: The request parameters are invalid or the requested operation cannot be performed. + content: + application/json: + schema: + $ref: '#/components/schemas/DecisionsUsageErrorResponse' + '403': + description: The caller does not have permission to perform this operation. + content: + application/json: + schema: + $ref: '#/components/schemas/DecisionsUsagePermissionErrorResponse' + '429': + $ref: '#/components/responses/TooManyRequests' + x-oaiMeta: + group: usage-decisions + examples: + request: + curl: | + curl --get "https://api.openai.com/v1/organization/usage/decisions" \ + -H "Authorization: Bearer $OPENAI_ADMIN_KEY" \ + --data-urlencode "start_time=1790812800" \ + --data-urlencode "end_time=1790899200" \ + --data-urlencode "bucket_width=1d" \ + --data-urlencode "group_by=project_id" \ + --data-urlencode "group_by=model" + response: | + { + "object": "page", + "data": [ + { + "object": "bucket", + "start_time": 1790812800, + "end_time": 1790899200, + "results": [ + { + "object": "organization.usage.decisions.result", + "input_tokens": 1000, + "input_cached_tokens": 400, + "output_tokens": 0, + "num_model_requests": 5, + "project_id": "proj_example", + "model": "gpt-6-luna", + "user_id": null, + "api_key_id": null, + "batch": null, + "service_tier": null + } + ] + } + ], + "has_more": false, + "next_page": null + } + security: + - AdminApiKeyAuth: [] /assistants: get: operationId: listAssistants @@ -36728,6 +36910,235 @@ webhooks: description: Return any 2xx status code to acknowledge receipt. A 410 Gone response also stops retries; other non-2xx responses are retried. components: schemas: + DecisionsUsageBucketWidth: + type: string + enum: + - 1m + - 1h + - 1d + DecisionsUsageGroupBy: + type: string + enum: + - project_id + - user_id + - api_key_id + - model + - batch + - service_tier + - api_source + DecisionsUsageApiSource: + type: string + enum: + - agents_api + - unlabeled + DecisionsUsageResult: + properties: + api_source: + anyOf: + - $ref: '#/components/schemas/DecisionsUsageApiSource' + description: When grouped by `api_source`, `agents_api` identifies attributed Agents API activity and `unlabeled` includes all records without published source attribution, including historical and unknown origins. Unlabeled does not imply direct API usage. Without source grouping, this field is null. + - type: 'null' + object: + type: string + enum: + - organization.usage.decisions.result + default: organization.usage.decisions.result + x-stainless-const: true + input_tokens: + type: integer + description: The aggregated number of input tokens used, including cached and cache-write tokens. This includes text, audio, and image tokens. For customers subscribed to Scale Tier, this includes Scale Tier tokens. + input_cached_tokens: + anyOf: + - type: integer + description: The aggregated number of cached input tokens used across text, audio, and image inputs. For customers subscribed to Scale Tier, this includes Scale Tier tokens. + - type: 'null' + input_cache_write_tokens: + anyOf: + - type: integer + description: The aggregated number of input tokens written to the cache with a 30-minute retention period. + - type: 'null' + input_cache_write_12h_tokens: + anyOf: + - type: integer + description: The aggregated number of input tokens written to the cache with a 12-hour retention period. + - type: 'null' + input_uncached_tokens: + anyOf: + - type: integer + description: The aggregated number of uncached input tokens used across text, audio, and image inputs, excluding cache-write tokens. + - type: 'null' + output_tokens: + type: integer + description: The aggregated number of output tokens used across text, audio, and image outputs. For customers subscribed to Scale Tier, this includes Scale Tier tokens. + input_text_tokens: + anyOf: + - type: integer + description: The aggregated number of uncached text input tokens used, excluding cache-write tokens. + - type: 'null' + output_text_tokens: + anyOf: + - type: integer + description: The aggregated number of text output tokens used. + - type: 'null' + input_cached_text_tokens: + anyOf: + - type: integer + description: The aggregated number of cached text input tokens used. + - type: 'null' + input_audio_tokens: + anyOf: + - type: integer + description: The aggregated number of uncached audio input tokens used. + - type: 'null' + input_cached_audio_tokens: + anyOf: + - type: integer + description: The aggregated number of cached audio input tokens used. + - type: 'null' + output_audio_tokens: + anyOf: + - type: integer + description: The aggregated number of audio output tokens used. + - type: 'null' + input_image_tokens: + anyOf: + - type: integer + description: The aggregated number of uncached image input tokens used. + - type: 'null' + input_cached_image_tokens: + anyOf: + - type: integer + description: The aggregated number of cached image input tokens used. + - type: 'null' + output_image_tokens: + anyOf: + - type: integer + description: The aggregated number of image output tokens used. + - type: 'null' + num_model_requests: + type: integer + description: The count of requests made to the model. + project_id: + anyOf: + - type: string + description: When `group_by=project_id`, this field provides the project ID of the grouped usage result. + - type: 'null' + user_id: + anyOf: + - type: string + description: When `group_by=user_id`, this field provides the user ID of the grouped usage result. + - type: 'null' + api_key_id: + anyOf: + - type: string + description: When `group_by=api_key_id`, this field provides the API key ID of the grouped usage result. + - type: 'null' + model: + anyOf: + - type: string + description: When `group_by=model`, this field provides the model name of the grouped usage result. + - type: 'null' + batch: + anyOf: + - type: boolean + description: When `group_by=batch`, this field tells whether the grouped usage result is batch or not. + - type: 'null' + service_tier: + anyOf: + - type: string + description: When `group_by=service_tier`, this field provides the service tier of the grouped usage result. + - type: 'null' + type: object + required: + - object + - input_tokens + - output_tokens + - num_model_requests + description: The aggregated Decisions API usage details of the specific time bucket. + DecisionsUsageBucket: + properties: + object: + type: string + enum: + - bucket + default: bucket + x-stainless-const: true + start_time: + type: integer + end_time: + type: integer + results: + items: + $ref: '#/components/schemas/DecisionsUsageResult' + type: array + type: object + required: + - object + - start_time + - end_time + - results + PublicDecisionsUsageResponseResource: + properties: + object: + type: string + enum: + - page + default: page + x-stainless-const: true + has_more: + type: boolean + next_page: + anyOf: + - type: string + - type: 'null' + data: + items: + $ref: '#/components/schemas/DecisionsUsageBucket' + type: array + type: object + required: + - object + - has_more + - next_page + - data + DecisionsUsageErrorDetails: + properties: + code: + anyOf: + - type: string + - type: 'null' + message: + type: string + param: + anyOf: + - type: string + - type: 'null' + type: + type: string + type: object + required: + - code + - message + - param + - type + DecisionsUsageErrorResponse: + properties: + error: + $ref: '#/components/schemas/DecisionsUsageErrorDetails' + type: object + required: + - error + DecisionsUsagePermissionErrorResponse: + properties: + error: + description: Details about the permission error. + anyOf: + - $ref: '#/components/schemas/DecisionsUsageErrorDetails' + - type: string + description: An explanation of the missing API permissions. + type: object + required: + - error AddUploadPartRequest: type: object additionalProperties: false diff --git a/openai-java-core/src/main/kotlin/com/openai/models/admin/organization/usage/UsageDecisionsParams.kt b/openai-java-core/src/main/kotlin/com/openai/models/admin/organization/usage/UsageDecisionsParams.kt new file mode 100644 index 000000000..fa420ee43 --- /dev/null +++ b/openai-java-core/src/main/kotlin/com/openai/models/admin/organization/usage/UsageDecisionsParams.kt @@ -0,0 +1,795 @@ +// File generated from our OpenAPI spec by Castiron. See CONTRIBUTING.md for details. + +package com.openai.models.admin.organization.usage + +import com.fasterxml.jackson.annotation.JsonCreator +import com.openai.core.Enum +import com.openai.core.JsonField +import com.openai.core.Params +import com.openai.core.checkRequired +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.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +/** Get Decisions API usage details for the organization. */ +class UsageDecisionsParams +private constructor( + private val startTime: Long, + private val apiKeyIds: List?, + private val batch: Boolean?, + private val bucketWidth: BucketWidth?, + private val endTime: Long?, + private val groupBy: List?, + private val limit: Long?, + private val models: List?, + private val page: String?, + private val projectIds: List?, + private val userIds: List?, + private val additionalHeaders: Headers, + private val additionalQueryParams: QueryParams, +) : Params { + + /** Start time (Unix seconds) of the query time range, inclusive. */ + fun startTime(): Long = startTime + + /** Return only usage for these API keys. */ + fun apiKeyIds(): Optional> = Optional.ofNullable(apiKeyIds) + + /** + * If `true`, return batch jobs only. If `false`, return non-batch jobs only. By default, return + * both. + */ + fun batch(): Optional = Optional.ofNullable(batch) + + /** + * Width of each time bucket in response. Currently `1m`, `1h` and `1d` are supported, default + * to `1d`. + */ + fun bucketWidth(): Optional = Optional.ofNullable(bucketWidth) + + /** End time (Unix seconds) of the query time range, exclusive. */ + fun endTime(): Optional = Optional.ofNullable(endTime) + + /** + * Group the usage data by the specified fields. Support fields include `project_id`, `user_id`, + * `api_key_id`, `model`, `batch`, `service_tier`, `api_source` or any combination of them. When + * grouped by `api_source`, results use `agents_api` for attributed Agents API activity and + * `unlabeled` for all other activity. Without source grouping, `api_source` is null. + */ + fun groupBy(): Optional> = Optional.ofNullable(groupBy) + + /** + * Specifies the number of buckets to return. + * - `bucket_width=1d`: default: 7, max: 31 + * - `bucket_width=1h`: default: 24, max: 168 + * - `bucket_width=1m`: default: 60, max: 1440 + */ + fun limit(): Optional = Optional.ofNullable(limit) + + /** Return only usage for these models. */ + fun models(): Optional> = Optional.ofNullable(models) + + /** + * A cursor for use in pagination. Corresponding to the `next_page` field from the previous + * response. + */ + fun page(): Optional = Optional.ofNullable(page) + + /** Return only usage for these projects. */ + fun projectIds(): Optional> = Optional.ofNullable(projectIds) + + /** Return only usage for these users. */ + fun userIds(): Optional> = Optional.ofNullable(userIds) + + /** 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 [UsageDecisionsParams]. + * + * The following fields are required: + * ```java + * .startTime() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [UsageDecisionsParams]. */ + class Builder internal constructor() { + + private var startTime: Long? = null + private var apiKeyIds: MutableList? = null + private var batch: Boolean? = null + private var bucketWidth: BucketWidth? = null + private var endTime: Long? = null + private var groupBy: MutableList? = null + private var limit: Long? = null + private var models: MutableList? = null + private var page: String? = null + private var projectIds: MutableList? = null + private var userIds: MutableList? = null + private var additionalHeaders: Headers.Builder = Headers.builder() + private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() + + @JvmSynthetic + internal fun from(usageDecisionsParams: UsageDecisionsParams) = apply { + startTime = usageDecisionsParams.startTime + apiKeyIds = usageDecisionsParams.apiKeyIds?.toMutableList() + batch = usageDecisionsParams.batch + bucketWidth = usageDecisionsParams.bucketWidth + endTime = usageDecisionsParams.endTime + groupBy = usageDecisionsParams.groupBy?.toMutableList() + limit = usageDecisionsParams.limit + models = usageDecisionsParams.models?.toMutableList() + page = usageDecisionsParams.page + projectIds = usageDecisionsParams.projectIds?.toMutableList() + userIds = usageDecisionsParams.userIds?.toMutableList() + additionalHeaders = usageDecisionsParams.additionalHeaders.toBuilder() + additionalQueryParams = usageDecisionsParams.additionalQueryParams.toBuilder() + } + + /** Start time (Unix seconds) of the query time range, inclusive. */ + fun startTime(startTime: Long) = apply { this.startTime = startTime } + + /** Return only usage for these API keys. */ + fun apiKeyIds(apiKeyIds: List?) = apply { + this.apiKeyIds = apiKeyIds?.toMutableList() + } + + /** Alias for calling [Builder.apiKeyIds] with `apiKeyIds.orElse(null)`. */ + fun apiKeyIds(apiKeyIds: Optional>) = apiKeyIds(apiKeyIds.getOrNull()) + + /** + * Adds a single [String] to [apiKeyIds]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addApiKeyId(apiKeyId: String) = apply { + apiKeyIds = (apiKeyIds ?: mutableListOf()).apply { add(apiKeyId) } + } + + /** + * If `true`, return batch jobs only. If `false`, return non-batch jobs only. By default, + * return both. + */ + fun batch(batch: Boolean?) = apply { this.batch = batch } + + /** + * Alias for [Builder.batch]. + * + * This unboxed primitive overload exists for backwards compatibility. + */ + fun batch(batch: Boolean) = batch(batch as Boolean?) + + /** Alias for calling [Builder.batch] with `batch.orElse(null)`. */ + fun batch(batch: Optional) = batch(batch.getOrNull()) + + /** + * Width of each time bucket in response. Currently `1m`, `1h` and `1d` are supported, + * default to `1d`. + */ + fun bucketWidth(bucketWidth: BucketWidth?) = apply { this.bucketWidth = bucketWidth } + + /** Alias for calling [Builder.bucketWidth] with `bucketWidth.orElse(null)`. */ + fun bucketWidth(bucketWidth: Optional) = bucketWidth(bucketWidth.getOrNull()) + + /** End time (Unix seconds) of the query time range, exclusive. */ + fun endTime(endTime: Long?) = apply { this.endTime = endTime } + + /** + * Alias for [Builder.endTime]. + * + * This unboxed primitive overload exists for backwards compatibility. + */ + fun endTime(endTime: Long) = endTime(endTime as Long?) + + /** Alias for calling [Builder.endTime] with `endTime.orElse(null)`. */ + fun endTime(endTime: Optional) = endTime(endTime.getOrNull()) + + /** + * Group the usage data by the specified fields. Support fields include `project_id`, + * `user_id`, `api_key_id`, `model`, `batch`, `service_tier`, `api_source` or any + * combination of them. When grouped by `api_source`, results use `agents_api` for + * attributed Agents API activity and `unlabeled` for all other activity. Without source + * grouping, `api_source` is null. + */ + fun groupBy(groupBy: List?) = apply { this.groupBy = groupBy?.toMutableList() } + + /** Alias for calling [Builder.groupBy] with `groupBy.orElse(null)`. */ + fun groupBy(groupBy: Optional>) = groupBy(groupBy.getOrNull()) + + /** + * Adds a single [GroupBy] to [Builder.groupBy]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addGroupBy(groupBy: GroupBy) = apply { + this.groupBy = (this.groupBy ?: mutableListOf()).apply { add(groupBy) } + } + + /** + * Specifies the number of buckets to return. + * - `bucket_width=1d`: default: 7, max: 31 + * - `bucket_width=1h`: default: 24, max: 168 + * - `bucket_width=1m`: default: 60, max: 1440 + */ + fun limit(limit: Long?) = apply { this.limit = limit } + + /** + * Alias for [Builder.limit]. + * + * This unboxed primitive overload exists for backwards compatibility. + */ + fun limit(limit: Long) = limit(limit as Long?) + + /** Alias for calling [Builder.limit] with `limit.orElse(null)`. */ + fun limit(limit: Optional) = limit(limit.getOrNull()) + + /** Return only usage for these models. */ + fun models(models: List?) = apply { this.models = models?.toMutableList() } + + /** Alias for calling [Builder.models] with `models.orElse(null)`. */ + fun models(models: Optional>) = models(models.getOrNull()) + + /** + * Adds a single [String] to [models]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addModel(model: String) = apply { + models = (models ?: mutableListOf()).apply { add(model) } + } + + /** + * A cursor for use in pagination. Corresponding to the `next_page` field from the previous + * response. + */ + fun page(page: String?) = apply { this.page = page } + + /** Alias for calling [Builder.page] with `page.orElse(null)`. */ + fun page(page: Optional) = page(page.getOrNull()) + + /** Return only usage for these projects. */ + fun projectIds(projectIds: List?) = apply { + this.projectIds = projectIds?.toMutableList() + } + + /** Alias for calling [Builder.projectIds] with `projectIds.orElse(null)`. */ + fun projectIds(projectIds: Optional>) = projectIds(projectIds.getOrNull()) + + /** + * Adds a single [String] to [projectIds]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addProjectId(projectId: String) = apply { + projectIds = (projectIds ?: mutableListOf()).apply { add(projectId) } + } + + /** Return only usage for these users. */ + fun userIds(userIds: List?) = apply { this.userIds = userIds?.toMutableList() } + + /** Alias for calling [Builder.userIds] with `userIds.orElse(null)`. */ + fun userIds(userIds: Optional>) = userIds(userIds.getOrNull()) + + /** + * Adds a single [String] to [userIds]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addUserId(userId: String) = apply { + userIds = (userIds ?: mutableListOf()).apply { add(userId) } + } + + 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 [UsageDecisionsParams]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .startTime() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): UsageDecisionsParams = + UsageDecisionsParams( + checkRequired("startTime", startTime), + apiKeyIds?.toImmutable(), + batch, + bucketWidth, + endTime, + groupBy?.toImmutable(), + limit, + models?.toImmutable(), + page, + projectIds?.toImmutable(), + userIds?.toImmutable(), + additionalHeaders.build(), + additionalQueryParams.build(), + ) + } + + override fun _headers(): Headers = additionalHeaders + + override fun _queryParams(): QueryParams = + QueryParams.builder() + .apply { + put("start_time", startTime.toString()) + apiKeyIds?.forEach { put("api_key_ids[]", it) } + batch?.let { put("batch", it.toString()) } + bucketWidth?.let { put("bucket_width", it.toString()) } + endTime?.let { put("end_time", it.toString()) } + groupBy?.forEach { put("group_by[]", it.toString()) } + limit?.let { put("limit", it.toString()) } + models?.forEach { put("models[]", it) } + page?.let { put("page", it) } + projectIds?.forEach { put("project_ids[]", it) } + userIds?.forEach { put("user_ids[]", it) } + putAll(additionalQueryParams) + } + .build() + + /** + * Width of each time bucket in response. Currently `1m`, `1h` and `1d` are supported, default + * to `1d`. + */ + class BucketWidth @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 _1M = of("1m") + + @JvmField val _1H = of("1h") + + @JvmField val _1D = of("1d") + + @JvmStatic fun of(value: String) = BucketWidth(JsonField.of(value)) + } + + /** An enum containing [BucketWidth]'s known values. */ + enum class Known { + _1M, + _1H, + _1D, + } + + /** + * An enum containing [BucketWidth]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [BucketWidth] 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 { + _1M, + _1H, + _1D, + /** + * An enum member indicating that [BucketWidth] 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) { + _1M -> Value._1M + _1H -> Value._1H + _1D -> Value._1D + 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) { + _1M -> Known._1M + _1H -> Known._1H + _1D -> Known._1D + else -> throw OpenAIInvalidDataException("Unknown BucketWidth: $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(): BucketWidth = 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 BucketWidth && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + class GroupBy @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 PROJECT_ID = of("project_id") + + @JvmField val USER_ID = of("user_id") + + @JvmField val API_KEY_ID = of("api_key_id") + + @JvmField val MODEL = of("model") + + @JvmField val BATCH = of("batch") + + @JvmField val SERVICE_TIER = of("service_tier") + + @JvmField val API_SOURCE = of("api_source") + + @JvmStatic fun of(value: String) = GroupBy(JsonField.of(value)) + } + + /** An enum containing [GroupBy]'s known values. */ + enum class Known { + PROJECT_ID, + USER_ID, + API_KEY_ID, + MODEL, + BATCH, + SERVICE_TIER, + API_SOURCE, + } + + /** + * An enum containing [GroupBy]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [GroupBy] 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 { + PROJECT_ID, + USER_ID, + API_KEY_ID, + MODEL, + BATCH, + SERVICE_TIER, + API_SOURCE, + /** An enum member indicating that [GroupBy] 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) { + PROJECT_ID -> Value.PROJECT_ID + USER_ID -> Value.USER_ID + API_KEY_ID -> Value.API_KEY_ID + MODEL -> Value.MODEL + BATCH -> Value.BATCH + SERVICE_TIER -> Value.SERVICE_TIER + API_SOURCE -> Value.API_SOURCE + 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) { + PROJECT_ID -> Known.PROJECT_ID + USER_ID -> Known.USER_ID + API_KEY_ID -> Known.API_KEY_ID + MODEL -> Known.MODEL + BATCH -> Known.BATCH + SERVICE_TIER -> Known.SERVICE_TIER + API_SOURCE -> Known.API_SOURCE + else -> throw OpenAIInvalidDataException("Unknown GroupBy: $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(): GroupBy = 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 GroupBy && 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 UsageDecisionsParams && + startTime == other.startTime && + apiKeyIds == other.apiKeyIds && + batch == other.batch && + bucketWidth == other.bucketWidth && + endTime == other.endTime && + groupBy == other.groupBy && + limit == other.limit && + models == other.models && + page == other.page && + projectIds == other.projectIds && + userIds == other.userIds && + additionalHeaders == other.additionalHeaders && + additionalQueryParams == other.additionalQueryParams + } + + override fun hashCode(): Int = + Objects.hash( + startTime, + apiKeyIds, + batch, + bucketWidth, + endTime, + groupBy, + limit, + models, + page, + projectIds, + userIds, + additionalHeaders, + additionalQueryParams, + ) + + override fun toString() = + "UsageDecisionsParams{startTime=$startTime, apiKeyIds=$apiKeyIds, batch=$batch, bucketWidth=$bucketWidth, endTime=$endTime, groupBy=$groupBy, limit=$limit, models=$models, page=$page, projectIds=$projectIds, userIds=$userIds, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" +} diff --git a/openai-java-core/src/main/kotlin/com/openai/models/admin/organization/usage/UsageDecisionsResponse.kt b/openai-java-core/src/main/kotlin/com/openai/models/admin/organization/usage/UsageDecisionsResponse.kt new file mode 100644 index 000000000..e28a2b5b5 --- /dev/null +++ b/openai-java-core/src/main/kotlin/com/openai/models/admin/organization/usage/UsageDecisionsResponse.kt @@ -0,0 +1,2241 @@ +// File generated from our OpenAPI spec by Castiron. See CONTRIBUTING.md for details. + +package com.openai.models.admin.organization.usage + +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.checkKnown +import com.openai.core.checkRequired +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 UsageDecisionsResponse +@JsonCreator(mode = JsonCreator.Mode.DISABLED) +private constructor( + private val data: JsonField>, + private val hasMore: JsonField, + private val nextPage: JsonField, + private val object_: JsonValue, + private val additionalProperties: MutableMap, +) { + + @JsonCreator + private constructor( + @JsonProperty("data") @ExcludeMissing data: JsonField> = JsonMissing.of(), + @JsonProperty("has_more") @ExcludeMissing hasMore: JsonField = JsonMissing.of(), + @JsonProperty("next_page") @ExcludeMissing nextPage: JsonField = JsonMissing.of(), + @JsonProperty("object") @ExcludeMissing object_: JsonValue = JsonMissing.of(), + ) : this(data, hasMore, nextPage, object_, 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 data(): List = data.getRequired("data") + + /** + * @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 hasMore(): Boolean = hasMore.getRequired("has_more") + + /** + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun nextPage(): Optional = nextPage.getOptional("next_page") + + /** + * Expected to always return the following: + * ```java + * JsonValue.from("page") + * ``` + * + * However, this method can be useful for debugging and logging (e.g. if the server responded + * with an unexpected value). + */ + @JsonProperty("object") @ExcludeMissing fun _object_(): JsonValue = object_ + + /** + * Returns the raw JSON value of [data]. + * + * Unlike [data], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("data") @ExcludeMissing fun _data(): JsonField> = data + + /** + * Returns the raw JSON value of [hasMore]. + * + * Unlike [hasMore], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("has_more") @ExcludeMissing fun _hasMore(): JsonField = hasMore + + /** + * Returns the raw JSON value of [nextPage]. + * + * Unlike [nextPage], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("next_page") @ExcludeMissing fun _nextPage(): JsonField = nextPage + + @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 [UsageDecisionsResponse]. + * + * The following fields are required: + * ```java + * .data() + * .hasMore() + * .nextPage() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [UsageDecisionsResponse]. */ + class Builder internal constructor() { + + private var data: JsonField>? = null + private var hasMore: JsonField? = null + private var nextPage: JsonField? = null + private var object_: JsonValue = JsonValue.from("page") + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(usageDecisionsResponse: UsageDecisionsResponse) = apply { + data = usageDecisionsResponse.data.map { it.toMutableList() } + hasMore = usageDecisionsResponse.hasMore + nextPage = usageDecisionsResponse.nextPage + object_ = usageDecisionsResponse.object_ + additionalProperties = usageDecisionsResponse.additionalProperties.toMutableMap() + } + + fun data(data: List) = data(JsonField.of(data)) + + /** + * Sets [Builder.data] to an arbitrary JSON value. + * + * You should usually call [Builder.data] with a well-typed `List` value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun data(data: JsonField>) = apply { + this.data = data.map { it.toMutableList() } + } + + /** + * Adds a single [Data] to [Builder.data]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addData(data: Data) = apply { + this.data = + (this.data ?: JsonField.of(mutableListOf())).also { + checkKnown("data", it).add(data) + } + } + + fun hasMore(hasMore: Boolean) = hasMore(JsonField.of(hasMore)) + + /** + * Sets [Builder.hasMore] to an arbitrary JSON value. + * + * You should usually call [Builder.hasMore] with a well-typed [Boolean] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun hasMore(hasMore: JsonField) = apply { this.hasMore = hasMore } + + fun nextPage(nextPage: String?) = nextPage(JsonField.ofNullable(nextPage)) + + /** Alias for calling [Builder.nextPage] with `nextPage.orElse(null)`. */ + fun nextPage(nextPage: Optional) = nextPage(nextPage.getOrNull()) + + /** + * Sets [Builder.nextPage] to an arbitrary JSON value. + * + * You should usually call [Builder.nextPage] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun nextPage(nextPage: JsonField) = apply { this.nextPage = nextPage } + + /** + * 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("page") + * ``` + * + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun object_(object_: JsonValue) = apply { this.object_ = object_ } + + 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 [UsageDecisionsResponse]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .data() + * .hasMore() + * .nextPage() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): UsageDecisionsResponse = + UsageDecisionsResponse( + checkRequired("data", data).map { it.toImmutable() }, + checkRequired("hasMore", hasMore), + checkRequired("nextPage", nextPage), + object_, + 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(): UsageDecisionsResponse = apply { + if (validated) { + return@apply + } + + data().forEach { it.validate() } + hasMore() + nextPage() + _object_().let { + if (it != JsonValue.from("page")) { + throw OpenAIInvalidDataException("'object_' 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 = + (data.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + + (if (hasMore.asKnown().isPresent) 1 else 0) + + (if (nextPage.asKnown().isPresent) 1 else 0) + + object_.let { if (it == JsonValue.from("page")) 1 else 0 } + + class Data + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val endTime: JsonField, + private val object_: JsonValue, + private val results: JsonField>, + private val startTime: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("end_time") @ExcludeMissing endTime: JsonField = JsonMissing.of(), + @JsonProperty("object") @ExcludeMissing object_: JsonValue = JsonMissing.of(), + @JsonProperty("results") + @ExcludeMissing + results: JsonField> = JsonMissing.of(), + @JsonProperty("start_time") + @ExcludeMissing + startTime: JsonField = JsonMissing.of(), + ) : this(endTime, object_, results, startTime, 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 endTime(): Long = endTime.getRequired("end_time") + + /** + * Expected to always return the following: + * ```java + * JsonValue.from("bucket") + * ``` + * + * However, this method can be useful for debugging and logging (e.g. if the server + * responded with an unexpected value). + */ + @JsonProperty("object") @ExcludeMissing fun _object_(): JsonValue = object_ + + /** + * @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 results(): List = results.getRequired("results") + + /** + * @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 startTime(): Long = startTime.getRequired("start_time") + + /** + * Returns the raw JSON value of [endTime]. + * + * Unlike [endTime], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("end_time") @ExcludeMissing fun _endTime(): JsonField = endTime + + /** + * Returns the raw JSON value of [results]. + * + * Unlike [results], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("results") @ExcludeMissing fun _results(): JsonField> = results + + /** + * Returns the raw JSON value of [startTime]. + * + * Unlike [startTime], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("start_time") @ExcludeMissing fun _startTime(): JsonField = startTime + + @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 [Data]. + * + * The following fields are required: + * ```java + * .endTime() + * .results() + * .startTime() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Data]. */ + class Builder internal constructor() { + + private var endTime: JsonField? = null + private var object_: JsonValue = JsonValue.from("bucket") + private var results: JsonField>? = null + private var startTime: JsonField? = null + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(data: Data) = apply { + endTime = data.endTime + object_ = data.object_ + results = data.results.map { it.toMutableList() } + startTime = data.startTime + additionalProperties = data.additionalProperties.toMutableMap() + } + + fun endTime(endTime: Long) = endTime(JsonField.of(endTime)) + + /** + * Sets [Builder.endTime] to an arbitrary JSON value. + * + * You should usually call [Builder.endTime] with a well-typed [Long] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun endTime(endTime: JsonField) = apply { this.endTime = endTime } + + /** + * 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("bucket") + * ``` + * + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun object_(object_: JsonValue) = apply { this.object_ = object_ } + + fun results(results: List) = results(JsonField.of(results)) + + /** + * Sets [Builder.results] to an arbitrary JSON value. + * + * You should usually call [Builder.results] with a well-typed `List` value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun results(results: JsonField>) = apply { + this.results = results.map { it.toMutableList() } + } + + /** + * Adds a single [Result] to [results]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addResult(result: Result) = apply { + results = + (results ?: JsonField.of(mutableListOf())).also { + checkKnown("results", it).add(result) + } + } + + fun startTime(startTime: Long) = startTime(JsonField.of(startTime)) + + /** + * Sets [Builder.startTime] to an arbitrary JSON value. + * + * You should usually call [Builder.startTime] with a well-typed [Long] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun startTime(startTime: JsonField) = apply { this.startTime = startTime } + + 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 [Data]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .endTime() + * .results() + * .startTime() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): Data = + Data( + checkRequired("endTime", endTime), + object_, + checkRequired("results", results).map { it.toImmutable() }, + checkRequired("startTime", startTime), + 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(): Data = apply { + if (validated) { + return@apply + } + + endTime() + _object_().let { + if (it != JsonValue.from("bucket")) { + throw OpenAIInvalidDataException("'object_' is invalid, received $it") + } + } + results().forEach { it.validate() } + startTime() + 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 (endTime.asKnown().isPresent) 1 else 0) + + object_.let { if (it == JsonValue.from("bucket")) 1 else 0 } + + (results.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + + (if (startTime.asKnown().isPresent) 1 else 0) + + /** The aggregated Decisions API usage details of the specific time bucket. */ + class Result + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val inputTokens: JsonField, + private val numModelRequests: JsonField, + private val object_: JsonValue, + private val outputTokens: JsonField, + private val apiKeyId: JsonField, + private val apiSource: JsonField, + private val batch: JsonField, + private val inputAudioTokens: JsonField, + private val inputCacheWrite12hTokens: JsonField, + private val inputCacheWriteTokens: JsonField, + private val inputCachedAudioTokens: JsonField, + private val inputCachedImageTokens: JsonField, + private val inputCachedTextTokens: JsonField, + private val inputCachedTokens: JsonField, + private val inputImageTokens: JsonField, + private val inputTextTokens: JsonField, + private val inputUncachedTokens: JsonField, + private val model: JsonField, + private val outputAudioTokens: JsonField, + private val outputImageTokens: JsonField, + private val outputTextTokens: JsonField, + private val projectId: JsonField, + private val serviceTier: JsonField, + private val userId: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("input_tokens") + @ExcludeMissing + inputTokens: JsonField = JsonMissing.of(), + @JsonProperty("num_model_requests") + @ExcludeMissing + numModelRequests: JsonField = JsonMissing.of(), + @JsonProperty("object") @ExcludeMissing object_: JsonValue = JsonMissing.of(), + @JsonProperty("output_tokens") + @ExcludeMissing + outputTokens: JsonField = JsonMissing.of(), + @JsonProperty("api_key_id") + @ExcludeMissing + apiKeyId: JsonField = JsonMissing.of(), + @JsonProperty("api_source") + @ExcludeMissing + apiSource: JsonField = JsonMissing.of(), + @JsonProperty("batch") @ExcludeMissing batch: JsonField = JsonMissing.of(), + @JsonProperty("input_audio_tokens") + @ExcludeMissing + inputAudioTokens: JsonField = JsonMissing.of(), + @JsonProperty("input_cache_write_12h_tokens") + @ExcludeMissing + inputCacheWrite12hTokens: JsonField = JsonMissing.of(), + @JsonProperty("input_cache_write_tokens") + @ExcludeMissing + inputCacheWriteTokens: JsonField = JsonMissing.of(), + @JsonProperty("input_cached_audio_tokens") + @ExcludeMissing + inputCachedAudioTokens: JsonField = JsonMissing.of(), + @JsonProperty("input_cached_image_tokens") + @ExcludeMissing + inputCachedImageTokens: JsonField = JsonMissing.of(), + @JsonProperty("input_cached_text_tokens") + @ExcludeMissing + inputCachedTextTokens: JsonField = JsonMissing.of(), + @JsonProperty("input_cached_tokens") + @ExcludeMissing + inputCachedTokens: JsonField = JsonMissing.of(), + @JsonProperty("input_image_tokens") + @ExcludeMissing + inputImageTokens: JsonField = JsonMissing.of(), + @JsonProperty("input_text_tokens") + @ExcludeMissing + inputTextTokens: JsonField = JsonMissing.of(), + @JsonProperty("input_uncached_tokens") + @ExcludeMissing + inputUncachedTokens: JsonField = JsonMissing.of(), + @JsonProperty("model") @ExcludeMissing model: JsonField = JsonMissing.of(), + @JsonProperty("output_audio_tokens") + @ExcludeMissing + outputAudioTokens: JsonField = JsonMissing.of(), + @JsonProperty("output_image_tokens") + @ExcludeMissing + outputImageTokens: JsonField = JsonMissing.of(), + @JsonProperty("output_text_tokens") + @ExcludeMissing + outputTextTokens: JsonField = JsonMissing.of(), + @JsonProperty("project_id") + @ExcludeMissing + projectId: JsonField = JsonMissing.of(), + @JsonProperty("service_tier") + @ExcludeMissing + serviceTier: JsonField = JsonMissing.of(), + @JsonProperty("user_id") + @ExcludeMissing + userId: JsonField = JsonMissing.of(), + ) : this( + inputTokens, + numModelRequests, + object_, + outputTokens, + apiKeyId, + apiSource, + batch, + inputAudioTokens, + inputCacheWrite12hTokens, + inputCacheWriteTokens, + inputCachedAudioTokens, + inputCachedImageTokens, + inputCachedTextTokens, + inputCachedTokens, + inputImageTokens, + inputTextTokens, + inputUncachedTokens, + model, + outputAudioTokens, + outputImageTokens, + outputTextTokens, + projectId, + serviceTier, + userId, + mutableMapOf(), + ) + + /** + * The aggregated number of input tokens used, including cached and cache-write tokens. + * This includes text, audio, and image tokens. For customers subscribed to Scale Tier, + * this includes Scale Tier 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 inputTokens(): Long = inputTokens.getRequired("input_tokens") + + /** + * The count of requests made 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 numModelRequests(): Long = numModelRequests.getRequired("num_model_requests") + + /** + * Expected to always return the following: + * ```java + * JsonValue.from("organization.usage.decisions.result") + * ``` + * + * However, this method can be useful for debugging and logging (e.g. if the server + * responded with an unexpected value). + */ + @JsonProperty("object") @ExcludeMissing fun _object_(): JsonValue = object_ + + /** + * The aggregated number of output tokens used across text, audio, and image outputs. + * For customers subscribed to Scale Tier, this includes Scale Tier 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 outputTokens(): Long = outputTokens.getRequired("output_tokens") + + /** + * When `group_by=api_key_id`, this field provides the API key ID of the grouped usage + * result. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun apiKeyId(): Optional = apiKeyId.getOptional("api_key_id") + + /** + * When grouped by `api_source`, `agents_api` identifies attributed Agents API activity + * and `unlabeled` includes all records without published source attribution, including + * historical and unknown origins. Unlabeled does not imply direct API usage. Without + * source grouping, this field is null. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun apiSource(): Optional = apiSource.getOptional("api_source") + + /** + * When `group_by=batch`, this field tells whether the grouped usage result is batch or + * not. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun batch(): Optional = batch.getOptional("batch") + + /** + * The aggregated number of uncached audio input tokens used. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun inputAudioTokens(): Optional = + inputAudioTokens.getOptional("input_audio_tokens") + + /** + * The aggregated number of input tokens written to the cache with a 12-hour retention + * period. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun inputCacheWrite12hTokens(): Optional = + inputCacheWrite12hTokens.getOptional("input_cache_write_12h_tokens") + + /** + * The aggregated number of input tokens written to the cache with a 30-minute retention + * period. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun inputCacheWriteTokens(): Optional = + inputCacheWriteTokens.getOptional("input_cache_write_tokens") + + /** + * The aggregated number of cached audio input tokens used. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun inputCachedAudioTokens(): Optional = + inputCachedAudioTokens.getOptional("input_cached_audio_tokens") + + /** + * The aggregated number of cached image input tokens used. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun inputCachedImageTokens(): Optional = + inputCachedImageTokens.getOptional("input_cached_image_tokens") + + /** + * The aggregated number of cached text input tokens used. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun inputCachedTextTokens(): Optional = + inputCachedTextTokens.getOptional("input_cached_text_tokens") + + /** + * The aggregated number of cached input tokens used across text, audio, and image + * inputs. For customers subscribed to Scale Tier, this includes Scale Tier tokens. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun inputCachedTokens(): Optional = + inputCachedTokens.getOptional("input_cached_tokens") + + /** + * The aggregated number of uncached image input tokens used. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun inputImageTokens(): Optional = + inputImageTokens.getOptional("input_image_tokens") + + /** + * The aggregated number of uncached text input tokens used, excluding cache-write + * tokens. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun inputTextTokens(): Optional = inputTextTokens.getOptional("input_text_tokens") + + /** + * The aggregated number of uncached input tokens used across text, audio, and image + * inputs, excluding cache-write tokens. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun inputUncachedTokens(): Optional = + inputUncachedTokens.getOptional("input_uncached_tokens") + + /** + * When `group_by=model`, this field provides the model name of the grouped usage + * result. + * + * @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") + + /** + * The aggregated number of audio output tokens used. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun outputAudioTokens(): Optional = + outputAudioTokens.getOptional("output_audio_tokens") + + /** + * The aggregated number of image output tokens used. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun outputImageTokens(): Optional = + outputImageTokens.getOptional("output_image_tokens") + + /** + * The aggregated number of text output tokens used. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun outputTextTokens(): Optional = + outputTextTokens.getOptional("output_text_tokens") + + /** + * When `group_by=project_id`, this field provides the project ID of the grouped usage + * result. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun projectId(): Optional = projectId.getOptional("project_id") + + /** + * When `group_by=service_tier`, this field provides the service tier of the grouped + * usage result. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun serviceTier(): Optional = serviceTier.getOptional("service_tier") + + /** + * When `group_by=user_id`, this field provides the user ID of the grouped usage result. + * + * @throws OpenAIInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun userId(): Optional = userId.getOptional("user_id") + + /** + * 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 [numModelRequests]. + * + * Unlike [numModelRequests], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("num_model_requests") + @ExcludeMissing + fun _numModelRequests(): JsonField = numModelRequests + + /** + * 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 [apiKeyId]. + * + * Unlike [apiKeyId], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("api_key_id") + @ExcludeMissing + fun _apiKeyId(): JsonField = apiKeyId + + /** + * Returns the raw JSON value of [apiSource]. + * + * Unlike [apiSource], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("api_source") + @ExcludeMissing + fun _apiSource(): JsonField = apiSource + + /** + * Returns the raw JSON value of [batch]. + * + * Unlike [batch], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("batch") @ExcludeMissing fun _batch(): JsonField = batch + + /** + * Returns the raw JSON value of [inputAudioTokens]. + * + * Unlike [inputAudioTokens], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("input_audio_tokens") + @ExcludeMissing + fun _inputAudioTokens(): JsonField = inputAudioTokens + + /** + * Returns the raw JSON value of [inputCacheWrite12hTokens]. + * + * Unlike [inputCacheWrite12hTokens], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("input_cache_write_12h_tokens") + @ExcludeMissing + fun _inputCacheWrite12hTokens(): JsonField = inputCacheWrite12hTokens + + /** + * Returns the raw JSON value of [inputCacheWriteTokens]. + * + * Unlike [inputCacheWriteTokens], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("input_cache_write_tokens") + @ExcludeMissing + fun _inputCacheWriteTokens(): JsonField = inputCacheWriteTokens + + /** + * Returns the raw JSON value of [inputCachedAudioTokens]. + * + * Unlike [inputCachedAudioTokens], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("input_cached_audio_tokens") + @ExcludeMissing + fun _inputCachedAudioTokens(): JsonField = inputCachedAudioTokens + + /** + * Returns the raw JSON value of [inputCachedImageTokens]. + * + * Unlike [inputCachedImageTokens], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("input_cached_image_tokens") + @ExcludeMissing + fun _inputCachedImageTokens(): JsonField = inputCachedImageTokens + + /** + * Returns the raw JSON value of [inputCachedTextTokens]. + * + * Unlike [inputCachedTextTokens], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("input_cached_text_tokens") + @ExcludeMissing + fun _inputCachedTextTokens(): JsonField = inputCachedTextTokens + + /** + * Returns the raw JSON value of [inputCachedTokens]. + * + * Unlike [inputCachedTokens], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("input_cached_tokens") + @ExcludeMissing + fun _inputCachedTokens(): JsonField = inputCachedTokens + + /** + * Returns the raw JSON value of [inputImageTokens]. + * + * Unlike [inputImageTokens], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("input_image_tokens") + @ExcludeMissing + fun _inputImageTokens(): JsonField = inputImageTokens + + /** + * Returns the raw JSON value of [inputTextTokens]. + * + * Unlike [inputTextTokens], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("input_text_tokens") + @ExcludeMissing + fun _inputTextTokens(): JsonField = inputTextTokens + + /** + * Returns the raw JSON value of [inputUncachedTokens]. + * + * Unlike [inputUncachedTokens], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("input_uncached_tokens") + @ExcludeMissing + fun _inputUncachedTokens(): JsonField = inputUncachedTokens + + /** + * 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 [outputAudioTokens]. + * + * Unlike [outputAudioTokens], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("output_audio_tokens") + @ExcludeMissing + fun _outputAudioTokens(): JsonField = outputAudioTokens + + /** + * Returns the raw JSON value of [outputImageTokens]. + * + * Unlike [outputImageTokens], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("output_image_tokens") + @ExcludeMissing + fun _outputImageTokens(): JsonField = outputImageTokens + + /** + * Returns the raw JSON value of [outputTextTokens]. + * + * Unlike [outputTextTokens], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("output_text_tokens") + @ExcludeMissing + fun _outputTextTokens(): JsonField = outputTextTokens + + /** + * Returns the raw JSON value of [projectId]. + * + * Unlike [projectId], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("project_id") + @ExcludeMissing + fun _projectId(): JsonField = projectId + + /** + * Returns the raw JSON value of [serviceTier]. + * + * Unlike [serviceTier], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("service_tier") + @ExcludeMissing + fun _serviceTier(): JsonField = serviceTier + + /** + * Returns the raw JSON value of [userId]. + * + * Unlike [userId], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("user_id") @ExcludeMissing fun _userId(): JsonField = userId + + @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 [Result]. + * + * The following fields are required: + * ```java + * .inputTokens() + * .numModelRequests() + * .outputTokens() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Result]. */ + class Builder internal constructor() { + + private var inputTokens: JsonField? = null + private var numModelRequests: JsonField? = null + private var object_: JsonValue = + JsonValue.from("organization.usage.decisions.result") + private var outputTokens: JsonField? = null + private var apiKeyId: JsonField = JsonMissing.of() + private var apiSource: JsonField = JsonMissing.of() + private var batch: JsonField = JsonMissing.of() + private var inputAudioTokens: JsonField = JsonMissing.of() + private var inputCacheWrite12hTokens: JsonField = JsonMissing.of() + private var inputCacheWriteTokens: JsonField = JsonMissing.of() + private var inputCachedAudioTokens: JsonField = JsonMissing.of() + private var inputCachedImageTokens: JsonField = JsonMissing.of() + private var inputCachedTextTokens: JsonField = JsonMissing.of() + private var inputCachedTokens: JsonField = JsonMissing.of() + private var inputImageTokens: JsonField = JsonMissing.of() + private var inputTextTokens: JsonField = JsonMissing.of() + private var inputUncachedTokens: JsonField = JsonMissing.of() + private var model: JsonField = JsonMissing.of() + private var outputAudioTokens: JsonField = JsonMissing.of() + private var outputImageTokens: JsonField = JsonMissing.of() + private var outputTextTokens: JsonField = JsonMissing.of() + private var projectId: JsonField = JsonMissing.of() + private var serviceTier: JsonField = JsonMissing.of() + private var userId: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(result: Result) = apply { + inputTokens = result.inputTokens + numModelRequests = result.numModelRequests + object_ = result.object_ + outputTokens = result.outputTokens + apiKeyId = result.apiKeyId + apiSource = result.apiSource + batch = result.batch + inputAudioTokens = result.inputAudioTokens + inputCacheWrite12hTokens = result.inputCacheWrite12hTokens + inputCacheWriteTokens = result.inputCacheWriteTokens + inputCachedAudioTokens = result.inputCachedAudioTokens + inputCachedImageTokens = result.inputCachedImageTokens + inputCachedTextTokens = result.inputCachedTextTokens + inputCachedTokens = result.inputCachedTokens + inputImageTokens = result.inputImageTokens + inputTextTokens = result.inputTextTokens + inputUncachedTokens = result.inputUncachedTokens + model = result.model + outputAudioTokens = result.outputAudioTokens + outputImageTokens = result.outputImageTokens + outputTextTokens = result.outputTextTokens + projectId = result.projectId + serviceTier = result.serviceTier + userId = result.userId + additionalProperties = result.additionalProperties.toMutableMap() + } + + /** + * The aggregated number of input tokens used, including cached and cache-write + * tokens. This includes text, audio, and image tokens. For customers subscribed to + * Scale Tier, this includes Scale Tier tokens. + */ + 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 + } + + /** The count of requests made to the model. */ + fun numModelRequests(numModelRequests: Long) = + numModelRequests(JsonField.of(numModelRequests)) + + /** + * Sets [Builder.numModelRequests] to an arbitrary JSON value. + * + * You should usually call [Builder.numModelRequests] with a well-typed [Long] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun numModelRequests(numModelRequests: JsonField) = apply { + this.numModelRequests = numModelRequests + } + + /** + * 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("organization.usage.decisions.result") + * ``` + * + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun object_(object_: JsonValue) = apply { this.object_ = object_ } + + /** + * The aggregated number of output tokens used across text, audio, and image + * outputs. For customers subscribed to Scale Tier, this includes Scale Tier tokens. + */ + 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 + } + + /** + * When `group_by=api_key_id`, this field provides the API key ID of the grouped + * usage result. + */ + fun apiKeyId(apiKeyId: String?) = apiKeyId(JsonField.ofNullable(apiKeyId)) + + /** Alias for calling [Builder.apiKeyId] with `apiKeyId.orElse(null)`. */ + fun apiKeyId(apiKeyId: Optional) = apiKeyId(apiKeyId.getOrNull()) + + /** + * Sets [Builder.apiKeyId] to an arbitrary JSON value. + * + * You should usually call [Builder.apiKeyId] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun apiKeyId(apiKeyId: JsonField) = apply { this.apiKeyId = apiKeyId } + + /** + * When grouped by `api_source`, `agents_api` identifies attributed Agents API + * activity and `unlabeled` includes all records without published source + * attribution, including historical and unknown origins. Unlabeled does not imply + * direct API usage. Without source grouping, this field is null. + */ + fun apiSource(apiSource: ApiSource?) = apiSource(JsonField.ofNullable(apiSource)) + + /** Alias for calling [Builder.apiSource] with `apiSource.orElse(null)`. */ + fun apiSource(apiSource: Optional) = apiSource(apiSource.getOrNull()) + + /** + * Sets [Builder.apiSource] to an arbitrary JSON value. + * + * You should usually call [Builder.apiSource] with a well-typed [ApiSource] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun apiSource(apiSource: JsonField) = apply { + this.apiSource = apiSource + } + + /** + * When `group_by=batch`, this field tells whether the grouped usage result is batch + * or not. + */ + fun batch(batch: Boolean?) = batch(JsonField.ofNullable(batch)) + + /** + * Alias for [Builder.batch]. + * + * This unboxed primitive overload exists for backwards compatibility. + */ + fun batch(batch: Boolean) = batch(batch as Boolean?) + + /** Alias for calling [Builder.batch] with `batch.orElse(null)`. */ + fun batch(batch: Optional) = batch(batch.getOrNull()) + + /** + * Sets [Builder.batch] to an arbitrary JSON value. + * + * You should usually call [Builder.batch] with a well-typed [Boolean] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun batch(batch: JsonField) = apply { this.batch = batch } + + /** The aggregated number of uncached audio input tokens used. */ + fun inputAudioTokens(inputAudioTokens: Long?) = + inputAudioTokens(JsonField.ofNullable(inputAudioTokens)) + + /** + * Alias for [Builder.inputAudioTokens]. + * + * This unboxed primitive overload exists for backwards compatibility. + */ + fun inputAudioTokens(inputAudioTokens: Long) = + inputAudioTokens(inputAudioTokens as Long?) + + /** + * Alias for calling [Builder.inputAudioTokens] with + * `inputAudioTokens.orElse(null)`. + */ + fun inputAudioTokens(inputAudioTokens: Optional) = + inputAudioTokens(inputAudioTokens.getOrNull()) + + /** + * Sets [Builder.inputAudioTokens] to an arbitrary JSON value. + * + * You should usually call [Builder.inputAudioTokens] with a well-typed [Long] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun inputAudioTokens(inputAudioTokens: JsonField) = apply { + this.inputAudioTokens = inputAudioTokens + } + + /** + * The aggregated number of input tokens written to the cache with a 12-hour + * retention period. + */ + fun inputCacheWrite12hTokens(inputCacheWrite12hTokens: Long?) = + inputCacheWrite12hTokens(JsonField.ofNullable(inputCacheWrite12hTokens)) + + /** + * Alias for [Builder.inputCacheWrite12hTokens]. + * + * This unboxed primitive overload exists for backwards compatibility. + */ + fun inputCacheWrite12hTokens(inputCacheWrite12hTokens: Long) = + inputCacheWrite12hTokens(inputCacheWrite12hTokens as Long?) + + /** + * Alias for calling [Builder.inputCacheWrite12hTokens] with + * `inputCacheWrite12hTokens.orElse(null)`. + */ + fun inputCacheWrite12hTokens(inputCacheWrite12hTokens: Optional) = + inputCacheWrite12hTokens(inputCacheWrite12hTokens.getOrNull()) + + /** + * Sets [Builder.inputCacheWrite12hTokens] to an arbitrary JSON value. + * + * You should usually call [Builder.inputCacheWrite12hTokens] with a well-typed + * [Long] value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun inputCacheWrite12hTokens(inputCacheWrite12hTokens: JsonField) = apply { + this.inputCacheWrite12hTokens = inputCacheWrite12hTokens + } + + /** + * The aggregated number of input tokens written to the cache with a 30-minute + * retention period. + */ + fun inputCacheWriteTokens(inputCacheWriteTokens: Long?) = + inputCacheWriteTokens(JsonField.ofNullable(inputCacheWriteTokens)) + + /** + * Alias for [Builder.inputCacheWriteTokens]. + * + * This unboxed primitive overload exists for backwards compatibility. + */ + fun inputCacheWriteTokens(inputCacheWriteTokens: Long) = + inputCacheWriteTokens(inputCacheWriteTokens as Long?) + + /** + * Alias for calling [Builder.inputCacheWriteTokens] with + * `inputCacheWriteTokens.orElse(null)`. + */ + fun inputCacheWriteTokens(inputCacheWriteTokens: Optional) = + inputCacheWriteTokens(inputCacheWriteTokens.getOrNull()) + + /** + * Sets [Builder.inputCacheWriteTokens] to an arbitrary JSON value. + * + * You should usually call [Builder.inputCacheWriteTokens] with a well-typed [Long] + * value instead. This method is primarily for setting the field to an undocumented + * or not yet supported value. + */ + fun inputCacheWriteTokens(inputCacheWriteTokens: JsonField) = apply { + this.inputCacheWriteTokens = inputCacheWriteTokens + } + + /** The aggregated number of cached audio input tokens used. */ + fun inputCachedAudioTokens(inputCachedAudioTokens: Long?) = + inputCachedAudioTokens(JsonField.ofNullable(inputCachedAudioTokens)) + + /** + * Alias for [Builder.inputCachedAudioTokens]. + * + * This unboxed primitive overload exists for backwards compatibility. + */ + fun inputCachedAudioTokens(inputCachedAudioTokens: Long) = + inputCachedAudioTokens(inputCachedAudioTokens as Long?) + + /** + * Alias for calling [Builder.inputCachedAudioTokens] with + * `inputCachedAudioTokens.orElse(null)`. + */ + fun inputCachedAudioTokens(inputCachedAudioTokens: Optional) = + inputCachedAudioTokens(inputCachedAudioTokens.getOrNull()) + + /** + * Sets [Builder.inputCachedAudioTokens] to an arbitrary JSON value. + * + * You should usually call [Builder.inputCachedAudioTokens] with a well-typed [Long] + * value instead. This method is primarily for setting the field to an undocumented + * or not yet supported value. + */ + fun inputCachedAudioTokens(inputCachedAudioTokens: JsonField) = apply { + this.inputCachedAudioTokens = inputCachedAudioTokens + } + + /** The aggregated number of cached image input tokens used. */ + fun inputCachedImageTokens(inputCachedImageTokens: Long?) = + inputCachedImageTokens(JsonField.ofNullable(inputCachedImageTokens)) + + /** + * Alias for [Builder.inputCachedImageTokens]. + * + * This unboxed primitive overload exists for backwards compatibility. + */ + fun inputCachedImageTokens(inputCachedImageTokens: Long) = + inputCachedImageTokens(inputCachedImageTokens as Long?) + + /** + * Alias for calling [Builder.inputCachedImageTokens] with + * `inputCachedImageTokens.orElse(null)`. + */ + fun inputCachedImageTokens(inputCachedImageTokens: Optional) = + inputCachedImageTokens(inputCachedImageTokens.getOrNull()) + + /** + * Sets [Builder.inputCachedImageTokens] to an arbitrary JSON value. + * + * You should usually call [Builder.inputCachedImageTokens] with a well-typed [Long] + * value instead. This method is primarily for setting the field to an undocumented + * or not yet supported value. + */ + fun inputCachedImageTokens(inputCachedImageTokens: JsonField) = apply { + this.inputCachedImageTokens = inputCachedImageTokens + } + + /** The aggregated number of cached text input tokens used. */ + fun inputCachedTextTokens(inputCachedTextTokens: Long?) = + inputCachedTextTokens(JsonField.ofNullable(inputCachedTextTokens)) + + /** + * Alias for [Builder.inputCachedTextTokens]. + * + * This unboxed primitive overload exists for backwards compatibility. + */ + fun inputCachedTextTokens(inputCachedTextTokens: Long) = + inputCachedTextTokens(inputCachedTextTokens as Long?) + + /** + * Alias for calling [Builder.inputCachedTextTokens] with + * `inputCachedTextTokens.orElse(null)`. + */ + fun inputCachedTextTokens(inputCachedTextTokens: Optional) = + inputCachedTextTokens(inputCachedTextTokens.getOrNull()) + + /** + * Sets [Builder.inputCachedTextTokens] to an arbitrary JSON value. + * + * You should usually call [Builder.inputCachedTextTokens] with a well-typed [Long] + * value instead. This method is primarily for setting the field to an undocumented + * or not yet supported value. + */ + fun inputCachedTextTokens(inputCachedTextTokens: JsonField) = apply { + this.inputCachedTextTokens = inputCachedTextTokens + } + + /** + * The aggregated number of cached input tokens used across text, audio, and image + * inputs. For customers subscribed to Scale Tier, this includes Scale Tier tokens. + */ + fun inputCachedTokens(inputCachedTokens: Long?) = + inputCachedTokens(JsonField.ofNullable(inputCachedTokens)) + + /** + * Alias for [Builder.inputCachedTokens]. + * + * This unboxed primitive overload exists for backwards compatibility. + */ + fun inputCachedTokens(inputCachedTokens: Long) = + inputCachedTokens(inputCachedTokens as Long?) + + /** + * Alias for calling [Builder.inputCachedTokens] with + * `inputCachedTokens.orElse(null)`. + */ + fun inputCachedTokens(inputCachedTokens: Optional) = + inputCachedTokens(inputCachedTokens.getOrNull()) + + /** + * Sets [Builder.inputCachedTokens] to an arbitrary JSON value. + * + * You should usually call [Builder.inputCachedTokens] with a well-typed [Long] + * value instead. This method is primarily for setting the field to an undocumented + * or not yet supported value. + */ + fun inputCachedTokens(inputCachedTokens: JsonField) = apply { + this.inputCachedTokens = inputCachedTokens + } + + /** The aggregated number of uncached image input tokens used. */ + fun inputImageTokens(inputImageTokens: Long?) = + inputImageTokens(JsonField.ofNullable(inputImageTokens)) + + /** + * Alias for [Builder.inputImageTokens]. + * + * This unboxed primitive overload exists for backwards compatibility. + */ + fun inputImageTokens(inputImageTokens: Long) = + inputImageTokens(inputImageTokens as Long?) + + /** + * Alias for calling [Builder.inputImageTokens] with + * `inputImageTokens.orElse(null)`. + */ + fun inputImageTokens(inputImageTokens: Optional) = + inputImageTokens(inputImageTokens.getOrNull()) + + /** + * Sets [Builder.inputImageTokens] to an arbitrary JSON value. + * + * You should usually call [Builder.inputImageTokens] with a well-typed [Long] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun inputImageTokens(inputImageTokens: JsonField) = apply { + this.inputImageTokens = inputImageTokens + } + + /** + * The aggregated number of uncached text input tokens used, excluding cache-write + * tokens. + */ + fun inputTextTokens(inputTextTokens: Long?) = + inputTextTokens(JsonField.ofNullable(inputTextTokens)) + + /** + * Alias for [Builder.inputTextTokens]. + * + * This unboxed primitive overload exists for backwards compatibility. + */ + fun inputTextTokens(inputTextTokens: Long) = + inputTextTokens(inputTextTokens as Long?) + + /** + * Alias for calling [Builder.inputTextTokens] with `inputTextTokens.orElse(null)`. + */ + fun inputTextTokens(inputTextTokens: Optional) = + inputTextTokens(inputTextTokens.getOrNull()) + + /** + * Sets [Builder.inputTextTokens] to an arbitrary JSON value. + * + * You should usually call [Builder.inputTextTokens] with a well-typed [Long] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun inputTextTokens(inputTextTokens: JsonField) = apply { + this.inputTextTokens = inputTextTokens + } + + /** + * The aggregated number of uncached input tokens used across text, audio, and image + * inputs, excluding cache-write tokens. + */ + fun inputUncachedTokens(inputUncachedTokens: Long?) = + inputUncachedTokens(JsonField.ofNullable(inputUncachedTokens)) + + /** + * Alias for [Builder.inputUncachedTokens]. + * + * This unboxed primitive overload exists for backwards compatibility. + */ + fun inputUncachedTokens(inputUncachedTokens: Long) = + inputUncachedTokens(inputUncachedTokens as Long?) + + /** + * Alias for calling [Builder.inputUncachedTokens] with + * `inputUncachedTokens.orElse(null)`. + */ + fun inputUncachedTokens(inputUncachedTokens: Optional) = + inputUncachedTokens(inputUncachedTokens.getOrNull()) + + /** + * Sets [Builder.inputUncachedTokens] to an arbitrary JSON value. + * + * You should usually call [Builder.inputUncachedTokens] with a well-typed [Long] + * value instead. This method is primarily for setting the field to an undocumented + * or not yet supported value. + */ + fun inputUncachedTokens(inputUncachedTokens: JsonField) = apply { + this.inputUncachedTokens = inputUncachedTokens + } + + /** + * When `group_by=model`, this field provides the model name of the grouped usage + * result. + */ + fun model(model: String?) = model(JsonField.ofNullable(model)) + + /** Alias for calling [Builder.model] with `model.orElse(null)`. */ + fun model(model: Optional) = model(model.getOrNull()) + + /** + * 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 } + + /** The aggregated number of audio output tokens used. */ + fun outputAudioTokens(outputAudioTokens: Long?) = + outputAudioTokens(JsonField.ofNullable(outputAudioTokens)) + + /** + * Alias for [Builder.outputAudioTokens]. + * + * This unboxed primitive overload exists for backwards compatibility. + */ + fun outputAudioTokens(outputAudioTokens: Long) = + outputAudioTokens(outputAudioTokens as Long?) + + /** + * Alias for calling [Builder.outputAudioTokens] with + * `outputAudioTokens.orElse(null)`. + */ + fun outputAudioTokens(outputAudioTokens: Optional) = + outputAudioTokens(outputAudioTokens.getOrNull()) + + /** + * Sets [Builder.outputAudioTokens] to an arbitrary JSON value. + * + * You should usually call [Builder.outputAudioTokens] with a well-typed [Long] + * value instead. This method is primarily for setting the field to an undocumented + * or not yet supported value. + */ + fun outputAudioTokens(outputAudioTokens: JsonField) = apply { + this.outputAudioTokens = outputAudioTokens + } + + /** The aggregated number of image output tokens used. */ + fun outputImageTokens(outputImageTokens: Long?) = + outputImageTokens(JsonField.ofNullable(outputImageTokens)) + + /** + * Alias for [Builder.outputImageTokens]. + * + * This unboxed primitive overload exists for backwards compatibility. + */ + fun outputImageTokens(outputImageTokens: Long) = + outputImageTokens(outputImageTokens as Long?) + + /** + * Alias for calling [Builder.outputImageTokens] with + * `outputImageTokens.orElse(null)`. + */ + fun outputImageTokens(outputImageTokens: Optional) = + outputImageTokens(outputImageTokens.getOrNull()) + + /** + * Sets [Builder.outputImageTokens] to an arbitrary JSON value. + * + * You should usually call [Builder.outputImageTokens] with a well-typed [Long] + * value instead. This method is primarily for setting the field to an undocumented + * or not yet supported value. + */ + fun outputImageTokens(outputImageTokens: JsonField) = apply { + this.outputImageTokens = outputImageTokens + } + + /** The aggregated number of text output tokens used. */ + fun outputTextTokens(outputTextTokens: Long?) = + outputTextTokens(JsonField.ofNullable(outputTextTokens)) + + /** + * Alias for [Builder.outputTextTokens]. + * + * This unboxed primitive overload exists for backwards compatibility. + */ + fun outputTextTokens(outputTextTokens: Long) = + outputTextTokens(outputTextTokens as Long?) + + /** + * Alias for calling [Builder.outputTextTokens] with + * `outputTextTokens.orElse(null)`. + */ + fun outputTextTokens(outputTextTokens: Optional) = + outputTextTokens(outputTextTokens.getOrNull()) + + /** + * Sets [Builder.outputTextTokens] to an arbitrary JSON value. + * + * You should usually call [Builder.outputTextTokens] with a well-typed [Long] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun outputTextTokens(outputTextTokens: JsonField) = apply { + this.outputTextTokens = outputTextTokens + } + + /** + * When `group_by=project_id`, this field provides the project ID of the grouped + * usage result. + */ + fun projectId(projectId: String?) = projectId(JsonField.ofNullable(projectId)) + + /** Alias for calling [Builder.projectId] with `projectId.orElse(null)`. */ + fun projectId(projectId: Optional) = projectId(projectId.getOrNull()) + + /** + * Sets [Builder.projectId] to an arbitrary JSON value. + * + * You should usually call [Builder.projectId] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun projectId(projectId: JsonField) = apply { this.projectId = projectId } + + /** + * When `group_by=service_tier`, this field provides the service tier of the grouped + * usage result. + */ + fun serviceTier(serviceTier: String?) = + serviceTier(JsonField.ofNullable(serviceTier)) + + /** Alias for calling [Builder.serviceTier] with `serviceTier.orElse(null)`. */ + fun serviceTier(serviceTier: Optional) = + serviceTier(serviceTier.getOrNull()) + + /** + * Sets [Builder.serviceTier] to an arbitrary JSON value. + * + * You should usually call [Builder.serviceTier] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun serviceTier(serviceTier: JsonField) = apply { + this.serviceTier = serviceTier + } + + /** + * When `group_by=user_id`, this field provides the user ID of the grouped usage + * result. + */ + fun userId(userId: String?) = userId(JsonField.ofNullable(userId)) + + /** Alias for calling [Builder.userId] with `userId.orElse(null)`. */ + fun userId(userId: Optional) = userId(userId.getOrNull()) + + /** + * Sets [Builder.userId] to an arbitrary JSON value. + * + * You should usually call [Builder.userId] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun userId(userId: JsonField) = apply { this.userId = userId } + + 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 [Result]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .inputTokens() + * .numModelRequests() + * .outputTokens() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): Result = + Result( + checkRequired("inputTokens", inputTokens), + checkRequired("numModelRequests", numModelRequests), + object_, + checkRequired("outputTokens", outputTokens), + apiKeyId, + apiSource, + batch, + inputAudioTokens, + inputCacheWrite12hTokens, + inputCacheWriteTokens, + inputCachedAudioTokens, + inputCachedImageTokens, + inputCachedTextTokens, + inputCachedTokens, + inputImageTokens, + inputTextTokens, + inputUncachedTokens, + model, + outputAudioTokens, + outputImageTokens, + outputTextTokens, + projectId, + serviceTier, + userId, + 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(): Result = apply { + if (validated) { + return@apply + } + + inputTokens() + numModelRequests() + _object_().let { + if (it != JsonValue.from("organization.usage.decisions.result")) { + throw OpenAIInvalidDataException("'object_' is invalid, received $it") + } + } + outputTokens() + apiKeyId() + apiSource().ifPresent { it.validate() } + batch() + inputAudioTokens() + inputCacheWrite12hTokens() + inputCacheWriteTokens() + inputCachedAudioTokens() + inputCachedImageTokens() + inputCachedTextTokens() + inputCachedTokens() + inputImageTokens() + inputTextTokens() + inputUncachedTokens() + model() + outputAudioTokens() + outputImageTokens() + outputTextTokens() + projectId() + serviceTier() + userId() + 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) + + (if (numModelRequests.asKnown().isPresent) 1 else 0) + + object_.let { + if (it == JsonValue.from("organization.usage.decisions.result")) 1 else 0 + } + + (if (outputTokens.asKnown().isPresent) 1 else 0) + + (if (apiKeyId.asKnown().isPresent) 1 else 0) + + (apiSource.asKnown().getOrNull()?.validity() ?: 0) + + (if (batch.asKnown().isPresent) 1 else 0) + + (if (inputAudioTokens.asKnown().isPresent) 1 else 0) + + (if (inputCacheWrite12hTokens.asKnown().isPresent) 1 else 0) + + (if (inputCacheWriteTokens.asKnown().isPresent) 1 else 0) + + (if (inputCachedAudioTokens.asKnown().isPresent) 1 else 0) + + (if (inputCachedImageTokens.asKnown().isPresent) 1 else 0) + + (if (inputCachedTextTokens.asKnown().isPresent) 1 else 0) + + (if (inputCachedTokens.asKnown().isPresent) 1 else 0) + + (if (inputImageTokens.asKnown().isPresent) 1 else 0) + + (if (inputTextTokens.asKnown().isPresent) 1 else 0) + + (if (inputUncachedTokens.asKnown().isPresent) 1 else 0) + + (if (model.asKnown().isPresent) 1 else 0) + + (if (outputAudioTokens.asKnown().isPresent) 1 else 0) + + (if (outputImageTokens.asKnown().isPresent) 1 else 0) + + (if (outputTextTokens.asKnown().isPresent) 1 else 0) + + (if (projectId.asKnown().isPresent) 1 else 0) + + (if (serviceTier.asKnown().isPresent) 1 else 0) + + (if (userId.asKnown().isPresent) 1 else 0) + + /** + * When grouped by `api_source`, `agents_api` identifies attributed Agents API activity + * and `unlabeled` includes all records without published source attribution, including + * historical and unknown origins. Unlabeled does not imply direct API usage. Without + * source grouping, this field is null. + */ + class ApiSource @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 AGENTS_API = of("agents_api") + + @JvmField val UNLABELED = of("unlabeled") + + @JvmStatic fun of(value: String) = ApiSource(JsonField.of(value)) + } + + /** An enum containing [ApiSource]'s known values. */ + enum class Known { + AGENTS_API, + UNLABELED, + } + + /** + * An enum containing [ApiSource]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [ApiSource] 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 { + AGENTS_API, + UNLABELED, + /** + * An enum member indicating that [ApiSource] 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) { + AGENTS_API -> Value.AGENTS_API + UNLABELED -> Value.UNLABELED + 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) { + AGENTS_API -> Known.AGENTS_API + UNLABELED -> Known.UNLABELED + else -> throw OpenAIInvalidDataException("Unknown ApiSource: $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(): ApiSource = 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 ApiSource && 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 Result && + inputTokens == other.inputTokens && + numModelRequests == other.numModelRequests && + object_ == other.object_ && + outputTokens == other.outputTokens && + apiKeyId == other.apiKeyId && + apiSource == other.apiSource && + batch == other.batch && + inputAudioTokens == other.inputAudioTokens && + inputCacheWrite12hTokens == other.inputCacheWrite12hTokens && + inputCacheWriteTokens == other.inputCacheWriteTokens && + inputCachedAudioTokens == other.inputCachedAudioTokens && + inputCachedImageTokens == other.inputCachedImageTokens && + inputCachedTextTokens == other.inputCachedTextTokens && + inputCachedTokens == other.inputCachedTokens && + inputImageTokens == other.inputImageTokens && + inputTextTokens == other.inputTextTokens && + inputUncachedTokens == other.inputUncachedTokens && + model == other.model && + outputAudioTokens == other.outputAudioTokens && + outputImageTokens == other.outputImageTokens && + outputTextTokens == other.outputTextTokens && + projectId == other.projectId && + serviceTier == other.serviceTier && + userId == other.userId && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash( + inputTokens, + numModelRequests, + object_, + outputTokens, + apiKeyId, + apiSource, + batch, + inputAudioTokens, + inputCacheWrite12hTokens, + inputCacheWriteTokens, + inputCachedAudioTokens, + inputCachedImageTokens, + inputCachedTextTokens, + inputCachedTokens, + inputImageTokens, + inputTextTokens, + inputUncachedTokens, + model, + outputAudioTokens, + outputImageTokens, + outputTextTokens, + projectId, + serviceTier, + userId, + additionalProperties, + ) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Result{inputTokens=$inputTokens, numModelRequests=$numModelRequests, object_=$object_, outputTokens=$outputTokens, apiKeyId=$apiKeyId, apiSource=$apiSource, batch=$batch, inputAudioTokens=$inputAudioTokens, inputCacheWrite12hTokens=$inputCacheWrite12hTokens, inputCacheWriteTokens=$inputCacheWriteTokens, inputCachedAudioTokens=$inputCachedAudioTokens, inputCachedImageTokens=$inputCachedImageTokens, inputCachedTextTokens=$inputCachedTextTokens, inputCachedTokens=$inputCachedTokens, inputImageTokens=$inputImageTokens, inputTextTokens=$inputTextTokens, inputUncachedTokens=$inputUncachedTokens, model=$model, outputAudioTokens=$outputAudioTokens, outputImageTokens=$outputImageTokens, outputTextTokens=$outputTextTokens, projectId=$projectId, serviceTier=$serviceTier, userId=$userId, additionalProperties=$additionalProperties}" + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Data && + endTime == other.endTime && + object_ == other.object_ && + results == other.results && + startTime == other.startTime && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(endTime, object_, results, startTime, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Data{endTime=$endTime, object_=$object_, results=$results, startTime=$startTime, additionalProperties=$additionalProperties}" + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is UsageDecisionsResponse && + data == other.data && + hasMore == other.hasMore && + nextPage == other.nextPage && + object_ == other.object_ && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(data, hasMore, nextPage, object_, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "UsageDecisionsResponse{data=$data, hasMore=$hasMore, nextPage=$nextPage, object_=$object_, additionalProperties=$additionalProperties}" +} diff --git a/openai-java-core/src/main/kotlin/com/openai/services/async/admin/organization/UsageServiceAsync.kt b/openai-java-core/src/main/kotlin/com/openai/services/async/admin/organization/UsageServiceAsync.kt index 755400ca0..863207dfa 100644 --- a/openai-java-core/src/main/kotlin/com/openai/services/async/admin/organization/UsageServiceAsync.kt +++ b/openai-java-core/src/main/kotlin/com/openai/services/async/admin/organization/UsageServiceAsync.kt @@ -15,6 +15,8 @@ import com.openai.models.admin.organization.usage.UsageCompletionsParams import com.openai.models.admin.organization.usage.UsageCompletionsResponse import com.openai.models.admin.organization.usage.UsageCostsParams import com.openai.models.admin.organization.usage.UsageCostsResponse +import com.openai.models.admin.organization.usage.UsageDecisionsParams +import com.openai.models.admin.organization.usage.UsageDecisionsResponse import com.openai.models.admin.organization.usage.UsageEmbeddingsParams import com.openai.models.admin.organization.usage.UsageEmbeddingsResponse import com.openai.models.admin.organization.usage.UsageFileSearchCallsParams @@ -99,6 +101,16 @@ interface UsageServiceAsync { requestOptions: RequestOptions = RequestOptions.none(), ): CompletableFuture + /** Get Decisions API usage details for the organization. */ + fun decisions(params: UsageDecisionsParams): CompletableFuture = + decisions(params, RequestOptions.none()) + + /** @see decisions */ + fun decisions( + params: UsageDecisionsParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture + /** Get embeddings usage details for the organization. */ fun embeddings(params: UsageEmbeddingsParams): CompletableFuture = embeddings(params, RequestOptions.none()) @@ -251,6 +263,21 @@ interface UsageServiceAsync { requestOptions: RequestOptions = RequestOptions.none(), ): CompletableFuture> + /** + * Returns a raw HTTP response for `get /organization/usage/decisions`, but is otherwise the + * same as [UsageServiceAsync.decisions]. + */ + fun decisions( + params: UsageDecisionsParams + ): CompletableFuture> = + decisions(params, RequestOptions.none()) + + /** @see decisions */ + fun decisions( + params: UsageDecisionsParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture> + /** * Returns a raw HTTP response for `get /organization/usage/embeddings`, but is otherwise * the same as [UsageServiceAsync.embeddings]. diff --git a/openai-java-core/src/main/kotlin/com/openai/services/async/admin/organization/UsageServiceAsyncImpl.kt b/openai-java-core/src/main/kotlin/com/openai/services/async/admin/organization/UsageServiceAsyncImpl.kt index 6b8f063f6..a933ee53c 100644 --- a/openai-java-core/src/main/kotlin/com/openai/services/async/admin/organization/UsageServiceAsyncImpl.kt +++ b/openai-java-core/src/main/kotlin/com/openai/services/async/admin/organization/UsageServiceAsyncImpl.kt @@ -25,6 +25,8 @@ import com.openai.models.admin.organization.usage.UsageCompletionsParams import com.openai.models.admin.organization.usage.UsageCompletionsResponse import com.openai.models.admin.organization.usage.UsageCostsParams import com.openai.models.admin.organization.usage.UsageCostsResponse +import com.openai.models.admin.organization.usage.UsageDecisionsParams +import com.openai.models.admin.organization.usage.UsageDecisionsResponse import com.openai.models.admin.organization.usage.UsageEmbeddingsParams import com.openai.models.admin.organization.usage.UsageEmbeddingsResponse import com.openai.models.admin.organization.usage.UsageFileSearchCallsParams @@ -87,6 +89,13 @@ class UsageServiceAsyncImpl internal constructor(private val clientOptions: Clie // get /organization/costs withRawResponse().costs(params, requestOptions).thenApply { it.parse() } + override fun decisions( + params: UsageDecisionsParams, + requestOptions: RequestOptions, + ): CompletableFuture = + // get /organization/usage/decisions + withRawResponse().decisions(params, requestOptions).thenApply { it.parse() } + override fun embeddings( params: UsageEmbeddingsParams, requestOptions: RequestOptions, @@ -312,6 +321,40 @@ class UsageServiceAsyncImpl internal constructor(private val clientOptions: Clie } } + private val decisionsHandler: Handler = + jsonHandler(clientOptions.jsonMapper) + + override fun decisions( + params: UsageDecisionsParams, + requestOptions: RequestOptions, + ): CompletableFuture> { + val request = + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("organization", "usage", "decisions") + .build() + .prepareAsync( + clientOptions, + params, + SecurityOptions.builder().adminApiKeyAuth(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 { decisionsHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + } + private val embeddingsHandler: Handler = jsonHandler(clientOptions.jsonMapper) diff --git a/openai-java-core/src/main/kotlin/com/openai/services/blocking/admin/organization/UsageService.kt b/openai-java-core/src/main/kotlin/com/openai/services/blocking/admin/organization/UsageService.kt index 6350cd43c..943422bb8 100644 --- a/openai-java-core/src/main/kotlin/com/openai/services/blocking/admin/organization/UsageService.kt +++ b/openai-java-core/src/main/kotlin/com/openai/services/blocking/admin/organization/UsageService.kt @@ -16,6 +16,8 @@ import com.openai.models.admin.organization.usage.UsageCompletionsParams import com.openai.models.admin.organization.usage.UsageCompletionsResponse import com.openai.models.admin.organization.usage.UsageCostsParams import com.openai.models.admin.organization.usage.UsageCostsResponse +import com.openai.models.admin.organization.usage.UsageDecisionsParams +import com.openai.models.admin.organization.usage.UsageDecisionsResponse import com.openai.models.admin.organization.usage.UsageEmbeddingsParams import com.openai.models.admin.organization.usage.UsageEmbeddingsResponse import com.openai.models.admin.organization.usage.UsageFileSearchCallsParams @@ -95,6 +97,16 @@ interface UsageService { requestOptions: RequestOptions = RequestOptions.none(), ): UsageCostsResponse + /** Get Decisions API usage details for the organization. */ + fun decisions(params: UsageDecisionsParams): UsageDecisionsResponse = + decisions(params, RequestOptions.none()) + + /** @see decisions */ + fun decisions( + params: UsageDecisionsParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): UsageDecisionsResponse + /** Get embeddings usage details for the organization. */ fun embeddings(params: UsageEmbeddingsParams): UsageEmbeddingsResponse = embeddings(params, RequestOptions.none()) @@ -246,6 +258,21 @@ interface UsageService { requestOptions: RequestOptions = RequestOptions.none(), ): HttpResponseFor + /** + * Returns a raw HTTP response for `get /organization/usage/decisions`, but is otherwise the + * same as [UsageService.decisions]. + */ + @MustBeClosed + fun decisions(params: UsageDecisionsParams): HttpResponseFor = + decisions(params, RequestOptions.none()) + + /** @see decisions */ + @MustBeClosed + fun decisions( + params: UsageDecisionsParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor + /** * Returns a raw HTTP response for `get /organization/usage/embeddings`, but is otherwise * the same as [UsageService.embeddings]. diff --git a/openai-java-core/src/main/kotlin/com/openai/services/blocking/admin/organization/UsageServiceImpl.kt b/openai-java-core/src/main/kotlin/com/openai/services/blocking/admin/organization/UsageServiceImpl.kt index 1bb192e03..50a26fc15 100644 --- a/openai-java-core/src/main/kotlin/com/openai/services/blocking/admin/organization/UsageServiceImpl.kt +++ b/openai-java-core/src/main/kotlin/com/openai/services/blocking/admin/organization/UsageServiceImpl.kt @@ -25,6 +25,8 @@ import com.openai.models.admin.organization.usage.UsageCompletionsParams import com.openai.models.admin.organization.usage.UsageCompletionsResponse import com.openai.models.admin.organization.usage.UsageCostsParams import com.openai.models.admin.organization.usage.UsageCostsResponse +import com.openai.models.admin.organization.usage.UsageDecisionsParams +import com.openai.models.admin.organization.usage.UsageDecisionsResponse import com.openai.models.admin.organization.usage.UsageEmbeddingsParams import com.openai.models.admin.organization.usage.UsageEmbeddingsResponse import com.openai.models.admin.organization.usage.UsageFileSearchCallsParams @@ -86,6 +88,13 @@ class UsageServiceImpl internal constructor(private val clientOptions: ClientOpt // get /organization/costs withRawResponse().costs(params, requestOptions).parse() + override fun decisions( + params: UsageDecisionsParams, + requestOptions: RequestOptions, + ): UsageDecisionsResponse = + // get /organization/usage/decisions + withRawResponse().decisions(params, requestOptions).parse() + override fun embeddings( params: UsageEmbeddingsParams, requestOptions: RequestOptions, @@ -296,6 +305,37 @@ class UsageServiceImpl internal constructor(private val clientOptions: ClientOpt } } + private val decisionsHandler: Handler = + jsonHandler(clientOptions.jsonMapper) + + override fun decisions( + params: UsageDecisionsParams, + requestOptions: RequestOptions, + ): HttpResponseFor { + val request = + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("organization", "usage", "decisions") + .build() + .prepare( + clientOptions, + params, + SecurityOptions.builder().adminApiKeyAuth(true).build(), + ) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.execute(request, requestOptions) + return errorHandler.handle(response).parseable { + response + .use { decisionsHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + private val embeddingsHandler: Handler = jsonHandler(clientOptions.jsonMapper) diff --git a/openai-java-core/src/test/kotlin/com/openai/models/admin/organization/usage/UsageDecisionsParamsTest.kt b/openai-java-core/src/test/kotlin/com/openai/models/admin/organization/usage/UsageDecisionsParamsTest.kt new file mode 100644 index 000000000..4003b76cb --- /dev/null +++ b/openai-java-core/src/test/kotlin/com/openai/models/admin/organization/usage/UsageDecisionsParamsTest.kt @@ -0,0 +1,73 @@ +// File generated from our OpenAPI spec by Castiron. See CONTRIBUTING.md for details. + +package com.openai.models.admin.organization.usage + +import com.openai.core.http.QueryParams +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class UsageDecisionsParamsTest { + + @Test + fun create() { + UsageDecisionsParams.builder() + .startTime(0L) + .addApiKeyId("string") + .batch(true) + .bucketWidth(UsageDecisionsParams.BucketWidth._1M) + .endTime(0L) + .addGroupBy(UsageDecisionsParams.GroupBy.PROJECT_ID) + .limit(0L) + .addModel("string") + .page("page") + .addProjectId("string") + .addUserId("string") + .build() + } + + @Test + fun queryParams() { + val params = + UsageDecisionsParams.builder() + .startTime(0L) + .addApiKeyId("string") + .batch(true) + .bucketWidth(UsageDecisionsParams.BucketWidth._1M) + .endTime(0L) + .addGroupBy(UsageDecisionsParams.GroupBy.PROJECT_ID) + .limit(0L) + .addModel("string") + .page("page") + .addProjectId("string") + .addUserId("string") + .build() + + val queryParams = params._queryParams() + + assertThat(queryParams) + .isEqualTo( + QueryParams.builder() + .put("start_time", "0") + .put("api_key_ids[]", "string") + .put("batch", "true") + .put("bucket_width", "1m") + .put("end_time", "0") + .put("group_by[]", "project_id") + .put("limit", "0") + .put("models[]", "string") + .put("page", "page") + .put("project_ids[]", "string") + .put("user_ids[]", "string") + .build() + ) + } + + @Test + fun queryParamsWithoutOptionalFields() { + val params = UsageDecisionsParams.builder().startTime(0L).build() + + val queryParams = params._queryParams() + + assertThat(queryParams).isEqualTo(QueryParams.builder().put("start_time", "0").build()) + } +} diff --git a/openai-java-core/src/test/kotlin/com/openai/models/admin/organization/usage/UsageDecisionsResponseTest.kt b/openai-java-core/src/test/kotlin/com/openai/models/admin/organization/usage/UsageDecisionsResponseTest.kt new file mode 100644 index 000000000..6814f6e29 --- /dev/null +++ b/openai-java-core/src/test/kotlin/com/openai/models/admin/organization/usage/UsageDecisionsResponseTest.kt @@ -0,0 +1,141 @@ +// File generated from our OpenAPI spec by Castiron. See CONTRIBUTING.md for details. + +package com.openai.models.admin.organization.usage + +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 UsageDecisionsResponseTest { + + @Test + fun create() { + val usageDecisionsResponse = + UsageDecisionsResponse.builder() + .addData( + UsageDecisionsResponse.Data.builder() + .endTime(0L) + .addResult( + UsageDecisionsResponse.Data.Result.builder() + .inputTokens(0L) + .numModelRequests(0L) + .outputTokens(0L) + .apiKeyId("api_key_id") + .apiSource(UsageDecisionsResponse.Data.Result.ApiSource.AGENTS_API) + .batch(true) + .inputAudioTokens(0L) + .inputCacheWrite12hTokens(0L) + .inputCacheWriteTokens(0L) + .inputCachedAudioTokens(0L) + .inputCachedImageTokens(0L) + .inputCachedTextTokens(0L) + .inputCachedTokens(0L) + .inputImageTokens(0L) + .inputTextTokens(0L) + .inputUncachedTokens(0L) + .model("model") + .outputAudioTokens(0L) + .outputImageTokens(0L) + .outputTextTokens(0L) + .projectId("project_id") + .serviceTier("service_tier") + .userId("user_id") + .build() + ) + .startTime(0L) + .build() + ) + .hasMore(true) + .nextPage("next_page") + .build() + + assertThat(usageDecisionsResponse.data()) + .containsExactly( + UsageDecisionsResponse.Data.builder() + .endTime(0L) + .addResult( + UsageDecisionsResponse.Data.Result.builder() + .inputTokens(0L) + .numModelRequests(0L) + .outputTokens(0L) + .apiKeyId("api_key_id") + .apiSource(UsageDecisionsResponse.Data.Result.ApiSource.AGENTS_API) + .batch(true) + .inputAudioTokens(0L) + .inputCacheWrite12hTokens(0L) + .inputCacheWriteTokens(0L) + .inputCachedAudioTokens(0L) + .inputCachedImageTokens(0L) + .inputCachedTextTokens(0L) + .inputCachedTokens(0L) + .inputImageTokens(0L) + .inputTextTokens(0L) + .inputUncachedTokens(0L) + .model("model") + .outputAudioTokens(0L) + .outputImageTokens(0L) + .outputTextTokens(0L) + .projectId("project_id") + .serviceTier("service_tier") + .userId("user_id") + .build() + ) + .startTime(0L) + .build() + ) + assertThat(usageDecisionsResponse.hasMore()).isEqualTo(true) + assertThat(usageDecisionsResponse.nextPage()).contains("next_page") + } + + @Test + fun roundtrip() { + val jsonMapper = jsonMapper() + val usageDecisionsResponse = + UsageDecisionsResponse.builder() + .addData( + UsageDecisionsResponse.Data.builder() + .endTime(0L) + .addResult( + UsageDecisionsResponse.Data.Result.builder() + .inputTokens(0L) + .numModelRequests(0L) + .outputTokens(0L) + .apiKeyId("api_key_id") + .apiSource(UsageDecisionsResponse.Data.Result.ApiSource.AGENTS_API) + .batch(true) + .inputAudioTokens(0L) + .inputCacheWrite12hTokens(0L) + .inputCacheWriteTokens(0L) + .inputCachedAudioTokens(0L) + .inputCachedImageTokens(0L) + .inputCachedTextTokens(0L) + .inputCachedTokens(0L) + .inputImageTokens(0L) + .inputTextTokens(0L) + .inputUncachedTokens(0L) + .model("model") + .outputAudioTokens(0L) + .outputImageTokens(0L) + .outputTextTokens(0L) + .projectId("project_id") + .serviceTier("service_tier") + .userId("user_id") + .build() + ) + .startTime(0L) + .build() + ) + .hasMore(true) + .nextPage("next_page") + .build() + + val roundtrippedUsageDecisionsResponse = + jsonMapper.readValue( + jsonMapper.writeValueAsString(usageDecisionsResponse), + jacksonTypeRef(), + ) + + assertThat(roundtrippedUsageDecisionsResponse).isEqualTo(usageDecisionsResponse) + } +} diff --git a/openai-java-core/src/test/kotlin/com/openai/services/async/admin/organization/UsageServiceAsyncTest.kt b/openai-java-core/src/test/kotlin/com/openai/services/async/admin/organization/UsageServiceAsyncTest.kt index a890fa918..786061ba6 100644 --- a/openai-java-core/src/test/kotlin/com/openai/services/async/admin/organization/UsageServiceAsyncTest.kt +++ b/openai-java-core/src/test/kotlin/com/openai/services/async/admin/organization/UsageServiceAsyncTest.kt @@ -9,6 +9,7 @@ import com.openai.models.admin.organization.usage.UsageAudioTranscriptionsParams import com.openai.models.admin.organization.usage.UsageCodeInterpreterSessionsParams import com.openai.models.admin.organization.usage.UsageCompletionsParams import com.openai.models.admin.organization.usage.UsageCostsParams +import com.openai.models.admin.organization.usage.UsageDecisionsParams import com.openai.models.admin.organization.usage.UsageEmbeddingsParams import com.openai.models.admin.organization.usage.UsageFileSearchCallsParams import com.openai.models.admin.organization.usage.UsageImagesParams @@ -168,6 +169,37 @@ internal class UsageServiceAsyncTest { response.validate() } + @Test + fun decisions() { + val client = + OpenAIOkHttpClientAsync.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .adminApiKey("My Admin API Key") + .build() + val usageServiceAsync = client.admin().organization().usage() + + val responseFuture = + usageServiceAsync.decisions( + UsageDecisionsParams.builder() + .startTime(0L) + .addApiKeyId("string") + .batch(true) + .bucketWidth(UsageDecisionsParams.BucketWidth._1M) + .endTime(0L) + .addGroupBy(UsageDecisionsParams.GroupBy.PROJECT_ID) + .limit(0L) + .addModel("string") + .page("page") + .addProjectId("string") + .addUserId("string") + .build() + ) + + val response = responseFuture.get() + response.validate() + } + @Test fun embeddings() { val client = diff --git a/openai-java-core/src/test/kotlin/com/openai/services/blocking/admin/organization/UsageServiceTest.kt b/openai-java-core/src/test/kotlin/com/openai/services/blocking/admin/organization/UsageServiceTest.kt index f211a97c1..0f00716b4 100644 --- a/openai-java-core/src/test/kotlin/com/openai/services/blocking/admin/organization/UsageServiceTest.kt +++ b/openai-java-core/src/test/kotlin/com/openai/services/blocking/admin/organization/UsageServiceTest.kt @@ -9,6 +9,7 @@ import com.openai.models.admin.organization.usage.UsageAudioTranscriptionsParams import com.openai.models.admin.organization.usage.UsageCodeInterpreterSessionsParams import com.openai.models.admin.organization.usage.UsageCompletionsParams import com.openai.models.admin.organization.usage.UsageCostsParams +import com.openai.models.admin.organization.usage.UsageDecisionsParams import com.openai.models.admin.organization.usage.UsageEmbeddingsParams import com.openai.models.admin.organization.usage.UsageFileSearchCallsParams import com.openai.models.admin.organization.usage.UsageImagesParams @@ -163,6 +164,36 @@ internal class UsageServiceTest { response.validate() } + @Test + fun decisions() { + val client = + OpenAIOkHttpClient.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .adminApiKey("My Admin API Key") + .build() + val usageService = client.admin().organization().usage() + + val response = + usageService.decisions( + UsageDecisionsParams.builder() + .startTime(0L) + .addApiKeyId("string") + .batch(true) + .bucketWidth(UsageDecisionsParams.BucketWidth._1M) + .endTime(0L) + .addGroupBy(UsageDecisionsParams.GroupBy.PROJECT_ID) + .limit(0L) + .addModel("string") + .page("page") + .addProjectId("string") + .addUserId("string") + .build() + ) + + response.validate() + } + @Test fun embeddings() { val client =