{"version":3,"sources":["../src/errors.ts","../src/resources/analyst.ts","../src/resources/calendar.ts","../src/resources/documents.ts","../src/resources/earnings.ts","../src/resources/entityMetrics.ts","../src/resources/etfs.ts","../src/resources/insider.ts","../src/resources/politicians.ts","../src/resources/insights.ts","../src/resources/institutional.ts","../src/resources/kb.ts","../src/resources/marketMood.ts","../src/resources/marketSummary.ts","../src/resources/options.ts","../src/resources/screener.ts","../src/resources/stocks.ts","../src/resources/indexes.ts","../src/resources/trackers.ts","../src/version.ts","../src/client.ts"],"sourcesContent":["export class SentiSenseError extends Error {\n  status?: number;\n  code?: string;\n\n  constructor(message: string, status?: number, code?: string) {\n    super(message);\n    this.name = \"SentiSenseError\";\n    this.status = status;\n    this.code = code;\n  }\n}\n\nexport class AuthenticationError extends SentiSenseError {\n  constructor(message: string, status: number, code?: string) {\n    super(message, status, code);\n    this.name = \"AuthenticationError\";\n  }\n}\n\nexport class NotFoundError extends SentiSenseError {\n  constructor(message: string, code?: string) {\n    super(message, 404, code);\n    this.name = \"NotFoundError\";\n  }\n}\n\n/**\n * Thrown when a deep chart range is still being assembled.\n *\n * The API answers 202 for \"10Y\" and \"MAX\" the first time a rarely-requested stock is asked\n * for. It deliberately does not substitute a shorter range, so a successful response always\n * carries the timeframe you asked for. Retry after a few seconds.\n */\nexport class DeepHistoryUnavailableError extends SentiSenseError {\n  retryAfter?: number;\n\n  constructor(message: string, retryAfter?: number) {\n    super(message, 202);\n    this.name = \"DeepHistoryUnavailableError\";\n    this.retryAfter = retryAfter;\n  }\n}\n\nexport class RateLimitError extends SentiSenseError {\n  /**\n   * Seconds to wait before retrying, from the server's `Retry-After` header, clamped to\n   * `[0.5, 120]`. Always either a finite number or `undefined`: an absent header, or one\n   * carrying an HTTP-date instead of a number of seconds, leaves it undefined rather than\n   * `NaN`, so `setTimeout(fn, err.retryAfter * 1000)` can never fire immediately.\n   */\n  retryAfter?: number;\n\n  constructor(message: string, code?: string, retryAfter?: number) {\n    super(message, 429, code);\n    this.name = \"RateLimitError\";\n    this.retryAfter = retryAfter;\n  }\n}\n\nexport class APIError extends SentiSenseError {\n  constructor(message: string, status: number, code?: string) {\n    super(message, status, code);\n    this.name = \"APIError\";\n  }\n}\n","import type { APIClient } from \"../client.js\";\nimport type { PreviewResponse } from \"../types.js\";\n\nexport interface AnalystConsensus {\n  ticker: string;\n  currentPrice: number | null;\n  targetLow: number | null;\n  targetMean: number | null;\n  targetHigh: number | null;\n  targetMedian: number | null;\n  numberOfAnalysts: number;\n  upsidePercent: number | null;\n  consensusLabel: string | null;\n  recommendationMean: number | null;\n  /** PRO-only; zero in the free preview. */\n  strongBuy: number;\n  /** PRO-only; zero in the free preview. */\n  buy: number;\n  /** PRO-only; zero in the free preview. */\n  hold: number;\n  /** PRO-only; zero in the free preview. */\n  sell: number;\n  /** PRO-only; zero in the free preview. */\n  strongSell: number;\n  updatedAt: string | null;\n}\n\nexport interface AnalystAction {\n  ticker: string;\n  actionDate: string;\n  firm: string;\n  /** UPGRADE, DOWNGRADE, INITIATE, REITERATE, OTHER */\n  actionType: string;\n  fromGrade: string | null;\n  toGrade: string | null;\n}\n\nexport interface AnalystEstimate {\n  /** Fiscal period descriptor (provider-specific shape). */\n  [key: string]: unknown;\n}\n\nexport interface AnalystEarningsSurprise {\n  /** Past report descriptor (provider-specific shape). */\n  [key: string]: unknown;\n}\n\nexport interface AnalystEstimatesResponse {\n  estimates: AnalystEstimate[];\n  surprises: AnalystEarningsSurprise[];\n}\n\nexport interface GetAnalystActionsOptions {\n  /** Days of history to return. Default 90. */\n  lookbackDays?: number;\n}\n\nexport interface GetAnalystMarketActivityOptions {\n  /** Days of history to return. Default 30. */\n  lookbackDays?: number;\n}\n\n/**\n * Wall Street analyst coverage: aggregate price targets, recommendation distribution,\n * recent upgrade/downgrade actions, and forward EPS estimates with earnings surprise history.\n *\n * Free users receive the price target band (low/mean/high + analyst count + consensus label)\n * in full -- it powers the public projection cone. The buy/hold/sell distribution counts\n * and full action/estimate history are PRO-only.\n */\nexport class Analyst {\n  constructor(private client: APIClient) {}\n\n  /**\n   * Get the aggregate Wall Street consensus for a ticker. Returns 404 if no\n   * coverage exists.\n   */\n  async consensus(\n    ticker: string,\n  ): Promise<PreviewResponse<AnalystConsensus>> {\n    return this.client.get(\n      `/api/v1/analyst/${encodeURIComponent(ticker.toUpperCase())}/consensus`,\n    );\n  }\n\n  /**\n   * Get recent analyst upgrade/downgrade actions for a ticker, newest first.\n   * Free users receive the 3 most recent.\n   */\n  async actions(\n    ticker: string,\n    options?: GetAnalystActionsOptions,\n  ): Promise<PreviewResponse<AnalystAction[]>> {\n    return this.client.get(\n      `/api/v1/analyst/${encodeURIComponent(ticker.toUpperCase())}/actions`,\n      options,\n    );\n  }\n\n  /**\n   * Get forward EPS estimates and earnings surprise history for a ticker.\n   * Free users receive 1 estimate (current quarter) plus the 2 most recent surprises.\n   */\n  async estimates(\n    ticker: string,\n  ): Promise<PreviewResponse<AnalystEstimatesResponse>> {\n    return this.client.get(\n      `/api/v1/analyst/${encodeURIComponent(ticker.toUpperCase())}/estimates`,\n    );\n  }\n\n  /**\n   * Get market-wide recent analyst actions across all covered tickers, newest first.\n   * Free users receive the 5 most recent.\n   */\n  async marketActivity(\n    options?: GetAnalystMarketActivityOptions,\n  ): Promise<PreviewResponse<AnalystAction[]>> {\n    return this.client.get(\"/api/v1/analyst/activity\", options);\n  }\n}\n","import type { APIClient } from \"../client.js\";\nimport type {\n  EarningsCalendarResponse,\n  GetEarningsCalendarOptions,\n  PreviewResponse,\n} from \"../types.js\";\n\nexport class Calendar {\n  constructor(private client: APIClient) {}\n\n  /**\n   * Upcoming company earnings, sorted by date.\n   *\n   * Key-required. A FREE key returns the current week (`isPreview: true`); a PRO\n   * key returns the full forward window (about 30 days). Field richness is\n   * identical across tiers: the gate is how far ahead you can see, not which\n   * columns you get. On a preview, `totalCount` is the full-window event count.\n   */\n  async getEarnings(\n    options?: GetEarningsCalendarOptions,\n  ): Promise<PreviewResponse<EarningsCalendarResponse>> {\n    return this.client.get(\"/api/v1/calendar/earnings\", options);\n  }\n}\n","import type { APIClient } from \"../client.js\";\nimport type {\n  DocumentSearchResponse,\n  DocumentSource,\n  GetByEntityOptions,\n  GetBySourceOptions,\n  GetByTickerOptions,\n  GetByTickerRangeOptions,\n  GetStoriesByTickerOptions,\n  GetStoriesOptions,\n  SearchDocumentsOptions,\n  Story,\n} from \"../types.js\";\n\nexport class Documents {\n  constructor(private client: APIClient) {}\n\n  /** Get document metrics for a stock. The rows are in `documents`. */\n  async getByTicker(ticker: string, options?: GetByTickerOptions): Promise<DocumentSearchResponse> {\n    return this.client.get(`/api/v1/documents/ticker/${encodeURIComponent(ticker)}`, options);\n  }\n\n  /** Get document metrics for a stock within a date range. The rows are in `documents`. */\n  async getByTickerRange(ticker: string, options: GetByTickerRangeOptions): Promise<DocumentSearchResponse> {\n    return this.client.get(\n      `/api/v1/documents/ticker/${encodeURIComponent(ticker)}/range`,\n      options,\n    );\n  }\n\n  /** Get document metrics for a KB entity. The rows are in `documents`. */\n  async getByEntity(entityId: string, options?: GetByEntityOptions): Promise<DocumentSearchResponse> {\n    return this.client.get(\n      `/api/v1/documents/entity/${encodeURIComponent(entityId)}`,\n      options,\n    );\n  }\n\n  /** Smart search with natural language query parsing. The rows are in `documents`. */\n  async search(query: string, options?: SearchDocumentsOptions): Promise<DocumentSearchResponse> {\n    return this.client.get(\"/api/v1/documents/search\", { query, ...options });\n  }\n\n  /** Get latest document metrics from a source type. The rows are in `documents`. */\n  async getBySource(source: DocumentSource, options?: GetBySourceOptions): Promise<DocumentSearchResponse> {\n    return this.client.get(\n      `/api/v1/documents/source/${encodeURIComponent(source)}`,\n      options,\n    );\n  }\n\n  /** Get AI-curated news story clusters. */\n  async getStories(options?: GetStoriesOptions): Promise<Story[]> {\n    return this.client.get(\"/api/v1/documents/stories\", options);\n  }\n\n  /** Get full story detail by cluster ID. */\n  async getStoryDetail(clusterId: string): Promise<unknown> {\n    return this.client.get(`/api/v1/documents/stories/${encodeURIComponent(clusterId)}`);\n  }\n\n  /** Get stories for a specific stock. */\n  async getStoriesByTicker(\n    ticker: string,\n    options?: GetStoriesByTickerOptions,\n  ): Promise<Story[]> {\n    return this.client.get(\n      `/api/v1/documents/stories/ticker/${encodeURIComponent(ticker)}`,\n      options,\n    );\n  }\n\n}\n","import type { APIClient } from \"../client.js\";\nimport type {\n  EarningsQuarter,\n  GetEarningsSummariesOptions,\n  GetRecentEarningsOptions,\n  PreviewResponse,\n  RecentEarningsEntry,\n} from \"../types.js\";\n\n/**\n * Earnings: what a company actually reported, after the fact.\n *\n * A quarter's results arrive as a press release, a filing, and a call, none of\n * which is a data structure. {@link getSummaries} is the assembled version, one\n * object per fiscal quarter, and {@link getRecent} is the cross-ticker view of\n * who reported lately. Pair them to drive a post-earnings sweep: list the\n * window, then pull each ticker's analysis report.\n *\n * The forward-looking half of the family lives on `client.calendar.getEarnings()`,\n * which covers scheduled dates and consensus EPS rather than results.\n *\n * @see EarningsQuarter\n */\nexport class Earnings {\n  constructor(private client: APIClient) {}\n\n  /**\n   * Per-quarter earnings analysis report for one ticker, newest first.\n   *\n   * Each quarter carries the editorial headline, the KPI cards that matter for\n   * that company with year-over-year deltas, the guidance language as\n   * management phrased it, and a summary of the earnings call.\n   *\n   * Branch on `isPreview`: a PRO key receives every hydrated quarter in full, a\n   * FREE key receives the latest quarter shaped rather than truncated, plus\n   * `totalCount`. {@link EarningsQuarter} documents which fields each tier\n   * carries.\n   *\n   * A quarter typically appears within 48 hours of the company reporting, and\n   * the call summary can arrive after the press-release content for the same\n   * quarter, so read `generatedAt` and `transcriptGeneratedAt` rather than\n   * assuming a fixed lag. A ticker with no stored quarter answers with an empty\n   * `data` array, not a 404.\n   *\n   * Use canonical ticker symbols: `GOOGL` (not `GOOG`), `BRK.B` (not `BRK-B`).\n   */\n  async getSummaries(\n    ticker: string,\n    options?: GetEarningsSummariesOptions,\n  ): Promise<PreviewResponse<EarningsQuarter[]>> {\n    return this.client.get(\n      `/api/v1/stocks/${encodeURIComponent(ticker.toUpperCase())}/earnings-summaries`,\n      options,\n    );\n  }\n\n  /**\n   * Which covered companies reported on or after `today - days`, newest first.\n   *\n   * Every API key receives the full window it asks for, so `isPreview` is\n   * always `false` here. The window is bounded by `reportDate`, so a quarter\n   * reported inside it appears even when its call summary lands later, and an\n   * empty `data` array means nobody in the covered set reported in that window.\n   *\n   * This is the backward-looking feed; `client.calendar.getEarnings()` is the\n   * forward-looking one.\n   */\n  async getRecent(\n    options?: GetRecentEarningsOptions,\n  ): Promise<PreviewResponse<RecentEarningsEntry[]>> {\n    return this.client.get(\"/api/v1/earnings/recent\", options);\n  }\n}\n","import type { APIClient } from \"../client.js\";\nimport type {\n  MetricType,\n  MetricsOptions,\n  MetricDistributionOptions,\n  ServingMetric,\n  MetricDistribution,\n} from \"../types.js\";\n\nexport class EntityMetrics {\n  constructor(private client: APIClient) {}\n\n  /**\n   * Get time-series metric data for an entity using the v2 Serving Metrics API.\n   *\n   * @param symbol   Ticker symbol (e.g. \"AAPL\") or entity urlSlug (e.g. \"Nancy-Pelosi\",\n   *                 case-insensitive; discover slugs via stocks.getEntities()).\n   * @param options  Metric type and optional time range / resolution.\n   */\n  async getMetrics(\n    symbol: string,\n    options: MetricsOptions = {},\n  ): Promise<ServingMetric[]> {\n    const { metricType = \"sentiment\", startTime, endTime, maxDataPoints } = options;\n    return this.client.get(\n      `/api/v2/metrics/entity/${encodeURIComponent(symbol)}/metric/${encodeURIComponent(metricType)}`,\n      {\n        ...(startTime !== undefined && { startTime }),\n        ...(endTime !== undefined && { endTime }),\n        ...(maxDataPoints !== undefined && { maxDataPoints }),\n      },\n    );\n  }\n\n  /**\n   * Get distribution data for a metric, broken down by a dimension (default: source).\n   *\n   * @param symbol     Ticker symbol (e.g. \"AAPL\") or entity urlSlug.\n   * @param metricType The metric to break down (e.g. \"mentions\", \"sentiment\").\n   * @param options    Optional dimension parameter.\n   */\n  async getDistribution(\n    symbol: string,\n    metricType: MetricType,\n    options: MetricDistributionOptions = {},\n  ): Promise<MetricDistribution> {\n    const { dimension = \"source\" } = options;\n    return this.client.get(\n      `/api/v2/metrics/entity/${encodeURIComponent(symbol)}/distribution/${encodeURIComponent(metricType)}`,\n      { dimension },\n    );\n  }\n}\n","import type { APIClient } from \"../client.js\";\nimport type { PreviewResponse } from \"../types.js\";\n\nexport interface EtfInfo {\n  ticker: string;\n  name: string;\n  kbEntityId: string | null;\n  urlSlug: string | null;\n  issuer: string | null;\n  trackedIndex: string | null;\n  assetClass: string | null;\n}\n\nexport interface EtfHolding {\n  ticker: string;\n  name: string | null;\n  /** Weight in the fund as a percentage (0-100). */\n  weightPct: number;\n  /** ISO date \"YYYY-MM-DD\". First date this holding appeared in the composition. */\n  firstSeen: string | null;\n}\n\nexport interface EtfHoldings {\n  ticker: string;\n  issuer: string;\n  issuerEndpoint: string | null;\n  /** ISO date \"YYYY-MM-DD\". Composition snapshot date from the issuer. */\n  asOfDate: string;\n  /** Epoch seconds when SentiSense refreshed the composition. */\n  fetchedAt: number | null;\n  /** ISO date \"YYYY-MM-DD\". When the composition is scheduled to be refreshed next. */\n  nextRefreshDue: string;\n  totalHoldings: number;\n  holdings: EtfHolding[];\n  /** True when this is a top-N view rather than the full fund. */\n  partial?: boolean | null;\n  /** Issuer's reported total holdings when `partial=true`. */\n  totalKnownHoldings?: number | null;\n}\n\nexport interface EtfAggregateCoverage {\n  holdingsCount: number;\n  holdingsCovered: number;\n  /** Sum of weights (0-100) for the covered holdings. */\n  weightCovered: number;\n  partial?: boolean | null;\n  totalKnownHoldings?: number | null;\n}\n\nexport interface WeightedConsensus {\n  upsidePercent: number | null;\n  consensusLabel: string | null;\n  /** Fractions of covered AUM in each bucket. Sums to ~1.0. */\n  distribution: Record<string, number>;\n  totalAnalysts: number;\n}\n\nexport interface EtfAnalystContributor {\n  ticker: string;\n  weightPct: number;\n  upsidePercent: number | null;\n  consensusLabel: string | null;\n  /** Signed contribution to the fund's weighted upside in percentage points. */\n  contributionPp: number;\n}\n\nexport interface EtfAnalystAggregate {\n  ticker: string;\n  /** ISO date \"YYYY-MM-DD\". Composition snapshot date. */\n  asOfDate: string | null;\n  /** Epoch seconds when this rollup was computed. */\n  computedAt: number;\n  coverage: EtfAggregateCoverage;\n  weightedConsensus: WeightedConsensus;\n  /** Top contributors (up to 10) by absolute contribution to the weighted upside. */\n  topContributors: EtfAnalystContributor[];\n}\n\nexport interface WeightedNetFlow {\n  /** Weighted net dollar flow (buys - sells). Negative = net selling. */\n  netDollars: number;\n  buyDollars: number;\n  sellDollars: number;\n  /** Unweighted; for context. */\n  buyTradeCount: number;\n  /** Unweighted; for context. */\n  sellTradeCount: number;\n  distinctInsiderCount: number;\n}\n\nexport interface EtfInsiderContributor {\n  ticker: string;\n  weightPct: number;\n  /** Per-stock net flow over the window (signed). */\n  netDollars: number;\n  /** Signed contribution to the weighted headline. */\n  weightedNetDollars: number;\n  tradeCount: number;\n}\n\nexport interface EtfInsiderAggregate {\n  ticker: string;\n  /** ISO date \"YYYY-MM-DD\". Composition snapshot date. */\n  asOfDate: string | null;\n  /** Epoch seconds when this rollup was computed. */\n  computedAt: number;\n  lookbackDays: number;\n  coverage: EtfAggregateCoverage;\n  weightedNetFlow: WeightedNetFlow;\n  /** Top contributors (up to 10) by absolute weighted-net-dollar contribution. */\n  topContributors: EtfInsiderContributor[];\n}\n\nexport interface EtfSentimentReading {\n  sentiSenseScore: number | null;\n  /** BULLISH / NEUTRAL / BEARISH. */\n  scoreLabel: string;\n  /** Epoch seconds when the underlying metric was produced. */\n  asOfTimestamp: number | null;\n}\n\nexport interface EtfSentimentAggregate {\n  ticker: string;\n  /** ISO date \"YYYY-MM-DD\". Composition snapshot date. */\n  asOfDate: string | null;\n  /** Epoch seconds when this aggregate was assembled. */\n  computedAt: number;\n  coverage: EtfAggregateCoverage;\n  /** Holdings-weighted SentiSense across the fund's constituents. */\n  constituentsWeighted: EtfSentimentReading;\n  /** Direct reading from mentions of the fund's own ticker. Null for low-mention funds. */\n  direct: EtfSentimentReading | null;\n}\n\nexport interface GetEtfInsiderAggregateOptions {\n  /** Trailing window for the trade aggregation. Typical values: 30, 90. Default 30. */\n  lookbackDays?: number;\n}\n\n/**\n * ETF discovery, composition (holdings), and holdings-weighted aggregate views.\n *\n * Funds aren't rated by analysts directly, don't have insiders of their own, and\n * may not get many direct news mentions -- but the companies inside them do. The\n * aggregate endpoints synthesize fund-level views from each constituent's per-stock\n * data, weighted by allocation, with a coverage block so consumers see how much of\n * the fund's AUM the underlying data covered.\n *\n * Beta as of 2026-05-15: starting with a limited set of widely-traded funds.\n */\nexport class Etfs {\n  constructor(private client: APIClient) {}\n\n  /**\n   * List every ETF tracked by SentiSense, sorted by ticker.\n   */\n  async list(): Promise<EtfInfo[]> {\n    return this.client.get(\"/api/v1/etfs\");\n  }\n\n  /**\n   * Get the full holdings composition for an ETF, including per-holding weights\n   * and freshness metadata. Returns 404 for unknown ETFs or commodity-only funds.\n   */\n  async holdings(ticker: string): Promise<EtfHoldings> {\n    return this.client.get(\n      `/api/v1/etfs/${encodeURIComponent(ticker.toUpperCase())}/holdings`,\n    );\n  }\n\n  /**\n   * Get the holdings-weighted analyst consensus for an ETF, including the\n   * top per-holding contributors that drive the weighted upside.\n   */\n  async analystAggregate(\n    ticker: string,\n  ): Promise<PreviewResponse<EtfAnalystAggregate>> {\n    return this.client.get(\n      `/api/v1/etfs/${encodeURIComponent(ticker.toUpperCase())}/aggregates/analyst`,\n    );\n  }\n\n  /**\n   * Get the holdings-weighted SEC Form 4 insider aggregate for an ETF over a\n   * configurable trailing window, including per-holding `topContributors` with\n   * signed contribution to the weighted headline.\n   */\n  async insiderAggregate(\n    ticker: string,\n    options?: GetEtfInsiderAggregateOptions,\n  ): Promise<PreviewResponse<EtfInsiderAggregate>> {\n    return this.client.get(\n      `/api/v1/etfs/${encodeURIComponent(ticker.toUpperCase())}/aggregates/insider`,\n      options,\n    );\n  }\n\n  /**\n   * Get two SentiSense Score readings side-by-side: `constituentsWeighted`\n   * (precomputed daily weighted average across the fund's holdings) and `direct`\n   * (score from mentions of the fund's own ticker). The two can diverge, and the\n   * gap is itself information.\n   */\n  async sentimentAggregate(\n    ticker: string,\n  ): Promise<PreviewResponse<EtfSentimentAggregate>> {\n    return this.client.get(\n      `/api/v1/etfs/${encodeURIComponent(ticker.toUpperCase())}/aggregates/sentiment`,\n    );\n  }\n}\n","import type { APIClient } from \"../client.js\";\nimport type {\n  InsiderActivityResponse,\n  InsiderTrade,\n  ClusterBuy,\n  GetInsiderOptions,\n  PreviewResponse,\n} from \"../types.js\";\n\nexport class Insider {\n  constructor(private client: APIClient) {}\n\n  /**\n   * Get market-wide insider activity: top buys and sells aggregated by ticker.\n   *\n   * PRO-gated. Free-tier users receive a preview (top 5 per direction)\n   * with `isPreview: true` in the response.\n   */\n  async getActivity(options?: GetInsiderOptions): Promise<PreviewResponse<InsiderActivityResponse>> {\n    return this.client.get(\"/api/v1/insider/activity\", options);\n  }\n\n  /**\n   * Get individual insider transactions for a specific stock.\n   *\n   * PRO-gated. Free users receive a preview of the top 5 transactions.\n   */\n  async getTrades(ticker: string, options?: GetInsiderOptions): Promise<PreviewResponse<InsiderTrade[]>> {\n    return this.client.get(\n      `/api/v1/insider/trades/${encodeURIComponent(ticker.toUpperCase())}`,\n      options,\n    );\n  }\n\n  /**\n   * Get cluster buy signals: stocks where 3+ distinct insiders bought recently.\n   *\n   * PRO-gated. Free users receive a preview of the top 3 signals.\n   */\n  async getClusterBuys(options?: GetInsiderOptions): Promise<PreviewResponse<ClusterBuy[]>> {\n    return this.client.get(\"/api/v1/insider/cluster-buys\", options);\n  }\n}\n","import type { APIClient } from \"../client.js\";\nimport type {\n  CongressTrade,\n  PoliticianSummary,\n  PoliticianDetail,\n  GetPoliticianActivityOptions,\n  GetPoliticiansOptions,\n  GetPoliticianDirectoryOptions,\n  GetPoliticianMemberOptions,\n  PoliticianDirectory,\n  PoliticianDirectoryResponse,\n  PreviewResponse,\n} from \"../types.js\";\n\nexport class Politicians {\n  constructor(private client: APIClient) {}\n\n  /**\n   * Get recent congressional STOCK Act trading activity across all politicians.\n   *\n   * PRO-gated. Free-tier users receive a preview (top 5 trades)\n   * with `isPreview: true` in the response.\n   *\n   * The feed is longer than one response: a default 90-day window is routinely well over a\n   * thousand disclosures, and without `limit` the server sends the first 200 with no marker\n   * that it stopped. `totalCount` on the envelope is the real size on every tier, so page\n   * with `limit` and `offset` rather than reading `data.length` as the total.\n   *\n   * ```typescript\n   * const first = await client.politicians.getActivity({ limit: 100 });\n   * for (let offset = 100; offset < first.totalCount!; offset += 100) {\n   *   const page = await client.politicians.getActivity({ limit: 100, offset });\n   *   // ... page.data\n   * }\n   * ```\n   */\n  async getActivity(\n    options?: GetPoliticianActivityOptions,\n  ): Promise<PreviewResponse<CongressTrade[]>> {\n    return this.client.get(\"/api/v1/politicians/activity\", options);\n  }\n\n  /**\n   * Get congressional trades for a specific stock.\n   *\n   * PRO-gated. Free users receive a preview of the top 3 trades.\n   */\n  async getFilings(\n    ticker: string,\n    options?: GetPoliticiansOptions,\n  ): Promise<PreviewResponse<CongressTrade[]>> {\n    return this.client.get(\n      `/api/v1/politicians/filings/${encodeURIComponent(ticker.toUpperCase())}`,\n      options,\n    );\n  }\n\n  /**\n   * Discover tracked members of Congress and the page slug identifying each, so you\n   * can find who to query without knowing slugs upfront.\n   *\n   * Summary only, no trade data; use `getMember` for a member's filings.\n   *\n   * Unlike `getMembers`, this includes members who have **left Congress**, carrying\n   * `former` and `servedUntil`. That roster lists who currently holds office, so a\n   * former member is otherwise reachable only if you already know their slug.\n   *\n   * Requires an API key but does not consume monthly quota (per-minute rate limits\n   * still apply), and is not tier-gated. Returns the unwrapped list payload.\n   */\n  async getDirectory(\n    options?: GetPoliticianDirectoryOptions,\n  ): Promise<PoliticianDirectory> {\n    const resp = await this.client.get<PoliticianDirectoryResponse>(\n      \"/api/v1/politicians/directory\",\n      { ...options },\n    );\n    return resp.data;\n  }\n\n  /**\n   * Get all tracked politicians with trading summary statistics.\n   *\n   * PRO-gated. Free users receive a preview of the top 5 members.\n   *\n   * Serves only members currently in office. Use `getDirectory` to enumerate\n   * everyone tracked, former members included.\n   */\n  async getMembers(): Promise<PreviewResponse<PoliticianSummary[]>> {\n    return this.client.get(\"/api/v1/politicians/members\");\n  }\n\n  /**\n   * Get detailed profile for a single politician: summary, recent trades, top tickers.\n   *\n   * PRO-gated. Free users receive a preview-wrapped response.\n   *\n   * `data.recentTrades` is one page of the member's history, not all of it. Most members\n   * have a few dozen disclosures and arrive complete in the default page; a handful have\n   * thousands. `totalCount` on the envelope is the size of the whole history on every\n   * tier, so page with `limit` and `offset` rather than reading `recentTrades.length` as\n   * the total. `data.profile` and `data.topTickers` describe the whole history whatever\n   * page you ask for, so `profile.totalTrades` does not shrink with a small `limit`.\n   *\n   * ```typescript\n   * const first = await client.politicians.getMember(\"Ro-Khanna\", { limit: 500 });\n   * for (let offset = 500; offset < first.totalCount!; offset += 500) {\n   *   const page = await client.politicians.getMember(\"Ro-Khanna\", { limit: 500, offset });\n   *   // ... page.data.recentTrades\n   * }\n   * ```\n   */\n  async getMember(\n    slug: string,\n    options?: GetPoliticianMemberOptions,\n  ): Promise<PreviewResponse<PoliticianDetail>> {\n    return this.client.get(\n      `/api/v1/politicians/member/${encodeURIComponent(slug)}`,\n      options,\n    );\n  }\n}\n","import type { APIClient } from \"../client.js\";\nimport type {\n  Insight,\n  GetInsightsOptions,\n  PreviewResponse,\n} from \"../types.js\";\n\nexport interface GetStockInsightsRangeOptions {\n  startDate: string;\n  endDate: string;\n  urgency?: \"low\" | \"medium\" | \"high\";\n  insightType?: string;\n}\n\nexport interface GetLatestInsightsOptions {\n  limit?: number;\n  urgency?: \"low\" | \"medium\" | \"high\";\n}\n\nexport interface GetUserInsightsOptions {\n  limit?: number;\n  category?: string;\n}\n\nexport class Insights {\n  constructor(private client: APIClient) {}\n\n  /**\n   * Get AI-generated insights for a specific stock, sorted by urgency then confidence.\n   *\n   * Returns the preview envelope: read the insights as `.data`. PRO callers get the\n   * full list with `isPreview: false`; free callers get the top 3 with `isPreview: true`\n   * and `totalCount` carrying the untruncated size.\n   */\n  async stock(\n    ticker: string,\n    options?: GetInsightsOptions,\n  ): Promise<PreviewResponse<Insight[]>> {\n    return this.client.get(\n      `/api/v1/insights/stock/${encodeURIComponent(ticker.toUpperCase())}`,\n      options,\n    );\n  }\n\n  /**\n   * Get AI insights for a stock within a date range.\n   *\n   * Returns the preview envelope: read the insights as `.data`. Free callers receive\n   * the top 3, PRO callers the full list. The server returns 400 if `startDate` is\n   * after `endDate`.\n   */\n  async stockRange(\n    ticker: string,\n    options: GetStockInsightsRangeOptions,\n  ): Promise<PreviewResponse<Insight[]>> {\n    return this.client.get(\n      `/api/v1/insights/stock/${encodeURIComponent(ticker.toUpperCase())}/range`,\n      options,\n    );\n  }\n\n  /**\n   * Get AI-generated market-level insights, sorted by urgency then confidence.\n   *\n   * Returns the preview envelope: read the insights as `.data`. PRO callers get the\n   * full list with `isPreview: false`; free callers get the top 5 with `isPreview: true`\n   * and `totalCount` carrying the untruncated size.\n   */\n  async market(): Promise<PreviewResponse<Insight[]>> {\n    return this.client.get(\"/api/v1/insights/market\");\n  }\n\n  /**\n   * Get the latest AI insights across all tracked stocks, newest first.\n   *\n   * Returns the preview envelope: read the insights as `.data`. Free callers receive\n   * the top 5, PRO callers up to `limit` (clamped to 1-200).\n   */\n  async latest(\n    options?: GetLatestInsightsOptions,\n  ): Promise<PreviewResponse<Insight[]>> {\n    return this.client.get(\"/api/v1/insights/latest\", options);\n  }\n\n  /**\n   * Get personalized insights for the authenticated user.\n   *\n   * Biased toward the user's watchlist and portfolio when available; falls back\n   * to market-level insights otherwise. API key authentication required.\n   * Returns the preview envelope: read the insights as `.data`.\n   */\n  async user(\n    options?: GetUserInsightsOptions,\n  ): Promise<PreviewResponse<Insight[]>> {\n    return this.client.get(\"/api/v1/insights/user\", options);\n  }\n\n  /**\n   * Get available insight types for a specific stock.\n   * API key required.\n   *\n   * Returns an array of insight type strings (e.g., `[\"sentiment_shift\", \"options_activity\"]`).\n   */\n  async types(ticker: string): Promise<string[]> {\n    return this.client.get(\n      `/api/v1/insights/stock/${encodeURIComponent(ticker.toUpperCase())}/types`,\n    );\n  }\n}\n","import type { APIClient } from \"../client.js\";\nimport type {\n  GetFlowsOptions,\n  GetHoldersOptions,\n  Holder,\n  InstitutionList,\n  InstitutionListResponse,\n  InstitutionalFlows,\n  ListInstitutionsOptions,\n  PreviewResponse,\n  Quarter,\n  TickerHolders,\n} from \"../types.js\";\n\nexport class Institutional {\n  constructor(private client: APIClient) {}\n\n  /** Get available 13F reporting quarters. */\n  async getQuarters(): Promise<Quarter[]> {\n    return this.client.get(\"/api/v1/institutional/quarters\");\n  }\n\n  /**\n   * Get aggregate institutional activity per ticker for a quarter.\n   *\n   * `reportDate` is optional: omit it to get the latest available quarter, which may be\n   * a still-open one holding only early filers. The response then carries `reportDate`\n   * plus `isPending` and filer coverage counts so a partial quarter is clearly labeled.\n   *\n   * Returns the preview envelope, so the flows are one level down:\n   * `const { data } = await client.institutional.getFlows(); data.inflows`.\n   */\n  async getFlows(\n    reportDate?: string,\n    options?: GetFlowsOptions,\n  ): Promise<PreviewResponse<InstitutionalFlows>> {\n    return this.client.get(\"/api/v1/institutional/flows\", {\n      reportDate,\n      ...options,\n    });\n  }\n\n  /**\n   * Get institutional holders for a specific stock.\n   *\n   * Returns the preview envelope wrapping a {@link TickerHolders} object, so the rows\n   * are two levels down: `(await getHolders(t, d)).data.holders`, alongside ticker-level\n   * totals like `holderCount`. Free callers get a truncated `holders` array with\n   * `isPreview: true`.\n   *\n   * A widely held ticker returns thousands of rows: a megacap quarter is about\n   * 6,000 holders and 1.5 MB. Pass `limit` unless you really want all of them.\n   * Omitting `options` sends the original unbounded request.\n   *\n   * `limit` is the switch for the whole option set. With it, the response also carries\n   * `returnedCount`, `offset`, and a `notableChanges` summary, so you can walk the list\n   * without re-counting it. Without it, `offset` / `sortBy` / `sortDir` are ignored by the\n   * server and you get the full unsorted list back with a 200.\n   */\n  async getHolders(\n    ticker: string,\n    reportDate: string,\n    options?: GetHoldersOptions,\n  ): Promise<PreviewResponse<TickerHolders>> {\n    return this.client.get(\n      `/api/v1/institutional/holders/${encodeURIComponent(ticker)}`,\n      { reportDate, ...options },\n    );\n  }\n\n  /**\n   * Get activist investor positions (NEW or INCREASED).\n   *\n   * Returns the preview envelope, so read the rows as `.data`.\n   */\n  async getActivists(reportDate: string): Promise<PreviewResponse<Holder[]>> {\n    return this.client.get(\"/api/v1/institutional/activist\", { reportDate });\n  }\n\n  /**\n   * Discover institutions: a paginated, AUM-ranked list of filers (slug + metadata)\n   * so you can find what to query without knowing slugs upfront.\n   *\n   * Each institution is rolled up by parent filer, so a multi-filer manager\n   * (e.g. Vanguard) appears once with combined AUM. Summary only; use\n   * `getInstitutionDetail` for a filer's full holdings.\n   *\n   * Requires an API key but does not consume monthly quota (per-minute rate\n   * limits still apply). Returns the unwrapped list payload.\n   */\n  async listInstitutions(options?: ListInstitutionsOptions): Promise<InstitutionList> {\n    const resp = await this.client.get<InstitutionListResponse>(\n      \"/api/v1/institutional/institutions\",\n      { ...options },\n    );\n    return resp.data;\n  }\n\n  /**\n   * Get the full profile, summary stats, and current-quarter holdings for a\n   * specific institutional filer.\n   *\n   * Resolved by URL slug (e.g. `Berkshire-Hathaway`) or numeric SEC CIK.\n   * Free users receive the profile and top 10 holdings; PRO users receive the\n   * full holdings array. Returns 404 if the slug or CIK is unknown.\n   */\n  async getInstitutionDetail(slugOrCik: string): Promise<unknown> {\n    return this.client.get(\n      `/api/v1/institutional/institution/${encodeURIComponent(slugOrCik)}`,\n    );\n  }\n}\n","import type { APIClient } from \"../client.js\";\nimport type { KBEntity } from \"../types.js\";\n\nexport class KB {\n  constructor(private client: APIClient) {}\n\n  /** Get popular entities for search suggestions. */\n  async getPopularEntities(): Promise<KBEntity[]> {\n    return this.client.get(\"/api/v1/kb/entities/popular\");\n  }\n}\n","import type { APIClient } from \"../client.js\";\nimport type { MarketMood } from \"../types.js\";\n\nexport class MarketMoodResource {\n  constructor(private client: APIClient) {}\n\n  /** Get market mood data (scores, history, sectors). */\n  async get(): Promise<MarketMood> {\n    return this.client.get(\"/api/v2/market-mood\");\n  }\n\n  // TODO: accept a `days` param to control history length (the endpoint supports ?days=N).\n  //\n  // Market Mood is also reachable through `client.indexes`, which serves it in the shared\n  // index envelope alongside fed-sentiment and ai-sentiment. Use this resource when you want\n  // the phase band, weekly change, per-signal breakdown and per-sector map; use `indexes`\n  // when you want every index to answer the same shape. Both report the same headline number.\n}\n","import type { APIClient } from \"../client.js\";\nimport type { MarketSummary } from \"../types.js\";\n\nexport class MarketSummaryResource {\n  constructor(private client: APIClient) {}\n\n  /** Get the AI-generated market summary with headline and analysis. */\n  async get(): Promise<MarketSummary> {\n    return this.client.get(\"/api/v1/market-summary\");\n  }\n}\n","import type { APIClient } from \"../client.js\";\nimport type { OptionsOverview, PreviewResponse } from \"../types.js\";\n\n/**\n * Market-wide options intelligence.\n *\n * Per-ticker options live on `client.stocks` (`getOptionsSummary`, `getOptionsHistory`),\n * next to everything else keyed by a symbol. This resource holds the surfaces that have no\n * ticker at all, the same split the market-wide mood and screener resources use.\n */\nexport class Options {\n  constructor(private client: APIClient) {}\n\n  /**\n   * Get the market-wide options radar: where implied volatility, put/call flow and skew are\n   * unusual today, ranked.\n   *\n   * End of day, not live. `asOf` is the latest completed session and the build refreshes the\n   * following morning, so this is positioning, not a quote feed.\n   *\n   * **The response carries two separately-ranked boards.** `data.rows` is the covered stock\n   * universe and `data.etfRows` is the covered ETF universe. Do not merge them: each row's\n   * readings are percentiles of that ticker's own trailing history, so a rank built across\n   * both boards compares numbers measured against different baselines. The aggregates are\n   * split the same way, with the `etf`-prefixed fields describing the ETF board alone.\n   *\n   * `data` is `null` before the first nightly build populates it, which is a cold-start\n   * state rather than an error.\n   *\n   * Tiering: a PRO key receives every row. A FREE key receives the top 25 stock rows plus\n   * all the aggregates, with `isPreview` true and the envelope's `totalCount` reporting the\n   * full stock board; `data.etfTotalCount` does the same for the ETF board.\n   *\n   * Drill into any row with `client.stocks.getOptionsSummary(ticker)` for its full dossier,\n   * or `client.stocks.getOptionsHistory(ticker)` to chart how a reading has trended.\n   */\n  async getOverview(): Promise<PreviewResponse<OptionsOverview | null>> {\n    return this.client.get(\"/api/v1/options/overview\");\n  }\n}\n","import type { APIClient } from \"../client.js\";\nimport type {\n  EtfScreenerExecuteResponse,\n  EtfScreenerRow,\n  FeaturedScreen,\n  ScreenerExecuteOptions,\n  ScreenerExecuteResponse,\n  ScreenerFieldCatalog,\n  ScreenerFieldDescriptor,\n  ScreenerFieldOption,\n  ScreenerFilter,\n  ScreenerPlan,\n  ScreenerRow,\n  ScreenerScreensResponse,\n  ScreenerSort,\n} from \"../types.js\";\n\n/**\n * Screener: filter the tracked universe on the SentiSense Score, attention,\n * analyst consensus, technicals and price in a single query. It is the one\n * surface where our own signals sit in the same `WHERE` clause as the market\n * data, which is the point: screening on analyst ratings alone is something a\n * dozen free tools do, screening on analyst ratings *where the Score disagrees*\n * is not.\n *\n * Every screen is a {@link ScreenerPlan}. Take one from {@link screens} or\n * build your own, then hand it to {@link run} or {@link runEtfs}.\n *\n * Three field semantics are worth knowing before you write a filter, because\n * guessing them wrong produces a screen that looks fine and means nothing:\n *\n * - **`ANALYST_RATING_MEAN` is inverted.** It is the vendor's 1-to-5 scale\n *   where `1.0` is strong buy, so bullish is `LTE 2.5`, not `GTE`. Prefer\n *   `ANALYST_BUY_RATIO_PCT`, which runs the intuitive direction.\n * - **`MA_CROSS_STATE` is ordinal**, not a percentage: `1` golden cross (50-day\n *   above 200-day), `-1` death cross, `0` neither. Use `EQ`.\n * - **`SENTIMENT_DIRECTION` is the sign of the 7-day SentiSense Score**\n *   (`1` / `0` / `-1`) with a neutral band of plus-or-minus 5. Despite the name\n *   it is not sentiment polarity, and `0` matches only an exact zero, so it\n *   returns almost nothing.\n *\n * The Score fields (`SENTI_SCORE_7D`, `SENTI_SCORE_1M`, `SCORE_CHANGE_7D`) are\n * the SentiSense Score, not polarity: unbounded, banded at 5 / 13 / 23 either\n * side of zero. Filter on those band edges, not on values like `0.5`, which\n * behave as \"any positive score\".\n *\n * Nulls never match, in either direction: `RETURN_1Y >= 0` and `RETURN_1Y < 0`\n * do not partition the universe, because a stock listed four months ago is in\n * neither result. If a screen returns fewer rows than you expect, check\n * coverage before you check your thresholds.\n *\n * Screens read a snapshot that refreshes every 20 minutes, so this is not a\n * quote feed. Use `client.stocks.getQuote()` for live prices.\n */\nexport class Screener {\n  constructor(private client: APIClient) {}\n\n  /**\n   * Every filterable field, with its unit, operators and description, for both\n   * universes.\n   *\n   * Build a filter UI from this rather than hardcoding the list and you inherit\n   * new fields as they ship. The ETF `STRING` fields (`ISSUER`, `ASSET_CLASS`,\n   * `TRACKED_INDEX`) come back with their `values` populated from the live\n   * universe, so pickers stay current without a redeploy.\n   */\n  async fields(): Promise<ScreenerFieldCatalog> {\n    return this.client.get(\"/api/v1/screener/fields\");\n  }\n\n  /**\n   * The curated screens shipped in the product, each with a runnable plan.\n   *\n   * Each `plan` round-trips straight into {@link run} (or {@link runEtfs} when\n   * `plan.universe === \"ETF\"`) with nothing to rebuild.\n   *\n   * Their filters identify the field with `field` rather than `fieldName`.\n   * Both keys are accepted on the way in, so read either when inspecting a plan\n   * you did not build yourself.\n   */\n  async screens(): Promise<ScreenerScreensResponse> {\n    return this.client.get(\"/api/v1/screener/screens\");\n  }\n\n  /**\n   * Run a screen against the stock universe.\n   *\n   * `tickers` is optional: omit it to screen the whole tracked universe, pass a\n   * list to screen a watchlist. `limit` sits next to the plan rather than\n   * inside it, because a plan is a stored object and paging is a transport\n   * concern; it defaults to 100 and caps at 500.\n   *\n   * Read `matched` before you read `results`: it is the count before `limit`\n   * was applied, so a `matched` above your `limit` means you are holding the\n   * top slice under the plan's sort, not the whole answer.\n   *\n   * @example\n   * ```ts\n   * const res = await client.screener.run({\n   *   plan: {\n   *     filters: [\n   *       { fieldName: \"SENTI_SCORE_7D\", op: \"GTE\", value: 13 },\n   *       { fieldName: \"ANALYST_BUY_RATIO_PCT\", op: \"LTE\", value: 30 },\n   *       { fieldName: \"ANALYST_COUNT\", op: \"GTE\", value: 5 },\n   *     ],\n   *     sort: { fieldName: \"SENTI_SCORE_7D\", dir: \"DESC\" },\n   *   },\n   *   limit: 25,\n   * });\n   * ```\n   */\n  async run(options: ScreenerExecuteOptions): Promise<ScreenerExecuteResponse> {\n    return this.client.post(\"/api/v1/screener/execute\", options);\n  }\n\n  /**\n   * Run a screen against the ETF universe.\n   *\n   * Same request shape as {@link run}, against a different field vocabulary:\n   * take the ETF names from `fields().etf`. `IN` / `NOT_IN` take a `values`\n   * array instead of `value` and are the operators for the string fields\n   * (`ISSUER`, `ASSET_CLASS`, `TRACKED_INDEX`).\n   *\n   * `CONSTITUENTS_WEIGHTED_SENTISENSE` is the holdings-weighted SentiSense\n   * Score across what the fund owns and is usually the one you want;\n   * `DIRECT_SENTISENSE` is the Score from chatter about the fund ticker itself,\n   * which on a broad index fund is mostly macro noise. `WEIGHT_COVERED_PCT`\n   * tells you how much of the fund's weight had constituent data behind the\n   * weighted number.\n   */\n  async runEtfs(options: ScreenerExecuteOptions): Promise<EtfScreenerExecuteResponse> {\n    return this.client.post(\"/api/v1/screener/etfs/execute\", options);\n  }\n}\n\n// Re-export for convenience so callers can `import type { ScreenerPlan }`\n// from the resource module instead of `../types`.\nexport type {\n  EtfScreenerExecuteResponse,\n  EtfScreenerRow,\n  FeaturedScreen,\n  ScreenerExecuteOptions,\n  ScreenerExecuteResponse,\n  ScreenerFieldCatalog,\n  ScreenerFieldDescriptor,\n  ScreenerFieldOption,\n  ScreenerFilter,\n  ScreenerPlan,\n  ScreenerRow,\n  ScreenerScreensResponse,\n  ScreenerSort,\n};\n","import type { APIClient } from \"../client.js\";\nimport type {\n  AISummary,\n  ChartData,\n  ChartDataPoint,\n  CompanyKpisData,\n  FloatInfo,\n  Fundamentals,\n  FundamentalsPeriodsResponse,\n  TtmFundamentals,\n  GetAISummaryOptions,\n  GetChartOptions,\n  GetDescriptionsOptions,\n  GetFundamentalsOptions,\n  GetImagesOptions,\n  GetMetricsBreakdownOptions,\n  GetProfileOptions,\n  GetOptionsHistoryOptions,\n  GetSimilarOptions,\n  KpiCoverageResponse,\n  KpiTypeEntry,\n  MarketStatus,\n  MetricsBreakdown,\n  OptionsHistory,\n  OptionsSummary,\n  PreviewResponse,\n  SimilarStock,\n  ShortInterest,\n  ShortVolume,\n  StockDetail,\n  StockEntity,\n  StockSentiment,\n  StockImage,\n  StockPrice,\n  StockProfile,\n  StockQuote,\n} from \"../types.js\";\n\n/**\n * Fill the legacy `name` alias from the fields the API actually sends.\n *\n * `/stocks/detailed` and `/stocks/popular/detailed` return `simpleName` and\n * `companyName`; they have never sent `name`. Callers reading `.name` got\n * `undefined`, so it is backfilled here rather than left to crash.\n */\nfunction withLegacyName(rows: StockDetail[]): StockDetail[] {\n  if (!Array.isArray(rows)) return rows;\n  return rows.map((row) =>\n    row && !row.name ? { ...row, name: row.simpleName || row.companyName || \"\" } : row,\n  );\n}\n\nexport class Stocks {\n  constructor(private client: APIClient) {}\n\n  /** List all available ticker symbols. */\n  async list(): Promise<string[]> {\n    return this.client.get(\"/api/v1/stocks\");\n  }\n\n  /** List all stocks with company names, kbEntityId, urlSlug. */\n  async listDetailed(): Promise<StockDetail[]> {\n    const rows = await this.client.get<StockDetail[]>(\"/api/v1/stocks/detailed\");\n    return withLegacyName(rows);\n  }\n\n  /** Get popular ticker symbols. */\n  async listPopular(): Promise<string[]> {\n    return this.client.get(\"/api/v1/stocks/popular\");\n  }\n\n  /** Get popular stocks with details. */\n  async listPopularDetailed(): Promise<StockDetail[]> {\n    const rows = await this.client.get<StockDetail[]>(\"/api/v1/stocks/popular/detailed\");\n    return withLegacyName(rows);\n  }\n\n  /** Get real-time price for a single ticker. */\n  async getPrice(ticker: string): Promise<StockPrice> {\n    return this.client.get(\"/api/v1/stocks/price\", { ticker });\n  }\n\n  /**\n   * Get aggregate quote snapshot: live price, today OHLC, 52-week range,\n   * market cap, P/E, EPS TTM, and dividend yield in a single call.\n   * All fields except `ticker` may be null when upstream data is unavailable.\n   */\n  async getQuote(ticker: string): Promise<StockQuote> {\n    return this.client.get(`/api/v1/stocks/${encodeURIComponent(ticker)}/quote`);\n  }\n\n  /** Get real-time prices for multiple tickers. */\n  async getPrices(tickers: string[]): Promise<StockPrice[]> {\n    return this.client.get(\"/api/v1/stocks/prices\", {\n      tickers: tickers.join(\",\"),\n    });\n  }\n\n  /** Get batch company logo URLs. */\n  async getImages(\n    tickers: string[],\n    options?: GetImagesOptions,\n  ): Promise<Record<string, StockImage>> {\n    return this.client.get(\"/api/v1/stocks/images\", {\n      tickers: tickers.join(\",\"),\n      ...options,\n    });\n  }\n\n  /** Get company profiles with branding, market cap, sector. */\n  async getDescriptions(\n    tickers: string[],\n    options?: GetDescriptionsOptions,\n  ): Promise<Record<string, StockProfile>> {\n    return this.client.get(\"/api/v1/stocks/descriptions\", {\n      tickers: tickers.join(\",\"),\n      ...options,\n    });\n  }\n\n  /** Get peer/similar stocks. */\n  async getSimilar(ticker: string, options?: GetSimilarOptions): Promise<SimilarStock[]> {\n    return this.client.get(`/api/v1/stocks/${encodeURIComponent(ticker)}/similar`, options);\n  }\n\n  /** Get company profile (CEO, sector, industry, market data). */\n  async getProfile(ticker: string, options?: GetProfileOptions): Promise<StockProfile> {\n    return this.client.get(`/api/v1/stocks/${encodeURIComponent(ticker)}/profile`, options);\n  }\n\n  /**\n   * Get the headline sentiment picture for a stock in one call.\n   *\n   * Returns the SentiSense Score with its 30-day regime, mention volume and social\n   * dominance, per-source tone in `bySource`, plus related tickers, story drivers, a\n   * narrative and an FAQ. Available in full on every API-key tier.\n   *\n   * Use `entityMetrics.getMetrics(ticker, \"sentiment\", ...)` instead when you need a time\n   * series over a specific window rather than the headline read. Returns 404 for tickers\n   * with no sentiment coverage.\n   */\n  async getSentiment(ticker: string): Promise<PreviewResponse<StockSentiment>> {\n    return this.client.get(\n      `/api/v1/stocks/${encodeURIComponent(ticker)}/sentiment`,\n    );\n  }\n\n  /** Get related KB entities (people, products, partners). */\n  async getEntities(ticker: string): Promise<StockEntity[]> {\n    return this.client.get(`/api/v1/stocks/${encodeURIComponent(ticker)}/entities`);\n  }\n\n  /**\n   * Get AI-generated stock analysis report. Requires PRO tier.\n   *\n   * `depth: \"deep\"` returns the full curated report and consumes one report view on\n   * metered tiers; the default `\"basic\"` returns the one-paragraph summary.\n   *\n   * The deprecated `forceRefresh` option is accepted and discarded, not forwarded.\n   */\n  async getAISummary(ticker: string, options?: GetAISummaryOptions): Promise<AISummary> {\n    const { forceRefresh: _forceRefresh, ...params } = options ?? {};\n    return this.client.get(`/api/v1/stocks/${encodeURIComponent(ticker)}/ai-summary`, params);\n  }\n\n  /** Get sentiment/mention metrics breakdown by entity. */\n  async getMetricsBreakdown(\n    ticker: string,\n    metricType: string,\n    options?: GetMetricsBreakdownOptions,\n  ): Promise<MetricsBreakdown> {\n    return this.client.get(\n      `/api/v1/stocks/${encodeURIComponent(ticker)}/metrics/${encodeURIComponent(metricType)}/breakdown`,\n      options,\n    );\n  }\n\n  /**\n   * Get historical OHLCV chart data.\n   *\n   * The API returns a bare array of points; this normalizes it to\n   * `{ ticker, timeframe, data }`. `timeframe` echoes the requested value\n   * (defaulting to \"1M\", matching the server default when omitted).\n   */\n  async getChart(ticker: string, options?: GetChartOptions): Promise<ChartData> {\n    const data = await this.client.get<ChartDataPoint[]>(\"/api/v1/stocks/chart\", {\n      ticker,\n      ...options,\n    });\n    return { ticker, timeframe: options?.timeframe ?? \"1M\", data };\n  }\n\n  /** Get current market open/closed/pre-market/after-hours status. */\n  async getMarketStatus(): Promise<MarketStatus> {\n    return this.client.get(\"/api/v1/stocks/market-status\");\n  }\n\n  /**\n   * Get financial statement data for one reporting period: income statement, balance sheet,\n   * and cash flow, including `capitalExpenditure` and `freeCashFlow`.\n   *\n   * Capital expenditure is signed as filed, so normally negative. See {@link Fundamentals}\n   * for the free-cash-flow relationship and when it is `null`.\n   */\n  async getFundamentals(ticker: string, options?: GetFundamentalsOptions): Promise<Fundamentals> {\n    return this.client.get(\"/api/v1/stocks/fundamentals\", { ticker, ...options });\n  }\n\n  /** Get available fiscal periods. The periods are in `periods`. */\n  async getFundamentalsPeriods(ticker: string): Promise<FundamentalsPeriodsResponse> {\n    return this.client.get(\"/api/v1/stocks/fundamentals/periods\", { ticker });\n  }\n\n  /**\n   * Get the trailing-twelve-month fundamentals snapshot: TTM ratios, a different\n   * shape from the per-period statement data `getFundamentals()` returns.\n   */\n  async getCurrentFundamentals(ticker: string): Promise<TtmFundamentals> {\n    return this.client.get(\"/api/v1/stocks/fundamentals/current\", { ticker });\n  }\n\n  /** Get historical revenue data. */\n  async getHistoricalRevenue(ticker: string): Promise<unknown> {\n    return this.client.get(\"/api/v1/stocks/fundamentals/historical/revenue\", { ticker });\n  }\n\n  /** Get short interest metrics (FINRA). */\n  async getShortInterest(ticker: string): Promise<ShortInterest> {\n    return this.client.get(\"/api/v1/stocks/short-interest\", { ticker });\n  }\n\n  /** Get float information. */\n  async getFloat(ticker: string): Promise<FloatInfo> {\n    return this.client.get(\"/api/v1/stocks/float\", { ticker });\n  }\n\n  /** Get short volume trading data. */\n  async getShortVolume(ticker: string): Promise<ShortVolume> {\n    return this.client.get(\"/api/v1/stocks/short-volume\", { ticker });\n  }\n\n  /**\n   * Get company-specific KPI time-series for a ticker. Returns curated GAAP and\n   * non-GAAP metrics from earnings filings (e.g. iPhone unit sales, Tesla deliveries,\n   * AWS revenue).\n   *\n   * Free users receive metadata only with an empty `kpis` list; PRO users receive\n   * the full series. Returns 404 for tickers that do not yet have curated coverage.\n   *\n   * Coverage today: near-complete for the S&P 500 plus extended universe\n   * (~500 tickers). Use `listKpiCoverage()` to enumerate.\n   */\n  async getKpis(ticker: string): Promise<PreviewResponse<CompanyKpisData>> {\n    return this.client.get(\n      `/api/v1/stocks/${encodeURIComponent(ticker.toUpperCase())}/kpis`,\n    );\n  }\n\n  /**\n   * List every ticker with curated KPI coverage. Returns `{count, tickers: [...]}`\n   * with lightweight metadata (ticker, companyName, lastUpdated, kpiCount).\n   * Sorted alphabetically by ticker.\n   *\n   * Auth: API key required, but the call does NOT consume your monthly quota\n   * (rate-limit-per-minute still applies).\n   */\n  async listKpiCoverage(): Promise<KpiCoverageResponse> {\n    return this.client.get(\"/api/v1/stocks/with-kpis\");\n  }\n\n  /**\n   * List the KPI metadata tuples available for a ticker (`id, name, category,\n   * chartType`) without paying the cost of the full series payload. Mirrors\n   * the `/api/v1/insights/stock/{ticker}/types` precedent.\n   *\n   * Auth: API key required, no quota cost. 404 if the ticker has no curated KPIs.\n   */\n  async getKpiTypes(ticker: string): Promise<KpiTypeEntry[]> {\n    return this.client.get(\n      `/api/v1/stocks/${encodeURIComponent(ticker.toUpperCase())}/kpis/types`,\n    );\n  }\n\n  /**\n   * Get the end-of-day options dossier for one stock or ETF: the session's aggregate, its\n   * percentile context, the open-interest wall structure with max pain, and the contracts\n   * whose volume ran far ahead of their open interest.\n   *\n   * End of day, not live. `asOf` is the prior trading session and the data refreshes the\n   * following morning, so this is positioning, not a quote feed.\n   *\n   * **`data` is `null` for a ticker outside the covered universe**, which is the most\n   * actively optioned US names plus the tracked ETFs, and for a covered ticker with no\n   * snapshot yet. An unknown symbol behaves the same way rather than answering 404, so treat\n   * a null as \"no coverage\", never as an error. A covered ticker still building its baseline\n   * returns its raw readings with the percentiles omitted.\n   *\n   * Percentiles compare a ticker to its own trailing history, never to another ticker, so an\n   * ETF's readings are not comparable with a single stock's.\n   *\n   * Tiering: a PRO key always receives the full dossier. A FREE key receives it for the first\n   * ten calls each calendar month and a headline-only preview after that, with `isPreview`\n   * true; calls that return a null `data` never spend that allowance.\n   */\n  async getOptionsSummary(ticker: string): Promise<PreviewResponse<OptionsSummary | null>> {\n    return this.client.get(\n      `/api/v1/stocks/${encodeURIComponent(ticker.toUpperCase())}/options/summary`,\n    );\n  }\n\n  /**\n   * Get the daily options aggregates for one stock or ETF as a time series, oldest first.\n   * Use it to chart how a reading has trended: implied volatility, put/call flow, skew.\n   *\n   * Each element has the same shape as the dossier's `latest` aggregate, so a chart built\n   * off `getOptionsSummary` reads this series without a second mapping.\n   *\n   * **A null payload is not how this one reports no coverage.** Unlike\n   * {@link Stocks.getOptionsSummary}, an uncovered ticker, an unknown symbol and a covered\n   * ticker with nothing stored yet all answer with a populated object whose `series` is\n   * empty. Check the array's length, not the payload.\n   *\n   * The window served is not always the window requested: an unrecognised value clamps to\n   * `\"1y\"` rather than erroring, and a FREE key always receives `\"1y\"`. Read `data.window`\n   * for what you actually got. `\"5y\"` means all stored history, currently a little over two\n   * years, so it can answer with nearly the same series as `\"2y\"`.\n   */\n  async getOptionsHistory(\n    ticker: string,\n    options?: GetOptionsHistoryOptions,\n  ): Promise<PreviewResponse<OptionsHistory>> {\n    return this.client.get(\n      `/api/v1/stocks/${encodeURIComponent(ticker.toUpperCase())}/options/history`,\n      options,\n    );\n  }\n}\n","import type { APIClient } from \"../client.js\";\nimport type {\n  IndexConstituent,\n  IndexHistoryPoint,\n  IndexHistoryResponse,\n  IndexListing,\n  IndexListResponse,\n  IndexSnapshot,\n} from \"../types.js\";\n\n/**\n * Indexes: composite scalars tracked over time, each blending its own inputs\n * into one number on a stated scale. Every index answers on the same envelope,\n * so you write one renderer and get every current and future SentiSense index.\n *\n * Two archetypes share that envelope. A **basket** index weight-averages\n * tracked entities and fills `constituents` / `basketSize` / `coverage` /\n * `totalMentions`; a **composite** index is built from signals instead and\n * returns `null` for all four by construction. See {@link IndexSnapshot}.\n *\n * @see IndexSnapshot\n */\nexport class Indexes {\n  constructor(private client: APIClient) {}\n\n  /**\n   * List every index the platform publishes: id, display name, one-line\n   * description, the scale it lives on, its access tier, and where its richest\n   * view lives.\n   *\n   * Iterate this rather than hardcoding ids. Every `indexId` it advertises\n   * resolves on {@link get} and {@link history}.\n   */\n  async list(): Promise<IndexListResponse> {\n    return this.client.get(\"/api/v1/indexes\");\n  }\n\n  /**\n   * Latest reading for one index.\n   *\n   * Check `constituents` for `null` before iterating: it is `null` on a\n   * composite index like `market-mood`, which has no constituents by\n   * construction. For Market Mood this is the narrowed view; the phase band,\n   * weekly change, per-signal breakdown and per-sector map live on\n   * `client.marketMood.get()`, and both report the same headline number.\n   *\n   * @param indexId slug from {@link list}, e.g. `\"fed-sentiment\"`.\n   */\n  async get(indexId: string): Promise<IndexSnapshot> {\n    return this.client.get(`/api/v1/indexes/${indexId}`);\n  }\n\n  /**\n   * Historical scalar series for one index, for charting.\n   *\n   * Thin or low-coverage buckets are withheld, so the series can be shorter\n   * than `days` and can contain gaps. Plot against each point's `date`.\n   *\n   * @param indexId slug from {@link list}.\n   * @param days days of history to return. Defaults to the API's own 180.\n   */\n  async history(indexId: string, days?: number): Promise<IndexHistoryResponse> {\n    return this.client.get(\n      `/api/v1/indexes/${indexId}/history`,\n      days === undefined ? undefined : { days },\n    );\n  }\n}\n\n// Re-export for convenience so callers can `import type { IndexListing }`\n// from the resource module instead of `../types`.\nexport type {\n  IndexConstituent,\n  IndexHistoryPoint,\n  IndexHistoryResponse,\n  IndexListing,\n  IndexListResponse,\n  IndexSnapshot,\n};\n","import type { APIClient } from \"../client.js\";\nimport type {\n  TrackerListing,\n  TrackerListResponse,\n  TrackerSnapshot,\n  TrackerSnapshotResponse,\n} from \"../types.js\";\n\n/**\n * Trackers: observational data products published as a standardized\n * `TrackerSnapshot` envelope. Every tracker (institution rankings,\n * hedge-fund reported returns, social trackers, surveillance dashboards)\n * returns the same shape, so consumers write one renderer per `viewType` and\n * get every current and future SentiSense tracker for free.\n *\n * @see TrackerSnapshot\n */\nexport class Trackers {\n  constructor(private client: APIClient) {}\n\n  /**\n   * List every publicly-visible tracker: id, display name, category,\n   * one-line description, and the methodology anchor to link out to.\n   */\n  async list(): Promise<TrackerListResponse> {\n    return this.client.get(\"/api/v1/trackers\");\n  }\n\n  /**\n   * Standardized snapshot envelope for one tracker.\n   *\n   * Returns the envelope as-is: `{ isPreview, previewReason, totalCount?, data }`.\n   * When `data.viewType === \"table\"` the rows live at `data.rows[]`; when\n   * `\"choropleth\"` they live at `data.geo[]`; etc. Dispatch on `viewType`\n   * in your renderer.\n   *\n   * @param trackerId slug from {@link list}, e.g. `\"institution-concentration\"`.\n   * @param params provider-specific query params (e.g. `{ scope: \"us\" }` for\n   *   geographically-scoped trackers like hantavirus). Unknown keys are ignored.\n   */\n  async get(\n    trackerId: string,\n    params?: Record<string, string | number | boolean>,\n  ): Promise<TrackerSnapshotResponse> {\n    return this.client.get(`/api/v1/trackers/${trackerId}`, params);\n  }\n}\n\n// Re-export for convenience so callers can `import type { TrackerListing }`\n// from the resource module instead of `../types`.\nexport type {\n  TrackerListing,\n  TrackerListResponse,\n  TrackerSnapshot,\n  TrackerSnapshotResponse,\n};\n","export const VERSION = \"0.47.1\";\n","import {\n  APIError,\n  AuthenticationError,\n  DeepHistoryUnavailableError,\n  NotFoundError,\n  RateLimitError,\n  SentiSenseError,\n} from \"./errors.js\";\nimport { Analyst } from \"./resources/analyst.js\";\nimport { Calendar } from \"./resources/calendar.js\";\nimport { Documents } from \"./resources/documents.js\";\nimport { Earnings } from \"./resources/earnings.js\";\nimport { EntityMetrics } from \"./resources/entityMetrics.js\";\nimport { Etfs } from \"./resources/etfs.js\";\nimport { Insider } from \"./resources/insider.js\";\nimport { Politicians } from \"./resources/politicians.js\";\nimport { Insights } from \"./resources/insights.js\";\nimport { Institutional } from \"./resources/institutional.js\";\nimport { KB } from \"./resources/kb.js\";\nimport { MarketMoodResource } from \"./resources/marketMood.js\";\nimport { MarketSummaryResource } from \"./resources/marketSummary.js\";\nimport { Options } from \"./resources/options.js\";\nimport { Screener } from \"./resources/screener.js\";\nimport { Stocks } from \"./resources/stocks.js\";\nimport { Indexes } from \"./resources/indexes.js\";\nimport { Trackers } from \"./resources/trackers.js\";\nimport type { SentiSenseOptions } from \"./types.js\";\nimport { VERSION } from \"./version.js\";\n\nconst DEFAULT_BASE_URL = \"https://app.sentisense.ai\";\nconst DEFAULT_TIMEOUT = 30_000;\nconst DEFAULT_MAX_RETRIES = 3;\nconst BASE_DELAY_MS = 1_000;\nconst MAX_DELAY_MS = 60_000;\n// Used when a 202 arrives without a usable Retry-After header.\nconst DEEP_HISTORY_FALLBACK_WAIT_S = 3;\n\n// Upper bounds on any server-supplied Retry-After. Rate limiting gets the longer ceiling\n// because a genuine limit window is legitimately minutes, while a deep-history warm-up is\n// seconds. Without a ceiling an oversized header value strands the caller indefinitely.\nconst MAX_DEEP_HISTORY_WAIT_S = 30;\nconst MAX_RATE_LIMIT_WAIT_S = 120;\nconst RATE_LIMIT_FALLBACK_WAIT_S = 60;\n\n/**\n * A `Retry-After` header as a usable number of seconds, clamped to `[0.5, maxWaitS]`, or\n * `undefined` when there is no usable value.\n *\n * `Retry-After` is vendor-controlled and may legally carry an HTTP-date rather than a\n * number of seconds, in which case parsing yields `NaN`. Left unguarded that produced a\n * `NaN` delay which compared false against every threshold and retried instantly in a busy\n * loop, and a `NaN` on the error object that silently broke a caller's own backoff.\n * Anything that is not a finite number is treated as absent.\n */\nfunction clampRetryAfter(\n  raw: string | null,\n  maxWaitS: number,\n): number | undefined {\n  if (!raw) return undefined;\n  const parsed = Number(raw);\n  if (!Number.isFinite(parsed)) return undefined;\n  return Math.min(Math.max(0.5, parsed), maxWaitS);\n}\n\n/** Same clamp, resolved to `defaultS` when the header gives us nothing to go on. */\nfunction retryAfterSeconds(\n  raw: string | null,\n  defaultS: number,\n  maxWaitS: number,\n): number {\n  return clampRetryAfter(raw, maxWaitS) ?? defaultS;\n}\n\nfunction sleep(ms: number): Promise<void> {\n  return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/** @internal HTTP interface exposed to resource classes. */\nexport interface APIClient {\n  get<T = unknown>(path: string, params?: object): Promise<T>;\n  post<T = unknown>(path: string, body: unknown): Promise<T>;\n}\n\nexport class SentiSense implements APIClient {\n  private baseUrl: string;\n  private apiKey: string | undefined;\n  private timeout: number;\n  private maxRetries: number;\n  private userAgent: string;\n\n  readonly stocks: Stocks;\n  readonly documents: Documents;\n  readonly etfs: Etfs;\n  readonly institutional: Institutional;\n  readonly insider: Insider;\n  readonly politicians: Politicians;\n  readonly insights: Insights;\n  readonly analyst: Analyst;\n  readonly entityMetrics: EntityMetrics;\n  readonly marketMood: MarketMoodResource;\n  readonly marketSummary: MarketSummaryResource;\n  readonly kb: KB;\n  readonly indexes: Indexes;\n  readonly trackers: Trackers;\n  readonly calendar: Calendar;\n  readonly earnings: Earnings;\n  readonly screener: Screener;\n  readonly options: Options;\n\n  constructor(options: SentiSenseOptions = {}) {\n    this.apiKey = options.apiKey;\n    this.baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\\/+$/, \"\");\n    this.timeout = options.timeout ?? DEFAULT_TIMEOUT;\n    this.maxRetries = options.maxRetries ?? DEFAULT_MAX_RETRIES;\n    // A header value cannot carry CR/LF, so collapse them rather than letting a caller's\n    // string decide where the header block ends.\n    const suffix = options.userAgentSuffix?.replace(/[\\r\\n]+/g, \" \").trim();\n    this.userAgent = suffix\n      ? `sentisense-node/${VERSION} ${suffix}`\n      : `sentisense-node/${VERSION}`;\n\n    this.stocks = new Stocks(this);\n    this.documents = new Documents(this);\n    this.etfs = new Etfs(this);\n    this.institutional = new Institutional(this);\n    this.insider = new Insider(this);\n    this.politicians = new Politicians(this);\n    this.insights = new Insights(this);\n    this.analyst = new Analyst(this);\n    this.entityMetrics = new EntityMetrics(this);\n    this.marketMood = new MarketMoodResource(this);\n    this.marketSummary = new MarketSummaryResource(this);\n    this.kb = new KB(this);\n    this.indexes = new Indexes(this);\n    this.trackers = new Trackers(this);\n    this.calendar = new Calendar(this);\n    this.earnings = new Earnings(this);\n    this.screener = new Screener(this);\n    this.options = new Options(this);\n  }\n\n  /** @internal */\n  async get<T = unknown>(path: string, params?: object): Promise<T> {\n    const url = this.buildUrl(path, params);\n    const headers: Record<string, string> = {\n      \"Accept\": \"application/json\",\n    };\n\n    if (this.apiKey) {\n      headers[\"X-SentiSense-API-Key\"] = this.apiKey;\n    }\n\n    // User-Agent is only set in Node.js (browsers disallow it)\n    if (typeof process !== \"undefined\" && process.versions?.node) {\n      headers[\"User-Agent\"] = this.userAgent;\n    }\n\n    let delayMs = 0;\n\n    for (let attempt = 0; attempt <= this.maxRetries; attempt++) {\n      if (delayMs > 0) {\n        await sleep(delayMs);\n        delayMs = 0;\n      }\n\n      const controller = new AbortController();\n      const timer = setTimeout(() => controller.abort(), this.timeout);\n\n      try {\n        const response = await fetch(url, {\n          method: \"GET\",\n          headers,\n          signal: controller.signal,\n        });\n\n        // 202 means a deep chart range is still being built server-side. It is a 2xx, so\n        // without this it would fall through and return an empty array: the caller would\n        // see \"no data\" rather than \"not ready yet\", which is the exact confusion the\n        // status code exists to prevent. Retry honouring Retry-After, then surface it.\n        if (response.status === 202) {\n          const waitSeconds = retryAfterSeconds(\n            response.headers.get(\"Retry-After\"),\n            DEEP_HISTORY_FALLBACK_WAIT_S,\n            MAX_DEEP_HISTORY_WAIT_S,\n          );\n          try { await response.body?.cancel(); } catch { /* ignore */ }\n          if (attempt < this.maxRetries) {\n            delayMs = waitSeconds * 1000;\n            continue;\n          }\n          throw new DeepHistoryUnavailableError(\n            \"Deep history is still being assembled. Retry in a few seconds.\",\n            waitSeconds,\n          );\n        }\n\n        if (!response.ok) {\n          const isRetryable = response.status === 429 || response.status >= 500;\n          if (isRetryable && attempt < this.maxRetries) {\n            if (response.status === 429) {\n              delayMs = retryAfterSeconds(\n                response.headers.get(\"Retry-After\"),\n                RATE_LIMIT_FALLBACK_WAIT_S,\n                MAX_RATE_LIMIT_WAIT_S,\n              ) * 1000;\n            } else {\n              delayMs = Math.min(BASE_DELAY_MS * Math.pow(2, attempt), MAX_DELAY_MS) + Math.random() * 1000;\n            }\n            try { await response.body?.cancel(); } catch { /* ignore */ }\n            continue;\n          }\n          await this.handleErrorResponse(response);\n        }\n\n        return (await response.json()) as T;\n      } catch (error) {\n        if (error instanceof SentiSenseError) throw error;\n        if (error instanceof Error && error.name === \"AbortError\") {\n          throw new SentiSenseError(`Request timed out after ${this.timeout}ms`);\n        }\n        throw new SentiSenseError(\n          error instanceof Error ? error.message : \"Unknown error\",\n        );\n      } finally {\n        clearTimeout(timer);\n      }\n    }\n\n    throw new SentiSenseError(\"All retries exhausted\");\n  }\n\n  /** @internal */\n  async post<T = unknown>(path: string, body: unknown): Promise<T> {\n    const url = this.buildUrl(path);\n    const headers: Record<string, string> = {\n      \"Accept\": \"application/json\",\n      \"Content-Type\": \"application/json\",\n    };\n\n    if (this.apiKey) {\n      headers[\"X-SentiSense-API-Key\"] = this.apiKey;\n    }\n\n    if (typeof process !== \"undefined\" && process.versions?.node) {\n      headers[\"User-Agent\"] = this.userAgent;\n    }\n\n    const controller = new AbortController();\n    const timer = setTimeout(() => controller.abort(), this.timeout);\n\n    try {\n      const response = await fetch(url, {\n        method: \"POST\",\n        headers,\n        body: JSON.stringify(body),\n        signal: controller.signal,\n      });\n\n      if (!response.ok) {\n        await this.handleErrorResponse(response);\n      }\n\n      return (await response.json()) as T;\n    } catch (error) {\n      if (error instanceof SentiSenseError) throw error;\n      if (error instanceof Error && error.name === \"AbortError\") {\n        throw new SentiSenseError(`Request timed out after ${this.timeout}ms`);\n      }\n      throw new SentiSenseError(\n        error instanceof Error ? error.message : \"Unknown error\",\n      );\n    } finally {\n      clearTimeout(timer);\n    }\n  }\n\n  private buildUrl(path: string, params?: object): string {\n    const url = new URL(path, this.baseUrl);\n    if (params) {\n      for (const [key, value] of Object.entries(params as Record<string, unknown>)) {\n        if (value !== undefined && value !== null) {\n          url.searchParams.set(key, String(value));\n        }\n      }\n    }\n    return url.toString();\n  }\n\n  private async handleErrorResponse(response: Response): Promise<never> {\n    let body: { error?: string; message?: string } = {};\n    try {\n      body = await response.json();\n    } catch {\n      // Response may not be JSON\n    }\n\n    const message = body.message ?? response.statusText ?? \"API request failed\";\n    const code = body.error;\n\n    switch (response.status) {\n      case 401:\n      case 403:\n        throw new AuthenticationError(message, response.status, code);\n      case 404:\n        throw new NotFoundError(message, code);\n      case 429: {\n        // Same clamp the retry loop uses, so a caller running its own backoff off\n        // `error.retryAfter` gets a number it can pass to setTimeout, or nothing at all.\n        const retryAfter = clampRetryAfter(\n          response.headers.get(\"Retry-After\"),\n          MAX_RATE_LIMIT_WAIT_S,\n        );\n        throw new RateLimitError(message, code, retryAfter);\n      }\n      default:\n        throw new APIError(message, response.status, code);\n    }\n  }\n}\n"],"mappings":"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","names":[]}