Repository: TabbyML/tabby
File: clients/tabby-agent/src/codeCompletion/index.ts (TypeScript)

Code before:
      query,
      textDocument,
      config.completion.prompt.collectSnippetsFromRecentChangedFiles.maxSnippets,
    );
    this.logger.debug("Completed collecting snippets from recently changed files.");
    this.logger.trace("Collected snippets:", snippets);
    return snippets;
  }

  //get all recently opened files from the file tracker
  private async collectSnippetsFromOpenedFiles(): Promise<
    { filepath: string; offset: number; text: string; score: number }[] | undefined
  > {
    const config = this.configurations.getMergedConfig();
    if (!config.completion.prompt.collectSnippetsFromRecentOpenedFiles.enabled) {
      return undefined;
    }
    this.logger.debug("Starting collecting snippets from opened files.");
    const recentlyOpenedFiles = this.fileTracker.getAllFilesWithoutActive();
    const codeSnippets: { filepath: string; offset: number; text: string; score: number }[] = [];
    recentlyOpenedFiles.forEach((file) => {
      const doc = this.documents.get(file.uri);
      if (doc) {
        file.lastVisibleRange.forEach((range) => {
          const startOffset = doc.offsetAt(range.start);
          const text = doc.getText(range);

          //TODO(Sma1lboy): need to dynamic cal scores
          codeSnippets.push({
            filepath: file.uri,
            offset: startOffset,
            text: text,
            score: file.invisible ? 0.98 : 1,
          });
        });
      }
    });
    this.logger.debug("Completed collecting snippets from opened files.");
    return codeSnippets;
  }

  private async submitStats() {
    const stats = this.completionStats.stats();
    if (stats["completion_request"]["count"] > 0) {
      await this.anonymousUsageLogger.event("AgentStats", { stats });
      this.completionStats.reset();
    }
  }
}


Review comment (suggestion):
Use all text in the visible range may create a very long code snippet.  
I suggest to consider using `CodeSearchEngine` to split visible range into chunks when updating, and make a text search query when reading.

Code after:
      query,
      textDocument,
      config.completion.prompt.collectSnippetsFromRecentChangedFiles.maxSnippets,
    );
    this.logger.debug("Completed collecting snippets from recently changed files.");
    this.logger.trace("Collected snippets:", snippets);
    return snippets;
  }

  //get all recently opened files from the file tracker
  private async collectSnippetsFromOpenedFiles(): Promise<
    { filepath: string; offset: number; text: string; score: number }[] | undefined
  > {
    const config = this.configurations.getMergedConfig();
    if (!config.completion.prompt.collectSnippetsFromRecentOpenedFiles.enabled) {
      return undefined;
    }
    this.logger.debug("Starting collecting snippets from opened files.");
    const recentlyOpenedFiles = this.fileTracker.getAllFilesWithoutActive();
    const codeSnippets: { filepath: string; offset: number; text: string; score: number }[] = [];
    const chunkSize = config.completion.prompt.collectSnippetsFromRecentOpenedFiles.maxCharsPerOpenedFiles;
    recentlyOpenedFiles.forEach((file) => {
      const doc = this.documents.get(file.uri);
      if (doc) {
        file.lastVisibleRange.forEach((range: Range) => {
          this.logger.info(
            `Original range: start(${range.start.line},${range.start.character}), end(${range.end.line},${range.end.character})`,
          );

          const startOffset = doc.offsetAt(range.start);
          const endOffset = doc.offsetAt(range.end);
          const middleOffset = Math.floor((startOffset + endOffset) / 2);
          const halfChunkSize = Math.floor(chunkSize / 2);

          const upwardChunkSize = Math.min(halfChunkSize, middleOffset);
          const newStartOffset = middleOffset - upwardChunkSize;

          const downwardChunkSize = Math.min(chunkSize - upwardChunkSize, doc.getText().length - middleOffset);
          let newEndOffset = middleOffset + downwardChunkSize;

          if (newEndOffset - newStartOffset > chunkSize) {
            const excess = newEndOffset - newStartOffset - chunkSize;
            newEndOffset -= excess;
          }

          let newStart = doc.positionAt(newStartOffset);
          let newEnd = doc.positionAt(newEndOffset);

          newStart = { line: newStart.line, character: 0 };
          newEnd = {
            line: newEnd.line,