async getChatCompletion(messages = null, { temperature }) {
    if (!messages?.length)
      throw new Error(
        "AWSBedrock::getChatCompletion requires a non-empty messages array."
      );

    const hasSystem = messages[0]?.role === "system";
    const systemBlock = hasSystem ? messages[0].content : undefined;
    const history = hasSystem ? messages.slice(1) : messages;
    const maxTokensToSend = this.getMaxOutputTokens();

    const result = await LLMPerformanceMonitor.measureAsyncFunction(
      this.bedrockClient
        .send(
          new ConverseCommand({
            modelId: this.model,
            messages: history,
            inferenceConfig: {
              maxTokens: maxTokensToSend,
              temperature: temperature ?? this.defaultTemp,
            },
            system: systemBlock,
          })
        )
        .catch((e) => {
          this.#log(
            `Bedrock Converse API Error (getChatCompletion): ${e.message}`,
            e
          );
          if (
            e.name === "ValidationException" &&
            e.message.includes("maximum tokens")
          ) {
            throw new Error(
              `AWSBedrock::getChatCompletion failed. Model ${this.model} rejected maxTokens value of ${maxTokensToSend}. Check model documentation for its maximum output token limit and set AWS_BEDROCK_LLM_MAX_OUTPUT_TOKENS if needed. Original error: ${e.message}`
            );
          }
          throw new Error(`AWSBedrock::getChatCompletion failed. ${e.message}`);
        }),
      messages,
      false
    );

    const response = result.output;
    if (!response?.output?.message) {
      this.#log(
        "Bedrock response missing expected output.message structure.",
        response
      );
      return null;
    }

    const latencyMs = response?.metrics?.latencyMs;
    const outputTokens = response?.usage?.outputTokens;
    const outputTps =
      latencyMs > 0 && outputTokens ? outputTokens / (latencyMs / 1000) : 0;

    return {
      textResponse: this.#parseReasoningFromResponse(response.output.message),
      metrics: {
        prompt_tokens: response?.usage?.inputTokens ?? 0,
        completion_tokens: outputTokens ?? 0,
        total_tokens: response?.usage?.totalTokens ?? 0,
        outputTps: outputTps,
        duration: result.duration,
      },
    };
  }
Sends a request for chat completion (non-streaming).
@param {Array<object> | null} messages - Formatted message array from constructPrompt.
@param {object} options - Request options.
@param {number} options.temperature - Sampling temperature.
@returns {Promise<object | null>} Response object with textResponse and metrics, or null.
@throws {Error} If the API call fails or validation errors occur.