Member Junction
    Preparing search index...
    SearchStreamEvent:
        | {
            durationMs: number;
            phase: "provider";
            providerName: string;
            resultCount: number;
            results: SearchResultItem[];
        }
        | { phase: "fused"; results: SearchResultItem[] }
        | { phase: "reranked"; rerankerName: string; results: SearchResultItem[] }
        | {
            elapsedMs: number;
            phase: "final";
            results: SearchResultItem[];
            sourceCounts: {
                Entity: number;
                FullText: number;
                Storage: number;
                Tag?: number;
                Vector: number;
            };
        }
        | { error: string; phase: "error"; providerName?: string }

    Discriminated union emitted by SearchEngine.streamSearch() as each pipeline stage produces output. Consumers should treat unknown phases as no-ops to remain forward-compatible with future stages (e.g. a 'permission-filtered' phase added later).

    Type Declaration

    • {
          durationMs: number;
          phase: "provider";
          providerName: string;
          resultCount: number;
          results: SearchResultItem[];
      }
      • durationMs: number

        Provider wall-clock duration in ms.

      • phase: "provider"

        Progress: one provider has returned. Carries no record content — the provider's hits have not been through the permission pass yet. Results arrive in fused and final.

      • providerName: string

        Friendly provider name that just returned (Vector / FullText / Entity / Storage / external).

      • resultCount: number

        How many hits this provider returned, capped at the caller's MaxResults. Counted before fusion, the permission pass and any audience pass, like SearchResult.SourceCounts — so don't show it to a room.

      • results: SearchResultItem[]

        Always empty: a provider's hits arrive before the permission pass, so the stream never carries them. Use resultCount for progress and the final event for results.

    • { phase: "fused"; results: SearchResultItem[] }
      • phase: "fused"
      • results: SearchResultItem[]

        RRF-fused list across providers (and across scopes when applicable).

    • { phase: "reranked"; rerankerName: string; results: SearchResultItem[] }
      • phase: "reranked"
      • rerankerName: string

        Reranker class name (Cohere / Voyage / BGE / Noop / etc.)

      • results: SearchResultItem[]

        Reranker-permuted list. Same items as 'fused', new order.

    • {
          elapsedMs: number;
          phase: "final";
          results: SearchResultItem[];
          sourceCounts: {
              Entity: number;
              FullText: number;
              Storage: number;
              Tag?: number;
              Vector: number;
          };
      }
      • elapsedMs: number

        Total wall-clock duration of the stream.

      • phase: "final"
      • results: SearchResultItem[]

        Post-deduplication, post-permission, post-enrich result set — what Search() would have returned.

      • sourceCounts: {
            Entity: number;
            FullText: number;
            Storage: number;
            Tag?: number;
            Vector: number;
        }

        Same shape as the synchronous SearchResult.SourceCounts.

    • { error: string; phase: "error"; providerName?: string }
      • error: string

        Human-readable error message (do NOT include stack traces).

      • phase: "error"
      • OptionalproviderName?: string

        Provider that failed, if scoped to one.