001/*
002 * Copyright (c) 2026 Singular
003 * SPDX-License-Identifier: MIT
004 */
005
006package ai.singlr.openai;
007
008import ai.singlr.core.common.Strings;
009
010/**
011 * Supported OpenAI model identifiers.
012 *
013 * <p>Each enum constant maps to a specific model available through the Responses API.
014 */
015public enum OpenAIModelId {
016  // maxOutputTokens reflects the documented per-model output ceiling at time of writing —
017  // operators can override per-call via ModelConfig.Builder.withMaxOutputTokens. Reasoning models
018  // (o3, o4-mini) carry higher caps because their output includes reasoning tokens.
019  GPT_5_5("gpt-5.5", 1_050_000, 128_000),
020  GPT_5_4("gpt-5.4", 1_050_000, 128_000),
021  GPT_5_4_MINI("gpt-5.4-mini", 400_000, 128_000),
022  GPT_5_4_NANO("gpt-5.4-nano", 400_000, 128_000),
023  GPT_4_1("gpt-4.1", 1_000_000, 32_000),
024  GPT_4_1_MINI("gpt-4.1-mini", 1_000_000, 32_000),
025  GPT_4_1_NANO("gpt-4.1-nano", 1_000_000, 16_000),
026  GPT_4O("gpt-4o", 128_000, 16_384),
027  GPT_4O_MINI("gpt-4o-mini", 128_000, 16_384),
028  O3("o3", 200_000, 100_000),
029  O4_MINI("o4-mini", 200_000, 100_000);
030
031  private final String id;
032  private final int contextWindow;
033  private final int maxOutputTokens;
034
035  OpenAIModelId(String id, int contextWindow, int maxOutputTokens) {
036    this.id = id;
037    this.contextWindow = contextWindow;
038    this.maxOutputTokens = maxOutputTokens;
039  }
040
041  /**
042   * Returns the API model identifier string.
043   *
044   * @return the model ID used in API requests
045   */
046  public String id() {
047    return id;
048  }
049
050  /**
051   * Returns the context window size in tokens.
052   *
053   * @return the context window size
054   */
055  public int contextWindow() {
056    return contextWindow;
057  }
058
059  /**
060   * Returns the maximum output tokens this model can generate in a single response. Used as the
061   * fallback when {@code ModelConfig.maxOutputTokens()} is unset.
062   *
063   * @return the per-model output ceiling
064   */
065  public int maxOutputTokens() {
066    return maxOutputTokens;
067  }
068
069  /**
070   * Finds an OpenAIModelId by its string identifier.
071   *
072   * @param id the model identifier string
073   * @return the matching OpenAIModelId, or null if not found
074   */
075  public static OpenAIModelId fromId(String id) {
076    if (Strings.isBlank(id)) {
077      return null;
078    }
079    for (var model : values()) {
080      if (model.id.equals(id)) {
081        return model;
082      }
083    }
084    return null;
085  }
086
087  /**
088   * Checks if the given model ID is supported.
089   *
090   * @param id the model identifier string
091   * @return true if the model is supported
092   */
093  public static boolean isSupported(String id) {
094    return fromId(id) != null;
095  }
096}