Repository: TabbyML/tabby
File: clients/vscode/src/chat/webview.ts (TypeScript)

Code before:
        const maxResults = params.limit || 50;
        const searchQuery = params.query?.trim();
        const res: ListFileItem[] = [];
        let openTabs = window.tabGroups.all
          .flatMap((group) => group.tabs)
          .filter((tab) => tab.input && (tab.input as TabInputText).uri)
          .map((tab) => (tab.input as TabInputText).uri);

        openTabs = openTabs.filter((uri, idx) => openTabs.indexOf(uri) === idx);

        res.push(...openTabs.map((uri) => localUriToListFileItem(uri, this.gitProvider, "openedInEditor")));

        const globPattern = caseInsensitivePattern(searchQuery);
        try {
          let files = await this.findFiles(globPattern, {
            maxResults: maxResults,
            excludes: openTabs.map((uri) => uri.fsPath),
          });
          files = files.filter(
            (uri, idx) => files.indexOf(uri) === idx && !openTabs.some((tabUri) => tabUri.fsPath === uri.fsPath),
          );
          this.logger.debug(`Found ${files.length} files matching pattern "${globPattern}"`);
          res.push(...files.map((uri) => localUriToListFileItem(uri, this.gitProvider, "searchResult")));
        } catch (error) {
          this.logger.warn("Failed to find files:", error);
          return [];
        }

        return res;
      },

      readFileContent: async (info: FileRange): Promise<string | null> => {
        const uri = chatPanelFilepathToLocalUri(info.filepath, this.gitProvider);
        if (!uri) {
          this.logger.warn(`Could not resolve URI from filepath: ${JSON.stringify(info.filepath)}`);
          return null;
        }
        const document = await workspace.openTextDocument(uri);
        return document.getText(chatPanelLocationToVSCodeRange(info.range) ?? undefined);
      },
      listSymbols: async (params: ListSymbolsParams): Promise<ListSymbolItem[]> => {
        const { query } = params;
        let { limit } = params;
        const editor = window.activeTextEditor;

        if (!editor) {
          this.logger.warn("listActiveSymbols: No active editor found.");
          return [];
        }
        if (!limit || limit < 0) {
          limit = 20;

Review comment (bug):
```suggestion
```

When the search failed, just skip pushing the search result, the openTabs result can always be returned.

Code after:
        const maxResults = params.limit || 50;
        const searchQuery = params.query?.trim();
        const res: ListFileItem[] = [];
        let openTabs = window.tabGroups.all
          .flatMap((group) => group.tabs)
          .filter((tab) => tab.input && (tab.input as TabInputText).uri)
          .map((tab) => (tab.input as TabInputText).uri);

        openTabs = openTabs.filter((uri, idx) => openTabs.indexOf(uri) === idx);

        res.push(...openTabs.map((uri) => localUriToListFileItem(uri, this.gitProvider, "openedInEditor")));
        if (res.length > maxResults) {
          return res.slice(0, maxResults);
        }

        const globPattern = caseInsensitivePattern(searchQuery);
        try {
          let files = await this.findFiles(globPattern, {
            maxResults: maxResults - res.length,
            excludes: openTabs.map((uri) => uri.fsPath),
          });
          files = files.filter(
            (uri, idx) => files.indexOf(uri) === idx && !openTabs.some((tabUri) => tabUri.fsPath === uri.fsPath),
          );
          this.logger.debug(`Found ${files.length} files matching pattern "${globPattern}"`);
          res.push(...files.map((uri) => localUriToListFileItem(uri, this.gitProvider, "searchResult")));
        } catch (error) {
          this.logger.warn("Failed to find files:", error);
        }
        return res;
      },

      readFileContent: async (info: FileRange): Promise<string | null> => {
        const uri = chatPanelFilepathToLocalUri(info.filepath, this.gitProvider);
        if (!uri) {
          this.logger.warn(`Could not resolve URI from filepath: ${JSON.stringify(info.filepath)}`);
          return null;
        }
        const document = await workspace.openTextDocument(uri);
        return document.getText(chatPanelLocationToVSCodeRange(info.range) ?? undefined);
      },
      listSymbols: async (params: ListSymbolsParams): Promise<ListSymbolItem[]> => {
        const { query } = params;
        let { limit } = params;
        const editor = window.activeTextEditor;

        if (!editor) {
          this.logger.warn("listActiveSymbols: No active editor found.");
          return [];
        }
        if (!limit || limit < 0) {