Repository: TabbyML/tabby
File: clients/tabby-agent/src/http/tabbyApiClient.ts (TypeScript)

Code before:
      } else if (!(error instanceof HttpError)) {
        this.logger.error(`Fetch server provided config request failed. [${requestId}]`, error);
      }
    }
  }

  async fetchCompletion(
    request: TabbyApiComponents["schemas"]["CompletionRequest"],
    signal?: AbortSignal,
    stats?: CompletionStats,
  ): Promise<TabbyApiComponents["schemas"]["CompletionResponse"]> {
    const requestId = uuid();
    const requestPath = "/v1/completions";
    const requestDescription = `POST ${this.endpoint + requestPath}`;
    const requestOptions = {
      body: request,
      signal: abortSignalFromAnyOf([signal, this.createTimeOutAbortSignal()]),
    };

    const requestStartedAt = performance.now();
    const statsData = {
      latency: NaN,
      canceled: false,
      timeout: false,
      notAvailable: false,
      rateLimited: false,
    };

    try {
      if (!this.api) {
        throw new Error("http client not initialized");
      }
      this.logger.debug(`Completion request: ${requestDescription}. [${requestId}]`);
      this.logger.trace(`Completion request body: [${requestId}]`, requestOptions.body);
      this.updateIsFetchingCompletion(true);
      const response = await this.api.POST(requestPath, requestOptions);
      this.updateIsFetchingCompletion(false);
      this.logger.debug(`Completion response status: ${response.response.status}. [${requestId}]`);
      if (response.error || !response.response.ok) {
        throw new HttpError(response.response);
      }
      this.logger.trace(`Completion response data: [${requestId}]`, response.data);
      statsData.latency = performance.now() - requestStartedAt;
      return response.data;
    } catch (error) {
      this.updateIsFetchingCompletion(false);
      if (isCanceledError(error)) {
        this.logger.debug(`Completion request canceled. [${requestId}]`);
        statsData.canceled = true;
      } else if (isTimeoutError(error)) {
        this.logger.debug(`Completion request timed out. [${requestId}]`);

Review comment (suggestion):
Don't add rateLimited in statsData, call `updateIsRateLimited` directly in the error handling branches.

Code after:
      } else if (!(error instanceof HttpError)) {
        this.logger.error(`Fetch server provided config request failed. [${requestId}]`, error);
      }
    }
  }

  async fetchCompletion(
    request: TabbyApiComponents["schemas"]["CompletionRequest"],
    signal?: AbortSignal,
    stats?: CompletionStats,
  ): Promise<TabbyApiComponents["schemas"]["CompletionResponse"]> {
    const requestId = uuid();
    const requestPath = "/v1/completions";
    const requestDescription = `POST ${this.endpoint + requestPath}`;
    const requestOptions = {
      body: request,
      signal: abortSignalFromAnyOf([signal, this.createTimeOutAbortSignal()]),
    };

    const requestStartedAt = performance.now();
    const statsData = {
      latency: NaN,
      canceled: false,
      timeout: false,
      notAvailable: false,
    };

    try {
      if (!this.api) {
        throw new Error("http client not initialized");
      }
      this.logger.debug(`Completion request: ${requestDescription}. [${requestId}]`);
      this.logger.trace(`Completion request body: [${requestId}]`, requestOptions.body);
      this.updateIsFetchingCompletion(true);
      const response = await this.api.POST(requestPath, requestOptions);
      this.updateIsFetchingCompletion(false);
      this.logger.debug(`Completion response status: ${response.response.status}. [${requestId}]`);
      if (response.error || !response.response.ok) {
        throw new HttpError(response.response);
      }
      this.logger.trace(`Completion response data: [${requestId}]`, response.data);
      statsData.latency = performance.now() - requestStartedAt;
      this.updateIsRateLimitExceeded(false);
      return response.data;
    } catch (error) {
      this.updateIsFetchingCompletion(false);
      if (isCanceledError(error)) {
        this.logger.debug(`Completion request canceled. [${requestId}]`);
        statsData.canceled = true;
      } else if (isTimeoutError(error)) {
        this.logger.debug(`Completion request timed out. [${requestId}]`);