SPB Git

spb/search-box Public

Agentic web research engine — hypotheses, verbatim evidence, contradictions, sourced answers streamed live. Claude Opus 5 + Firecrawl + PostgreSQL.

TypeScript 76.9% CSS 18.7% SQL 2.1% JavaScript 1.8% Shell 0.5%
2.0 KB · 70 lines typescript
Raw Blame History
1/**2 * Search-box.ai3 * Author: Simon-Pierre Boucher4 * Contact: contact@spboucher.ai5 * File: packages/events/src/index.ts6 * Description: Typed research event protocol streamed from backend to UI.7 */89import type {10  Claim,11  Contradiction,12  Evidence,13  SessionStatus,14  Source15} from "@search-box/shared";1617/**18 * Every UI update corresponds to exactly one of these events, persisted in19 * order (monotonic `seq`) so streams can be replayed via Last-Event-ID.20 */21export type ResearchEventPayload =22  | { type: "session.started"; question: string }23  | { type: "session.status"; status: SessionStatus }24  | { type: "session.completed"; answer: string }25  | { type: "session.failed"; error: string }26  | { type: "plan.updated"; objectives: string[]; publicReason: string }27  | { type: "thought"; publicReason: string }28  | {29      type: "action.started";30      actionId: string;31      kind: "search" | "fetch";32      label: string;33      input: Record<string, unknown>;34    }35  | {36      type: "action.completed";37      actionId: string;38      kind: "search" | "fetch";39      ok: boolean;40      summary: string;41      latencyMs: number;42    }43  | { type: "source.added"; source: Source }44  | { type: "source.updated"; source: Source }45  | { type: "evidence.added"; evidence: Evidence; sourceUrl: string; sourceTitle: string | null }46  | { type: "claim.added"; claim: Claim }47  | { type: "claim.updated"; claim: Claim }48  | { type: "contradiction.added"; contradiction: Contradiction }49  | { type: "budget.updated"; usage: Record<string, number>; limits: Record<string, number> }50  | { type: "synthesis.started" }51  | { type: "answer.delta"; delta: string }52  | { type: "answer.completed"; answer: string; citations: CitationMapEntry[] };5354export interface CitationMapEntry {55  index: number;56  sourceId: string;57  url: string;58  title: string | null;59}6061export interface ResearchEvent {62  id: string;63  sessionId: string;64  seq: number;65  createdAt: string;66  payload: ResearchEventPayload;67}6869export type ResearchEventType = ResearchEventPayload["type"];70