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