{"version":3,"file":"params.cjs","names":["settableServiceTier"],"sources":["../../src/converters/params.ts"],"sourcesContent":["import {\n  ChatGoogleFields,\n  GooglePlatformType,\n  settableServiceTier,\n  SimplifiedSpeechConfig,\n  SimplifiedSpeechLanguageConfig,\n  SpeechSpeakerName,\n  SpeechVoice,\n  SpeechVoiceLanguage,\n} from \"../chat_models/types.js\";\nimport type { Gemini } from \"../chat_models/api-types.js\";\n\n/**\n * Converts a reasoning \"effort\" level value (e.g., \"minimal\", \"low\", \"medium\", \"high\")\n * to a corresponding reasoning token budget, depending on the target Gemini model.\n *\n * This mapping is essential when configuring Google Gemini API calls with reasoning\n * effort/level fields (as in the Gemini OpenAI-compatible API) or when translating\n * user-friendly configuration to explicit token budgets.\n *\n * - The mapping is refined to reflect the constraints documented by Google:\n *   - For \"gemini-2.5-flash\" models, token budgets may be set as low as 0 and up to 24k.\n *   - For other Gemini models, minimum is 128, maximum is 32k.\n * - Standard effort levels and their token mappings:\n *   - \"none\" / \"minimal\": lowest allowed (minTokens)\n *   - \"low\": 1k tokens\n *   - \"medium\": 8k tokens\n *   - \"high\": maximum allowed for the model (maxTokens)\n * - See reference:\n *   https://ai.google.dev/gemini-api/docs/thinking#thinking-levels\n *   https://ai.google.dev/gemini-api/docs/openai#thinking\n *\n * @param {string | undefined} modelName\n *   The Gemini model name (e.g., \"gemini-2.5-flash\"). Used to determine token range constraints.\n * @param {string | undefined} effort\n *   The reasoning effort level: one of \"none\", \"minimal\", \"low\", \"medium\", \"high\"\n *   (case-insensitive). If undefined, the function returns undefined.\n * @returns {number | undefined}\n *   The corresponding token count for the given effort and model. Returns undefined if\n *   the effort is not recognized or not provided.\n *\n * @example\n * convertReasoningEffortToReasoningTokens(\"gemini-2.5-flash\", \"medium\") // 8192\n * convertReasoningEffortToReasoningTokens(\"gemini-1.5-pro\", \"high\") // 32768\n * convertReasoningEffortToReasoningTokens(\"gemini-2.5-flash\", \"none\") // 0\n * convertReasoningEffortToReasoningTokens(undefined, \"low\") // 1024\n */\nexport function convertReasoningEffortToReasoningTokens(\n  modelName?: string,\n  effort?: string\n): number | undefined {\n  if (effort === undefined) {\n    return undefined;\n  }\n\n  // gemini-2.5-flash and -flash-lite can be disabled. Others can't.\n  // https://ai.google.dev/gemini-api/docs/thinking#thinking-levels\n  const minTokens: number = modelName?.startsWith(\"gemini-2.5-flash\") ? 0 : 128;\n  const maxTokens: number = modelName?.startsWith(\"gemini-2.5-flash\")\n    ? 24 * 1024\n    : 32 * 1024;\n\n  const normalizedEffort = effort.toLowerCase();\n  switch (normalizedEffort) {\n    case \"none\":\n    case \"minimal\":\n      return minTokens;\n    case \"low\":\n      // Defined as 1k by https://ai.google.dev/gemini-api/docs/openai#thinking\n      return 1024;\n    case \"medium\":\n      // Defined as 8k by https://ai.google.dev/gemini-api/docs/openai#thinking\n      return 8 * 1024;\n    case \"high\":\n      // Defined as 24k or 32k (model-dependent) by https://ai.google.dev/gemini-api/docs/openai#thinking\n      return maxTokens;\n    default:\n      return undefined;\n  }\n}\n\n/**\n * Converts a reasoning token budget (e.g., 0, 1024, 8192, 32768) to its corresponding\n * reasoning \"effort\" level, as used in the Google Gemini API (\"minimal\", \"low\", \"medium\", \"high\").\n *\n * This is the inverse of {@link convertReasoningEffortToReasoningTokens}. It is useful for\n * translating explicit numeric settings (often surfaced in raw API responses or configs)\n * into user-facing friendly reasoning levels/labels. The mapping relies on Google's\n * documented reasoning levels for different models:\n *\n * - -1 means default effort (per API documentation: this is \"minimal\" for flash-lite models\n *   and \"high\" (dynamic) for others).\n * - 0 means \"minimal\" unless the model is \"gemini-3-pro\", for which it maps to \"low\".\n * - <= 1024 tokens: \"low\"\n * - <= 8192 tokens: \"medium\" (unless model is \"gemini-3-pro\", for which it reverts to \"low\")\n * - > 8192: \"high\"\n *\n * Reference:\n *   https://ai.google.dev/gemini-api/docs/thinking#thinking-levels\n *   https://ai.google.dev/gemini-api/docs/openai#thinking\n *\n * @param {string | undefined} model\n *   The Gemini model name (e.g., \"gemini-3-pro\"). Used for model-specific special cases.\n * @param {number | undefined} reasoningTokens\n *   The token budget to convert. If undefined, the function returns undefined.\n * @returns {Lowercase<Gemini.ThinkingLevel> | undefined}\n *   The reasoning \"effort\" level (\"minimal\", \"low\", \"medium\", \"high\") or undefined if input is not valid.\n *\n * @example\n * convertReasoningTokensToReasoningEffort(\"gemini-3-pro\", 0) // \"low\"\n * convertReasoningTokensToReasoningEffort(\"gemini-1.5-pro\", 0) // \"minimal\"\n * convertReasoningTokensToReasoningEffort(undefined, 1024) // \"low\"\n * convertReasoningTokensToReasoningEffort(undefined, -1) // \"high\"\n * convertReasoningTokensToReasoningEffort(undefined, 9000) // \"high\"\n */\nexport function convertReasoningTokensToReasoningEffort(\n  model?: string,\n  reasoningTokens?: number\n): Gemini.ThinkingLevel | undefined {\n  if (typeof reasoningTokens === \"undefined\") {\n    return undefined;\n  } else if (reasoningTokens === -1) {\n    // -1 means \"minimal\" for flash-lite models and \"high\"/dynamic for others\n    // (\"default\" per https://ai.google.dev/gemini-api/docs/thinking#thinking-levels)\n    if (model && getModelLevel(model) === \"flash-lite\") {\n      return \"minimal\";\n    }\n    return \"high\";\n  } else if (reasoningTokens === 0) {\n    if (model?.startsWith(\"gemini-3-pro\")) {\n      return \"low\";\n    } else {\n      return \"minimal\";\n    }\n  } else if (reasoningTokens <= 1024) {\n    return \"low\";\n  } else if (reasoningTokens <= 8192) {\n    if (model?.startsWith(\"gemini-3-pro\")) {\n      return \"low\";\n    } else {\n      return \"medium\";\n    }\n  } else {\n    return \"high\";\n  }\n}\n\n/**\n * Infers and returns the Google platform type from the provided chat model parameters.\n *\n * This function helps determine which Google platform (e.g., Vertex AI on GCP or the public API)\n * should be used for calling Gemini/PaLM endpoints, based on the options provided in\n * {@link BaseChatGoogleParams} (such as model constructors or call options).\n */\nexport function convertParamsToPlatformType(params: {\n  platformType?: GooglePlatformType;\n  vertexai?: boolean;\n}): GooglePlatformType | undefined {\n  if (typeof params === \"undefined\") {\n    return undefined;\n  }\n  if (typeof params.platformType !== \"undefined\") {\n    return params.platformType;\n  }\n  if (params.vertexai === true) {\n    return \"gcp\";\n  }\n  return undefined;\n}\n\n/**\n * Returns the model family from a Gemini model name.\n * e.g. \"gemini-2.5-flash\" → \"gemini\"\n */\nexport function getModelFamily(model: string): string {\n  return model.split(\"-\")[0];\n}\n\n/**\n * Returns the model version from a Gemini model name.\n * e.g. \"gemini-2.5-flash\" → \"2.5\"\n */\nexport function getModelVersion(model: string): string {\n  return model.split(\"-\")[1];\n}\n\n/**\n * Returns the model level from a Gemini model name.\n * e.g. \"gemini-2.5-flash\" → \"flash\", \"gemini-2.5-flash-lite\" → \"flash-lite\"\n */\nexport function getModelLevel(model: string): string {\n  const parts = model.split(\"-\");\n  let ret = parts[2];\n  if (ret === \"flash\" && parts[3] === \"lite\") {\n    ret = \"flash-lite\";\n  }\n  return ret;\n}\n\n/**\n * Returns the model specialty from a Gemini model name.\n * e.g. \"gemini-2.5-flash-preview-image\" → \"image\",\n *      \"gemini-2.5-flash-preview-tts\" → \"tts\",\n *      \"gemini-2.5-flash\" → \"\"\n */\nexport function getModelSpecialty(model: string): string {\n  if (model.includes(\"image\")) {\n    return \"image\";\n  } else if (model.includes(\"tts\")) {\n    return \"tts\";\n  } else {\n    return \"\";\n  }\n}\n\n// Gemini 3 models that accept thinkingLevel \"MINIMAL\"; the others reject it with a 400, so they get \"LOW\".\n// TODO: Move this to model profile.\nconst MINIMAL_THINKING_LEVEL_MODELS = [\n  \"gemini-3-flash\",\n  \"gemini-3.1-flash-lite\",\n  \"gemini-3.5-flash\",\n  \"gemini-3.6-flash\",\n];\n\nfunction supportsMinimalThinkingLevel(model: string): boolean {\n  return MINIMAL_THINKING_LEVEL_MODELS.some((prefix) =>\n    model.startsWith(prefix)\n  );\n}\n\n/**\n * Builds the `thinkingConfig` object for the Gemini `generationConfig`,\n * translating user-facing reasoning fields into the wire format.\n *\n * @param model  The full Gemini model name (e.g. \"gemini-2.5-flash\").\n * @param fields The combined user/call-option fields.\n * @returns A populated {@link Gemini.ThinkingConfig}, or `{}`\n *          when thinking should not be explicitly configured.\n */\nexport function convertFieldsToThinkingConfig(\n  model: string,\n  fields: ChatGoogleFields\n): Gemini.ThinkingConfig | undefined {\n  // Thinking / reasoning\n  let includeThoughts = true;\n\n  let thinkingBudget =\n    fields?.maxReasoningTokens ??\n    fields?.thinkingBudget ??\n    convertReasoningEffortToReasoningTokens(\n      model,\n      fields?.reasoningEffort ?? fields?.thinkingLevel\n    );\n  if (\n    thinkingBudget === 0 ||\n    (model.includes(\"pro\") && thinkingBudget === 128)\n  ) {\n    includeThoughts = false;\n  }\n  if (\n    model.startsWith(\"gemini-2.5-pro\") &&\n    typeof thinkingBudget !== \"undefined\"\n  ) {\n    // Can't turn off Gemini 2.5 Pro thinking completely\n    if (thinkingBudget >= 0 && thinkingBudget < 128) {\n      thinkingBudget = 128;\n    }\n  }\n\n  const thinkingLevelRaw =\n    fields?.reasoningEffort ??\n    fields?.thinkingLevel ??\n    convertReasoningTokensToReasoningEffort(\n      model,\n      fields?.maxReasoningTokens ?? fields?.thinkingBudget\n    );\n  let thinkingLevel = thinkingLevelRaw?.toUpperCase();\n  if (thinkingLevel === \"MINIMAL\") {\n    includeThoughts = false;\n  }\n  if (\n    thinkingLevel === \"MINIMAL\" &&\n    model.startsWith(\"gemini-3\") &&\n    !supportsMinimalThinkingLevel(model)\n  ) {\n    thinkingLevel = \"LOW\";\n  }\n  if (model.startsWith(\"gemini-3-pro\") && thinkingLevel === \"MEDIUM\") {\n    // Gemini 3 Pro has only low and high.\n    thinkingLevel = \"HIGH\";\n  }\n\n  // If we are using a model that doesn't support thinking at all (gemini 2.5 imaging)\n  // or we haven't explicitly tried to set a thinking budget/level, then bail out.\n  const modelVersion = getModelVersion(model);\n  const modelSpecialty = getModelSpecialty(model);\n  const thoughtsNotSupported =\n    modelVersion === \"2.5\" && modelSpecialty === \"image\";\n  if (\n    thoughtsNotSupported ||\n    typeof thinkingBudget === \"undefined\" ||\n    typeof thinkingLevel === \"undefined\"\n  ) {\n    return undefined;\n  }\n\n  // If we have gotten this far, then we want to explicitly set if we include thoughts or not.\n  const thinkingConfig: Gemini.ThinkingConfig = {\n    includeThoughts,\n  };\n\n  // Explicitly setting the budget/level is only valid (currently) for text models.\n  if (modelSpecialty === \"\") {\n    if (model.startsWith(\"gemini-2.5\")) {\n      thinkingConfig.thinkingBudget = thinkingBudget;\n    } else {\n      thinkingConfig.thinkingLevel = thinkingLevel as Gemini.ThinkingLevel;\n    }\n  }\n\n  return thinkingConfig;\n}\n\n/**\n * Builds the `speechConfig` object for the Gemini `generationConfig`,\n * normalising the user-friendly simplified forms into the wire format.\n *\n * @param fields The combined user/call-option fields.\n * @returns A populated {@link Gemini.SpeechConfig}, or `{}`\n *          when no speech config was provided.\n */\nexport function convertFieldsToSpeechConfig(\n  fields: ChatGoogleFields\n): Gemini.SpeechConfig | undefined {\n  const config: Gemini.SpeechConfig | SimplifiedSpeechConfig | undefined =\n    fields.speechConfig;\n  if (typeof config === \"undefined\") {\n    return undefined;\n  }\n\n  function isSpeechConfig(\n    config: Gemini.SpeechConfig | SimplifiedSpeechConfig\n  ): config is Gemini.SpeechConfig {\n    return (\n      typeof config === \"object\" &&\n      (Object.hasOwn(config, \"voiceConfig\") ||\n        Object.hasOwn(config, \"multiSpeakerVoiceConfig\"))\n    );\n  }\n\n  function hasLanguage(\n    config: SimplifiedSpeechConfig\n  ): config is SimplifiedSpeechLanguageConfig {\n    return typeof config === \"object\" && Object.hasOwn(config, \"languageCode\");\n  }\n\n  function hasVoice(\n    config: SimplifiedSpeechLanguageConfig\n  ): config is SpeechVoiceLanguage {\n    return Object.hasOwn(config, \"voice\");\n  }\n\n  // If this is already a SpeechConfig, just return it\n  if (isSpeechConfig(config)) {\n    return config;\n  }\n\n  let languageCode: string | undefined;\n  let voice: SpeechVoice;\n  if (hasLanguage(config)) {\n    languageCode = config.languageCode;\n    voice = hasVoice(config) ? config.voice : config.voices;\n  } else {\n    languageCode = undefined;\n    voice = config;\n  }\n\n  let ret: Gemini.SpeechConfig;\n\n  if (typeof voice === \"string\") {\n    // They just provided the prebuilt voice configuration name. Use it.\n    ret = {\n      voiceConfig: {\n        prebuiltVoiceConfig: {\n          voiceName: voice,\n        },\n      },\n    };\n  } else {\n    // This is multi-speaker, so we have speaker/name pairs\n    // If we have just one (why?), turn it into an array for the moment\n    const voices: SpeechSpeakerName[] = Array.isArray(voice) ? voice : [voice];\n    // Go through all the speaker/name pairs and turn this into the voice config array\n    const speakerVoiceConfigs: Gemini.SpeakerVoiceConfig[] = voices.map(\n      (v: SpeechSpeakerName): Gemini.SpeakerVoiceConfig => ({\n        speaker: v.speaker,\n        voiceConfig: {\n          prebuiltVoiceConfig: {\n            voiceName: v.name,\n          },\n        },\n      })\n    );\n    // Create the multi-speaker voice configuration\n    ret = {\n      multiSpeakerVoiceConfig: {\n        speakerVoiceConfigs,\n      },\n    };\n  }\n\n  if (languageCode) {\n    ret.languageCode = languageCode;\n  }\n\n  return ret;\n}\n\ntype ServiceTierResponse = {} | { serviceTier: Gemini.ServiceTier };\n\n/**\n * Builds an object that can be included as part of the request\n * which will add a `speechConfig` attribute if appropriate.\n */\nexport function convertFieldsToServiceTier(\n  platform: GooglePlatformType,\n  fields: ChatGoogleFields\n): ServiceTierResponse {\n  // Service tier is handled in a different way on GCP\n  if (platform === \"gcp\") {\n    return {};\n  }\n\n  const serviceTier = fields.serviceTier;\n  if (!serviceTier || !settableServiceTier.includes(serviceTier)) {\n    return {};\n  }\n\n  return {\n    serviceTier: serviceTier,\n  };\n}\n"],"mappings":"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"}