BID · Console
Baseline · Intelligence · Decision
src/tools/retrieval/interface.ts 2,904 bytes · typescript
/**
 * Retrieval connector contract.
 *
 * Any retrieval implementation (mock, SEC EDGAR, Bloomberg, an
 * internal database, a CSV vault) implements RetrievalConnector and is
 * registered with the dispatcher under a unique `name`. The
 * orchestrator routes JobRequest.sources to the right connector — the
 * framework itself ships with no domain-specific connector, only the
 * mock one.
 *
 * Standard 5 (methods & tools): connectors are tool descriptors with
 * approved capabilities; the dispatcher refuses unregistered sources.
 * Standard 12 (failure handling): connectors throw RetrievalError; the
 * dispatcher converts to a structured DispatchResult — never raw.
 */

import type { Capability } from '../../standards.js';

export interface RetrievalConnector {
  /** Unique registration key, e.g. "sec-edgar", "bloomberg", "mock". */
  readonly name: string;
  /** Whether the connector needs credentials to operate. */
  readonly authRequired: boolean;
  /** Rate limit envelope the dispatcher enforces on behalf of the connector. */
  readonly rateLimit: { readonly requestsPerSecond: number; readonly burstSize?: number };

  /** Fetch a raw payload. Throws RetrievalError on failure. */
  fetch(params: FetchParams): Promise<RawPayload>;

  /** Liveness probe — returns false if the connector is misconfigured / down. */
  isAvailable(): Promise<boolean>;
}

export interface FetchParams {
  readonly entity: { readonly id: string; readonly aliases: readonly string[] };
  readonly period: string;
  readonly filingTypes?: readonly string[];
  readonly query?: Readonly<Record<string, unknown>>;
}

export interface RawPayload {
  /** The connector that produced this payload. */
  readonly source: string;
  /** Canonical URL of the upstream document, if applicable. */
  readonly sourceUrl?: string;
  /** ISO-8601 timestamp the payload was captured. */
  readonly capturedAt: string;
  /** MIME type — "text/html", "application/json", "application/xbrl+xml", etc. */
  readonly contentType: string;
  /** The raw response bytes as a UTF-8 string. */
  readonly rawContent: string;
  /** Connector-defined free-form metadata; persisted as-is for audit. */
  readonly metadata: Readonly<Record<string, unknown>>;
}

export type RetrievalErrorCategory =
  | 'unavailable'
  | 'no-content'
  | 'auth-failed'
  | 'rate-limited'
  | 'connector-not-registered'
  | 'invalid-request'
  | 'internal';

export class RetrievalError extends Error {
  constructor(
    public readonly category: RetrievalErrorCategory,
    message: string,
    public readonly context?: Record<string, unknown>,
  ) {
    super(message);
    this.name = 'RetrievalError';
  }
}

/** Capability-typed tool descriptor for the retrieval dispatcher itself (Std 5). */
export const retrievalToolDescriptor = {
  name: 'retrieval-dispatcher',
  capability: 'retrieval' as Capability,
  approved: true,
} as const;