sentisense 0.44.0 → 0.45.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.cjs CHANGED
@@ -278,6 +278,16 @@ function signedPercent(value, decimals = 2) {
278
278
  function percent(value, decimals = 1) {
279
279
  return isNum(value) ? `${value.toFixed(decimals)}%` : ABSENT;
280
280
  }
281
+ var MAX_RATIO_DECIMALS = 6;
282
+ function ratioPercent(value, decimals = 2) {
283
+ if (!isNum(value)) return ABSENT;
284
+ const scaled = value * 100;
285
+ let places = decimals;
286
+ while (scaled !== 0 && places < MAX_RATIO_DECIMALS && Number(scaled.toFixed(places)) === 0) {
287
+ places += 1;
288
+ }
289
+ return `${scaled.toFixed(places)}%`;
290
+ }
281
291
  function money(value, decimals = 2) {
282
292
  return isNum(value) ? `$${value.toFixed(decimals)}` : ABSENT;
283
293
  }
@@ -1028,7 +1038,7 @@ var flowsCommand = {
1028
1038
  };
1029
1039
 
1030
1040
  // src/version.ts
1031
- var VERSION = "0.44.0";
1041
+ var VERSION = "0.45.0";
1032
1042
 
1033
1043
  // src/resources/analyst.ts
1034
1044
  var Analyst = class {
@@ -2784,13 +2794,20 @@ var newsCommand = {
2784
2794
  "A story is a cluster of articles covering the same event, not a single headline, so",
2785
2795
  "the size column is how many sources picked it up and impact ranks how much it moved.",
2786
2796
  "Tone is the average sentiment across the cluster, between -1 and 1.",
2787
- "--days only applies to the market-wide feed.",
2797
+ "--days only applies to the market-wide feed, and counts from when a story STARTED",
2798
+ "breaking, not from its latest article. A running story with fresh coverage but an",
2799
+ "older start falls out of short windows, so an empty window can be correct. It also",
2800
+ "switches ordering to curation score instead of the day-bucketed default.",
2788
2801
  EMPTY_VERIFY_NOTE,
2789
2802
  EMPTY_VERIFY_NOTE_2
2790
2803
  ],
2791
2804
  flags: {
2792
2805
  limit: { type: "number", placeholder: "N", describe: `Stories to return (default ${DEFAULT_LIMIT})` },
2793
- days: { type: "number", placeholder: "N", describe: "Look-back window, market-wide feed only" }
2806
+ days: {
2807
+ type: "number",
2808
+ placeholder: "N",
2809
+ describe: "Look-back window in days, market-wide feed only"
2810
+ }
2794
2811
  },
2795
2812
  async run({ args, client, full }) {
2796
2813
  const api = client();
@@ -2798,7 +2815,10 @@ var newsCommand = {
2798
2815
  const notes = [];
2799
2816
  const limit = typeof args.flags.limit === "number" ? args.flags.limit : DEFAULT_LIMIT;
2800
2817
  const days = typeof args.flags.days === "number" ? args.flags.days : void 0;
2801
- const stories = ticker ? await api.documents.getStoriesByTicker(ticker, { limit }) : await api.documents.getStories({ limit, ...days === void 0 ? {} : { days } });
2818
+ const stories = ticker ? await api.documents.getStoriesByTicker(ticker, { limit }) : await api.documents.getStories({
2819
+ limit,
2820
+ ...days === void 0 ? {} : { filterHours: days * 24 }
2821
+ });
2802
2822
  if (ticker && stories.length === 0) {
2803
2823
  const note = await verifyTickerOnEmpty(api, ticker);
2804
2824
  if (note) notes.push(note);
@@ -3032,7 +3052,8 @@ function single(row, full) {
3032
3052
  field("Mkt cap", humanize(quote.marketCap)),
3033
3053
  field("P/E", fixed(quote.peRatio)),
3034
3054
  field("EPS TTM", fixed(quote.epsTTM)),
3035
- field("Div yield", percent(quote.dividendYield, 2)),
3055
+ // A ratio, unlike `changePercent` and the other percentages in the same payload.
3056
+ field("Div yield", ratioPercent(quote.dividendYield)),
3036
3057
  field(
3037
3058
  "52w",
3038
3059
  `${fixed(quote.week52Low)} to ${fixed(quote.week52High)}`
package/dist/index.cjs CHANGED
@@ -1036,7 +1036,7 @@ var Trackers = class {
1036
1036
  };
1037
1037
 
1038
1038
  // src/version.ts
1039
- var VERSION = "0.44.0";
1039
+ var VERSION = "0.45.0";
1040
1040
 
1041
1041
  // src/client.ts
1042
1042
  var DEFAULT_BASE_URL = "https://app.sentisense.ai";
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../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/screener.ts","../src/resources/stocks.ts","../src/resources/indexes.ts","../src/resources/trackers.ts","../src/version.ts","../src/client.ts"],"sourcesContent":["export { SentiSense } from \"./client.js\";\nexport { SentiSense as default } from \"./client.js\";\n\nexport type {\n AnalystConsensus,\n AnalystAction,\n AnalystEstimate,\n AnalystEarningsSurprise,\n AnalystEstimatesResponse,\n GetAnalystActionsOptions,\n GetAnalystMarketActivityOptions,\n} from \"./resources/analyst.js\";\n\n// Screener 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} from \"./resources/screener.js\";\n\nexport type {\n GetStockInsightsRangeOptions,\n GetLatestInsightsOptions,\n GetUserInsightsOptions,\n} from \"./resources/insights.js\";\n\n// ETF aggregate types\nexport type {\n EtfInfo,\n EtfHolding,\n EtfHoldings,\n EtfAggregateCoverage,\n WeightedConsensus,\n EtfAnalystContributor,\n EtfAnalystAggregate,\n WeightedNetFlow,\n EtfInsiderContributor,\n EtfInsiderAggregate,\n EtfSentimentReading,\n EtfSentimentAggregate,\n GetEtfInsiderAggregateOptions,\n} from \"./resources/etfs.js\";\n\n// KPI types\nexport type {\n KpiDataPoint,\n KpiSeries,\n CompanyKpisData,\n KpiCoverageEntry,\n KpiCoverageResponse,\n KpiTypeEntry,\n} from \"./types.js\";\n\nexport {\n SentiSenseError,\n AuthenticationError,\n NotFoundError,\n DeepHistoryUnavailableError,\n RateLimitError,\n APIError,\n} from \"./errors.js\";\n\nexport type {\n SentiSenseOptions,\n Insight,\n InsightPreviewResponse,\n LockedInsight,\n GetInsightsOptions,\n InsiderActivitySummary,\n InsiderActivityResponse,\n InsiderTrade,\n ClusterBuy,\n GetInsiderOptions,\n AssetMetadata,\n CongressTrade,\n PoliticianSummary,\n PoliticianDetail,\n PoliticianDirectoryEntry,\n PoliticianDirectory,\n PoliticianDirectoryResponse,\n GetPoliticianActivityOptions,\n GetPoliticianMemberOptions,\n GetPoliticiansOptions,\n GetPoliticianDirectoryOptions,\n EarningsEvent,\n CalendarMeta,\n EarningsCalendarResponse,\n GetEarningsCalendarOptions,\n EarningsKpiHighlight,\n EarningsSource,\n EarningsQuarter,\n RecentEarningsEntry,\n GetEarningsSummariesOptions,\n GetRecentEarningsOptions,\n PreviewResponse,\n StockPrice,\n StockQuote,\n StockDetail,\n SimilarStock,\n StockImage,\n StockProfile,\n StockEntity,\n ChartData,\n ChartDataPoint,\n MarketStatus,\n OptionsSummary,\n OptionsAggregate,\n OptionsContext,\n OptionsOiWalls,\n OptionsWall,\n OptionsUnusualContract,\n Fundamentals,\n TtmFundamentals,\n FundamentalsPeriod,\n FundamentalsPeriodsResponse,\n ShortInterest,\n FloatInfo,\n ShortVolume,\n AISummary,\n MetricsBreakdown,\n Document,\n DocumentSearchResponse,\n DocumentSource,\n SentimentEntry,\n Story,\n StoryCluster,\n Quarter,\n InstitutionalFlow,\n InstitutionalFlows,\n InstitutionalFlowsResponse,\n Holder,\n HolderNotableChanges,\n TickerHolders,\n GetHoldersOptions,\n InstitutionSummary,\n InstitutionList,\n InstitutionListResponse,\n ListInstitutionsOptions,\n MetricType,\n MetricsOptions,\n MetricDistributionOptions,\n ServingMetric,\n MetricDistribution,\n MarketMood,\n MarketSummary,\n KBEntity,\n IndexListing,\n IndexListResponse,\n IndexConstituent,\n IndexSnapshot,\n IndexHistoryPoint,\n IndexHistoryResponse,\n TrackerListing,\n TrackerListResponse,\n TrackerSnapshot,\n TrackerSnapshotResponse,\n TrackerTableRow,\n TrackerMetricValue,\n TrackerHeadlineMetric,\n TrackerGeoEntry,\n TrackerTimeSeriesPoint,\n TrackerEvent,\n TrackerSignal,\n TrackerSourceRef,\n} from \"./types.js\";\n\nexport { VERSION } from \"./version.js\";\n","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 {\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 GetSimilarOptions,\n KpiCoverageResponse,\n KpiTypeEntry,\n MarketStatus,\n MetricsBreakdown,\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\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 name, kbEntityId, urlSlug. */\n async listDetailed(): Promise<StockDetail[]> {\n return this.client.get(\"/api/v1/stocks/detailed\");\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 return this.client.get(\"/api/v1/stocks/popular/detailed\");\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","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.44.0\";\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 { 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\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 }\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":[]}
1
+ {"version":3,"sources":["../src/index.ts","../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/screener.ts","../src/resources/stocks.ts","../src/resources/indexes.ts","../src/resources/trackers.ts","../src/version.ts","../src/client.ts"],"sourcesContent":["export { SentiSense } from \"./client.js\";\nexport { SentiSense as default } from \"./client.js\";\n\nexport type {\n AnalystConsensus,\n AnalystAction,\n AnalystEstimate,\n AnalystEarningsSurprise,\n AnalystEstimatesResponse,\n GetAnalystActionsOptions,\n GetAnalystMarketActivityOptions,\n} from \"./resources/analyst.js\";\n\n// Screener 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} from \"./resources/screener.js\";\n\nexport type {\n GetStockInsightsRangeOptions,\n GetLatestInsightsOptions,\n GetUserInsightsOptions,\n} from \"./resources/insights.js\";\n\n// ETF aggregate types\nexport type {\n EtfInfo,\n EtfHolding,\n EtfHoldings,\n EtfAggregateCoverage,\n WeightedConsensus,\n EtfAnalystContributor,\n EtfAnalystAggregate,\n WeightedNetFlow,\n EtfInsiderContributor,\n EtfInsiderAggregate,\n EtfSentimentReading,\n EtfSentimentAggregate,\n GetEtfInsiderAggregateOptions,\n} from \"./resources/etfs.js\";\n\n// KPI types\nexport type {\n KpiDataPoint,\n KpiSeries,\n CompanyKpisData,\n KpiCoverageEntry,\n KpiCoverageResponse,\n KpiTypeEntry,\n} from \"./types.js\";\n\nexport {\n SentiSenseError,\n AuthenticationError,\n NotFoundError,\n DeepHistoryUnavailableError,\n RateLimitError,\n APIError,\n} from \"./errors.js\";\n\nexport type {\n SentiSenseOptions,\n Insight,\n InsightPreviewResponse,\n LockedInsight,\n GetInsightsOptions,\n InsiderActivitySummary,\n InsiderActivityResponse,\n InsiderTrade,\n ClusterBuy,\n GetInsiderOptions,\n AssetMetadata,\n CongressTrade,\n PoliticianSummary,\n PoliticianDetail,\n PoliticianDirectoryEntry,\n PoliticianDirectory,\n PoliticianDirectoryResponse,\n GetPoliticianActivityOptions,\n GetPoliticianMemberOptions,\n GetPoliticiansOptions,\n GetPoliticianDirectoryOptions,\n EarningsEvent,\n CalendarMeta,\n EarningsCalendarResponse,\n GetEarningsCalendarOptions,\n EarningsKpiHighlight,\n EarningsSource,\n EarningsQuarter,\n RecentEarningsEntry,\n GetEarningsSummariesOptions,\n GetRecentEarningsOptions,\n PreviewResponse,\n StockPrice,\n StockQuote,\n StockDetail,\n SimilarStock,\n StockImage,\n StockProfile,\n StockEntity,\n ChartData,\n ChartDataPoint,\n MarketStatus,\n OptionsSummary,\n OptionsAggregate,\n OptionsContext,\n OptionsOiWalls,\n OptionsWall,\n OptionsUnusualContract,\n Fundamentals,\n TtmFundamentals,\n FundamentalsPeriod,\n FundamentalsPeriodsResponse,\n ShortInterest,\n FloatInfo,\n ShortVolume,\n AISummary,\n MetricsBreakdown,\n Document,\n DocumentSearchResponse,\n DocumentSource,\n SentimentEntry,\n Story,\n StoryCluster,\n Quarter,\n InstitutionalFlow,\n InstitutionalFlows,\n InstitutionalFlowsResponse,\n Holder,\n HolderNotableChanges,\n TickerHolders,\n GetHoldersOptions,\n InstitutionSummary,\n InstitutionList,\n InstitutionListResponse,\n ListInstitutionsOptions,\n MetricType,\n MetricsOptions,\n MetricDistributionOptions,\n ServingMetric,\n MetricDistribution,\n MarketMood,\n MarketSummary,\n KBEntity,\n IndexListing,\n IndexListResponse,\n IndexConstituent,\n IndexSnapshot,\n IndexHistoryPoint,\n IndexHistoryResponse,\n TrackerListing,\n TrackerListResponse,\n TrackerSnapshot,\n TrackerSnapshotResponse,\n TrackerTableRow,\n TrackerMetricValue,\n TrackerHeadlineMetric,\n TrackerGeoEntry,\n TrackerTimeSeriesPoint,\n TrackerEvent,\n TrackerSignal,\n TrackerSourceRef,\n} from \"./types.js\";\n\nexport { VERSION } from \"./version.js\";\n","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 {\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 GetSimilarOptions,\n KpiCoverageResponse,\n KpiTypeEntry,\n MarketStatus,\n MetricsBreakdown,\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\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 name, kbEntityId, urlSlug. */\n async listDetailed(): Promise<StockDetail[]> {\n return this.client.get(\"/api/v1/stocks/detailed\");\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 return this.client.get(\"/api/v1/stocks/popular/detailed\");\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","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.45.0\";\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 { 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\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 }\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":[]}
package/dist/index.d.mts CHANGED
@@ -79,6 +79,11 @@ interface StockQuote {
79
79
  marketCap: number | null;
80
80
  peRatio: number | null;
81
81
  epsTTM: number | null;
82
+ /**
83
+ * Trailing dividend yield as a fraction, not as percentage points: 0.031 is a 3.1% yield.
84
+ * This differs from {@link StockQuote.changePercent}, which is already in percentage points.
85
+ * Null for a stock that pays no dividend.
86
+ */
82
87
  dividendYield: number | null;
83
88
  /** 200-day simple moving average of daily closes. Null when fewer than 200 trading days of history exist. */
84
89
  movingAverage200Day: number | null;
@@ -591,8 +596,13 @@ interface GetBySourceOptions {
591
596
  }
592
597
  interface GetStoriesOptions {
593
598
  limit?: number;
599
+ /**
600
+ * Accepted by the endpoint but ignored, so it does not narrow the window. Use
601
+ * `filterHours` for the look-back, and pass `days * 24` if you are thinking in days.
602
+ */
594
603
  days?: number;
595
604
  offset?: number;
605
+ /** Look-back window in hours, for example 48 for the last two days. */
596
606
  filterHours?: number;
597
607
  }
598
608
  interface GetStoriesByTickerOptions {
@@ -2908,6 +2918,6 @@ declare class APIError extends SentiSenseError {
2908
2918
  constructor(message: string, status: number, code?: string);
2909
2919
  }
2910
2920
 
2911
- declare const VERSION = "0.44.0";
2921
+ declare const VERSION = "0.45.0";
2912
2922
 
2913
2923
  export { type AISummary, APIError, type AnalystAction, type AnalystConsensus, type AnalystEarningsSurprise, type AnalystEstimate, type AnalystEstimatesResponse, type AssetMetadata, AuthenticationError, type CalendarMeta, type ChartData, type ChartDataPoint, type ClusterBuy, type CompanyKpisData, type CongressTrade, DeepHistoryUnavailableError, type Document, type DocumentSearchResponse, type DocumentSource, type EarningsCalendarResponse, type EarningsEvent, type EarningsKpiHighlight, type EarningsQuarter, type EarningsSource, type EtfAggregateCoverage, type EtfAnalystAggregate, type EtfAnalystContributor, type EtfHolding, type EtfHoldings, type EtfInfo, type EtfInsiderAggregate, type EtfInsiderContributor, type EtfScreenerExecuteResponse, type EtfScreenerRow, type EtfSentimentAggregate, type EtfSentimentReading, type FeaturedScreen, type FloatInfo, type Fundamentals, type FundamentalsPeriod, type FundamentalsPeriodsResponse, type GetAnalystActionsOptions, type GetAnalystMarketActivityOptions, type GetEarningsCalendarOptions, type GetEarningsSummariesOptions, type GetEtfInsiderAggregateOptions, type GetHoldersOptions, type GetInsiderOptions, type GetInsightsOptions, type GetLatestInsightsOptions, type GetPoliticianActivityOptions, type GetPoliticianDirectoryOptions, type GetPoliticianMemberOptions, type GetPoliticiansOptions, type GetRecentEarningsOptions, type GetStockInsightsRangeOptions, type GetUserInsightsOptions, type Holder, type HolderNotableChanges, type IndexConstituent, type IndexHistoryPoint, type IndexHistoryResponse, type IndexListResponse, type IndexListing, type IndexSnapshot, type InsiderActivityResponse, type InsiderActivitySummary, type InsiderTrade, type Insight, type InsightPreviewResponse, type InstitutionList, type InstitutionListResponse, type InstitutionSummary, type InstitutionalFlow, type InstitutionalFlows, type InstitutionalFlowsResponse, type KBEntity, type KpiCoverageEntry, type KpiCoverageResponse, type KpiDataPoint, type KpiSeries, type KpiTypeEntry, type ListInstitutionsOptions, type LockedInsight, type MarketMood, type MarketStatus, type MarketSummary, type MetricDistribution, type MetricDistributionOptions, type MetricType, type MetricsBreakdown, type MetricsOptions, NotFoundError, type OptionsAggregate, type OptionsContext, type OptionsOiWalls, type OptionsSummary, type OptionsUnusualContract, type OptionsWall, type PoliticianDetail, type PoliticianDirectory, type PoliticianDirectoryEntry, type PoliticianDirectoryResponse, type PoliticianSummary, type PreviewResponse, type Quarter, RateLimitError, type RecentEarningsEntry, type ScreenerExecuteOptions, type ScreenerExecuteResponse, type ScreenerFieldCatalog, type ScreenerFieldDescriptor, type ScreenerFieldOption, type ScreenerFilter, type ScreenerPlan, type ScreenerRow, type ScreenerScreensResponse, type ScreenerSort, SentiSense, SentiSenseError, type SentiSenseOptions, type SentimentEntry, type ServingMetric, type ShortInterest, type ShortVolume, type SimilarStock, type StockDetail, type StockEntity, type StockImage, type StockPrice, type StockProfile, type StockQuote, type Story, type StoryCluster, type TickerHolders, type TrackerEvent, type TrackerGeoEntry, type TrackerHeadlineMetric, type TrackerListResponse, type TrackerListing, type TrackerMetricValue, type TrackerSignal, type TrackerSnapshot, type TrackerSnapshotResponse, type TrackerSourceRef, type TrackerTableRow, type TrackerTimeSeriesPoint, type TtmFundamentals, VERSION, type WeightedConsensus, type WeightedNetFlow, SentiSense as default };
package/dist/index.d.ts CHANGED
@@ -79,6 +79,11 @@ interface StockQuote {
79
79
  marketCap: number | null;
80
80
  peRatio: number | null;
81
81
  epsTTM: number | null;
82
+ /**
83
+ * Trailing dividend yield as a fraction, not as percentage points: 0.031 is a 3.1% yield.
84
+ * This differs from {@link StockQuote.changePercent}, which is already in percentage points.
85
+ * Null for a stock that pays no dividend.
86
+ */
82
87
  dividendYield: number | null;
83
88
  /** 200-day simple moving average of daily closes. Null when fewer than 200 trading days of history exist. */
84
89
  movingAverage200Day: number | null;
@@ -591,8 +596,13 @@ interface GetBySourceOptions {
591
596
  }
592
597
  interface GetStoriesOptions {
593
598
  limit?: number;
599
+ /**
600
+ * Accepted by the endpoint but ignored, so it does not narrow the window. Use
601
+ * `filterHours` for the look-back, and pass `days * 24` if you are thinking in days.
602
+ */
594
603
  days?: number;
595
604
  offset?: number;
605
+ /** Look-back window in hours, for example 48 for the last two days. */
596
606
  filterHours?: number;
597
607
  }
598
608
  interface GetStoriesByTickerOptions {
@@ -2908,6 +2918,6 @@ declare class APIError extends SentiSenseError {
2908
2918
  constructor(message: string, status: number, code?: string);
2909
2919
  }
2910
2920
 
2911
- declare const VERSION = "0.44.0";
2921
+ declare const VERSION = "0.45.0";
2912
2922
 
2913
2923
  export { type AISummary, APIError, type AnalystAction, type AnalystConsensus, type AnalystEarningsSurprise, type AnalystEstimate, type AnalystEstimatesResponse, type AssetMetadata, AuthenticationError, type CalendarMeta, type ChartData, type ChartDataPoint, type ClusterBuy, type CompanyKpisData, type CongressTrade, DeepHistoryUnavailableError, type Document, type DocumentSearchResponse, type DocumentSource, type EarningsCalendarResponse, type EarningsEvent, type EarningsKpiHighlight, type EarningsQuarter, type EarningsSource, type EtfAggregateCoverage, type EtfAnalystAggregate, type EtfAnalystContributor, type EtfHolding, type EtfHoldings, type EtfInfo, type EtfInsiderAggregate, type EtfInsiderContributor, type EtfScreenerExecuteResponse, type EtfScreenerRow, type EtfSentimentAggregate, type EtfSentimentReading, type FeaturedScreen, type FloatInfo, type Fundamentals, type FundamentalsPeriod, type FundamentalsPeriodsResponse, type GetAnalystActionsOptions, type GetAnalystMarketActivityOptions, type GetEarningsCalendarOptions, type GetEarningsSummariesOptions, type GetEtfInsiderAggregateOptions, type GetHoldersOptions, type GetInsiderOptions, type GetInsightsOptions, type GetLatestInsightsOptions, type GetPoliticianActivityOptions, type GetPoliticianDirectoryOptions, type GetPoliticianMemberOptions, type GetPoliticiansOptions, type GetRecentEarningsOptions, type GetStockInsightsRangeOptions, type GetUserInsightsOptions, type Holder, type HolderNotableChanges, type IndexConstituent, type IndexHistoryPoint, type IndexHistoryResponse, type IndexListResponse, type IndexListing, type IndexSnapshot, type InsiderActivityResponse, type InsiderActivitySummary, type InsiderTrade, type Insight, type InsightPreviewResponse, type InstitutionList, type InstitutionListResponse, type InstitutionSummary, type InstitutionalFlow, type InstitutionalFlows, type InstitutionalFlowsResponse, type KBEntity, type KpiCoverageEntry, type KpiCoverageResponse, type KpiDataPoint, type KpiSeries, type KpiTypeEntry, type ListInstitutionsOptions, type LockedInsight, type MarketMood, type MarketStatus, type MarketSummary, type MetricDistribution, type MetricDistributionOptions, type MetricType, type MetricsBreakdown, type MetricsOptions, NotFoundError, type OptionsAggregate, type OptionsContext, type OptionsOiWalls, type OptionsSummary, type OptionsUnusualContract, type OptionsWall, type PoliticianDetail, type PoliticianDirectory, type PoliticianDirectoryEntry, type PoliticianDirectoryResponse, type PoliticianSummary, type PreviewResponse, type Quarter, RateLimitError, type RecentEarningsEntry, type ScreenerExecuteOptions, type ScreenerExecuteResponse, type ScreenerFieldCatalog, type ScreenerFieldDescriptor, type ScreenerFieldOption, type ScreenerFilter, type ScreenerPlan, type ScreenerRow, type ScreenerScreensResponse, type ScreenerSort, SentiSense, SentiSenseError, type SentiSenseOptions, type SentimentEntry, type ServingMetric, type ShortInterest, type ShortVolume, type SimilarStock, type StockDetail, type StockEntity, type StockImage, type StockPrice, type StockProfile, type StockQuote, type Story, type StoryCluster, type TickerHolders, type TrackerEvent, type TrackerGeoEntry, type TrackerHeadlineMetric, type TrackerListResponse, type TrackerListing, type TrackerMetricValue, type TrackerSignal, type TrackerSnapshot, type TrackerSnapshotResponse, type TrackerSourceRef, type TrackerTableRow, type TrackerTimeSeriesPoint, type TtmFundamentals, VERSION, type WeightedConsensus, type WeightedNetFlow, SentiSense as default };
package/dist/index.mjs CHANGED
@@ -1002,7 +1002,7 @@ var Trackers = class {
1002
1002
  };
1003
1003
 
1004
1004
  // src/version.ts
1005
- var VERSION = "0.44.0";
1005
+ var VERSION = "0.45.0";
1006
1006
 
1007
1007
  // src/client.ts
1008
1008
  var DEFAULT_BASE_URL = "https://app.sentisense.ai";
@@ -1 +1 @@
1
- {"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/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 {\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 GetSimilarOptions,\n KpiCoverageResponse,\n KpiTypeEntry,\n MarketStatus,\n MetricsBreakdown,\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\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 name, kbEntityId, urlSlug. */\n async listDetailed(): Promise<StockDetail[]> {\n return this.client.get(\"/api/v1/stocks/detailed\");\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 return this.client.get(\"/api/v1/stocks/popular/detailed\");\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","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.44.0\";\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 { 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\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 }\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":[]}
1
+ {"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/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 {\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 GetSimilarOptions,\n KpiCoverageResponse,\n KpiTypeEntry,\n MarketStatus,\n MetricsBreakdown,\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\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 name, kbEntityId, urlSlug. */\n async listDetailed(): Promise<StockDetail[]> {\n return this.client.get(\"/api/v1/stocks/detailed\");\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 return this.client.get(\"/api/v1/stocks/popular/detailed\");\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","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.45.0\";\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 { 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\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 }\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":";AAAO,IAAM,kBAAN,cAA8B,MAAM;AAAA,EAIzC,YAAY,SAAiB,QAAiB,MAAe;AAC3D,UAAM,OAAO;AACb,SAAK,OAAO;AACZ,SAAK,SAAS;AACd,SAAK,OAAO;AAAA,EACd;AACF;AAEO,IAAM,sBAAN,cAAkC,gBAAgB;AAAA,EACvD,YAAY,SAAiB,QAAgB,MAAe;AAC1D,UAAM,SAAS,QAAQ,IAAI;AAC3B,SAAK,OAAO;AAAA,EACd;AACF;AAEO,IAAM,gBAAN,cAA4B,gBAAgB;AAAA,EACjD,YAAY,SAAiB,MAAe;AAC1C,UAAM,SAAS,KAAK,IAAI;AACxB,SAAK,OAAO;AAAA,EACd;AACF;AASO,IAAM,8BAAN,cAA0C,gBAAgB;AAAA,EAG/D,YAAY,SAAiB,YAAqB;AAChD,UAAM,SAAS,GAAG;AAClB,SAAK,OAAO;AACZ,SAAK,aAAa;AAAA,EACpB;AACF;AAEO,IAAM,iBAAN,cAA6B,gBAAgB;AAAA,EASlD,YAAY,SAAiB,MAAe,YAAqB;AAC/D,UAAM,SAAS,KAAK,IAAI;AACxB,SAAK,OAAO;AACZ,SAAK,aAAa;AAAA,EACpB;AACF;AAEO,IAAM,WAAN,cAAuB,gBAAgB;AAAA,EAC5C,YAAY,SAAiB,QAAgB,MAAe;AAC1D,UAAM,SAAS,QAAQ,IAAI;AAC3B,SAAK,OAAO;AAAA,EACd;AACF;;;ACMO,IAAM,UAAN,MAAc;AAAA,EACnB,YAAoB,QAAmB;AAAnB;AAAA,EAAoB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMxC,MAAM,UACJ,QAC4C;AAC5C,WAAO,KAAK,OAAO;AAAA,MACjB,mBAAmB,mBAAmB,OAAO,YAAY,CAAC,CAAC;AAAA,IAC7D;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,QACJ,QACA,SAC2C;AAC3C,WAAO,KAAK,OAAO;AAAA,MACjB,mBAAmB,mBAAmB,OAAO,YAAY,CAAC,CAAC;AAAA,MAC3D;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,UACJ,QACoD;AACpD,WAAO,KAAK,OAAO;AAAA,MACjB,mBAAmB,mBAAmB,OAAO,YAAY,CAAC,CAAC;AAAA,IAC7D;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,eACJ,SAC2C;AAC3C,WAAO,KAAK,OAAO,IAAI,4BAA4B,OAAO;AAAA,EAC5D;AACF;;;ACjHO,IAAM,WAAN,MAAe;AAAA,EACpB,YAAoB,QAAmB;AAAnB;AAAA,EAAoB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUxC,MAAM,YACJ,SACoD;AACpD,WAAO,KAAK,OAAO,IAAI,6BAA6B,OAAO;AAAA,EAC7D;AACF;;;ACTO,IAAM,YAAN,MAAgB;AAAA,EACrB,YAAoB,QAAmB;AAAnB;AAAA,EAAoB;AAAA;AAAA,EAGxC,MAAM,YAAY,QAAgB,SAA+D;AAC/F,WAAO,KAAK,OAAO,IAAI,4BAA4B,mBAAmB,MAAM,CAAC,IAAI,OAAO;AAAA,EAC1F;AAAA;AAAA,EAGA,MAAM,iBAAiB,QAAgB,SAAmE;AACxG,WAAO,KAAK,OAAO;AAAA,MACjB,4BAA4B,mBAAmB,MAAM,CAAC;AAAA,MACtD;AAAA,IACF;AAAA,EACF;AAAA;AAAA,EAGA,MAAM,YAAY,UAAkB,SAA+D;AACjG,WAAO,KAAK,OAAO;AAAA,MACjB,4BAA4B,mBAAmB,QAAQ,CAAC;AAAA,MACxD;AAAA,IACF;AAAA,EACF;AAAA;AAAA,EAGA,MAAM,OAAO,OAAe,SAAmE;AAC7F,WAAO,KAAK,OAAO,IAAI,4BAA4B,EAAE,OAAO,GAAG,QAAQ,CAAC;AAAA,EAC1E;AAAA;AAAA,EAGA,MAAM,YAAY,QAAwB,SAA+D;AACvG,WAAO,KAAK,OAAO;AAAA,MACjB,4BAA4B,mBAAmB,MAAM,CAAC;AAAA,MACtD;AAAA,IACF;AAAA,EACF;AAAA;AAAA,EAGA,MAAM,WAAW,SAA+C;AAC9D,WAAO,KAAK,OAAO,IAAI,6BAA6B,OAAO;AAAA,EAC7D;AAAA;AAAA,EAGA,MAAM,eAAe,WAAqC;AACxD,WAAO,KAAK,OAAO,IAAI,6BAA6B,mBAAmB,SAAS,CAAC,EAAE;AAAA,EACrF;AAAA;AAAA,EAGA,MAAM,mBACJ,QACA,SACkB;AAClB,WAAO,KAAK,OAAO;AAAA,MACjB,oCAAoC,mBAAmB,MAAM,CAAC;AAAA,MAC9D;AAAA,IACF;AAAA,EACF;AAEF;;;ACjDO,IAAM,WAAN,MAAe;AAAA,EACpB,YAAoB,QAAmB;AAAnB;AAAA,EAAoB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAsBxC,MAAM,aACJ,QACA,SAC6C;AAC7C,WAAO,KAAK,OAAO;AAAA,MACjB,kBAAkB,mBAAmB,OAAO,YAAY,CAAC,CAAC;AAAA,MAC1D;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,MAAM,UACJ,SACiD;AACjD,WAAO,KAAK,OAAO,IAAI,2BAA2B,OAAO;AAAA,EAC3D;AACF;;;AC/DO,IAAM,gBAAN,MAAoB;AAAA,EACzB,YAAoB,QAAmB;AAAnB;AAAA,EAAoB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASxC,MAAM,WACJ,QACA,UAA0B,CAAC,GACD;AAC1B,UAAM,EAAE,aAAa,aAAa,WAAW,SAAS,cAAc,IAAI;AACxE,WAAO,KAAK,OAAO;AAAA,MACjB,0BAA0B,mBAAmB,MAAM,CAAC,WAAW,mBAAmB,UAAU,CAAC;AAAA,MAC7F;AAAA,QACE,GAAI,cAAc,UAAa,EAAE,UAAU;AAAA,QAC3C,GAAI,YAAY,UAAa,EAAE,QAAQ;AAAA,QACvC,GAAI,kBAAkB,UAAa,EAAE,cAAc;AAAA,MACrD;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,gBACJ,QACA,YACA,UAAqC,CAAC,GACT;AAC7B,UAAM,EAAE,YAAY,SAAS,IAAI;AACjC,WAAO,KAAK,OAAO;AAAA,MACjB,0BAA0B,mBAAmB,MAAM,CAAC,iBAAiB,mBAAmB,UAAU,CAAC;AAAA,MACnG,EAAE,UAAU;AAAA,IACd;AAAA,EACF;AACF;;;ACkGO,IAAM,OAAN,MAAW;AAAA,EAChB,YAAoB,QAAmB;AAAnB;AAAA,EAAoB;AAAA;AAAA;AAAA;AAAA,EAKxC,MAAM,OAA2B;AAC/B,WAAO,KAAK,OAAO,IAAI,cAAc;AAAA,EACvC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,SAAS,QAAsC;AACnD,WAAO,KAAK,OAAO;AAAA,MACjB,gBAAgB,mBAAmB,OAAO,YAAY,CAAC,CAAC;AAAA,IAC1D;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,iBACJ,QAC+C;AAC/C,WAAO,KAAK,OAAO;AAAA,MACjB,gBAAgB,mBAAmB,OAAO,YAAY,CAAC,CAAC;AAAA,IAC1D;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,iBACJ,QACA,SAC+C;AAC/C,WAAO,KAAK,OAAO;AAAA,MACjB,gBAAgB,mBAAmB,OAAO,YAAY,CAAC,CAAC;AAAA,MACxD;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,mBACJ,QACiD;AACjD,WAAO,KAAK,OAAO;AAAA,MACjB,gBAAgB,mBAAmB,OAAO,YAAY,CAAC,CAAC;AAAA,IAC1D;AAAA,EACF;AACF;;;ACzMO,IAAM,UAAN,MAAc;AAAA,EACnB,YAAoB,QAAmB;AAAnB;AAAA,EAAoB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQxC,MAAM,YAAY,SAAgF;AAChG,WAAO,KAAK,OAAO,IAAI,4BAA4B,OAAO;AAAA,EAC5D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,UAAU,QAAgB,SAAuE;AACrG,WAAO,KAAK,OAAO;AAAA,MACjB,0BAA0B,mBAAmB,OAAO,YAAY,CAAC,CAAC;AAAA,MAClE;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,eAAe,SAAqE;AACxF,WAAO,KAAK,OAAO,IAAI,gCAAgC,OAAO;AAAA,EAChE;AACF;;;AC5BO,IAAM,cAAN,MAAkB;AAAA,EACvB,YAAoB,QAAmB;AAAnB;AAAA,EAAoB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAqBxC,MAAM,YACJ,SAC2C;AAC3C,WAAO,KAAK,OAAO,IAAI,gCAAgC,OAAO;AAAA,EAChE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,WACJ,QACA,SAC2C;AAC3C,WAAO,KAAK,OAAO;AAAA,MACjB,+BAA+B,mBAAmB,OAAO,YAAY,CAAC,CAAC;AAAA,MACvE;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAeA,MAAM,aACJ,SAC8B;AAC9B,UAAM,OAAO,MAAM,KAAK,OAAO;AAAA,MAC7B;AAAA,MACA,EAAE,GAAG,QAAQ;AAAA,IACf;AACA,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,aAA4D;AAChE,WAAO,KAAK,OAAO,IAAI,6BAA6B;AAAA,EACtD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAsBA,MAAM,UACJ,MACA,SAC4C;AAC5C,WAAO,KAAK,OAAO;AAAA,MACjB,8BAA8B,mBAAmB,IAAI,CAAC;AAAA,MACtD;AAAA,IACF;AAAA,EACF;AACF;;;ACjGO,IAAM,WAAN,MAAe;AAAA,EACpB,YAAoB,QAAmB;AAAnB;AAAA,EAAoB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASxC,MAAM,MACJ,QACA,SACqC;AACrC,WAAO,KAAK,OAAO;AAAA,MACjB,0BAA0B,mBAAmB,OAAO,YAAY,CAAC,CAAC;AAAA,MAClE;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,WACJ,QACA,SACqC;AACrC,WAAO,KAAK,OAAO;AAAA,MACjB,0BAA0B,mBAAmB,OAAO,YAAY,CAAC,CAAC;AAAA,MAClE;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,SAA8C;AAClD,WAAO,KAAK,OAAO,IAAI,yBAAyB;AAAA,EAClD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,OACJ,SACqC;AACrC,WAAO,KAAK,OAAO,IAAI,2BAA2B,OAAO;AAAA,EAC3D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,KACJ,SACqC;AACrC,WAAO,KAAK,OAAO,IAAI,yBAAyB,OAAO;AAAA,EACzD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,MAAM,QAAmC;AAC7C,WAAO,KAAK,OAAO;AAAA,MACjB,0BAA0B,mBAAmB,OAAO,YAAY,CAAC,CAAC;AAAA,IACpE;AAAA,EACF;AACF;;;AC9FO,IAAM,gBAAN,MAAoB;AAAA,EACzB,YAAoB,QAAmB;AAAnB;AAAA,EAAoB;AAAA;AAAA,EAGxC,MAAM,cAAkC;AACtC,WAAO,KAAK,OAAO,IAAI,gCAAgC;AAAA,EACzD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAM,SACJ,YACA,SAC8C;AAC9C,WAAO,KAAK,OAAO,IAAI,+BAA+B;AAAA,MACpD;AAAA,MACA,GAAG;AAAA,IACL,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAmBA,MAAM,WACJ,QACA,YACA,SACyC;AACzC,WAAO,KAAK,OAAO;AAAA,MACjB,iCAAiC,mBAAmB,MAAM,CAAC;AAAA,MAC3D,EAAE,YAAY,GAAG,QAAQ;AAAA,IAC3B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,aAAa,YAAwD;AACzE,WAAO,KAAK,OAAO,IAAI,kCAAkC,EAAE,WAAW,CAAC;AAAA,EACzE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,MAAM,iBAAiB,SAA6D;AAClF,UAAM,OAAO,MAAM,KAAK,OAAO;AAAA,MAC7B;AAAA,MACA,EAAE,GAAG,QAAQ;AAAA,IACf;AACA,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,qBAAqB,WAAqC;AAC9D,WAAO,KAAK,OAAO;AAAA,MACjB,qCAAqC,mBAAmB,SAAS,CAAC;AAAA,IACpE;AAAA,EACF;AACF;;;AC5GO,IAAM,KAAN,MAAS;AAAA,EACd,YAAoB,QAAmB;AAAnB;AAAA,EAAoB;AAAA;AAAA,EAGxC,MAAM,qBAA0C;AAC9C,WAAO,KAAK,OAAO,IAAI,6BAA6B;AAAA,EACtD;AACF;;;ACPO,IAAM,qBAAN,MAAyB;AAAA,EAC9B,YAAoB,QAAmB;AAAnB;AAAA,EAAoB;AAAA;AAAA,EAGxC,MAAM,MAA2B;AAC/B,WAAO,KAAK,OAAO,IAAI,qBAAqB;AAAA,EAC9C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAQF;;;ACdO,IAAM,wBAAN,MAA4B;AAAA,EACjC,YAAoB,QAAmB;AAAnB;AAAA,EAAoB;AAAA;AAAA,EAGxC,MAAM,MAA8B;AAClC,WAAO,KAAK,OAAO,IAAI,wBAAwB;AAAA,EACjD;AACF;;;AC4CO,IAAM,WAAN,MAAe;AAAA,EACpB,YAAoB,QAAmB;AAAnB;AAAA,EAAoB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWxC,MAAM,SAAwC;AAC5C,WAAO,KAAK,OAAO,IAAI,yBAAyB;AAAA,EAClD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAM,UAA4C;AAChD,WAAO,KAAK,OAAO,IAAI,0BAA0B;AAAA,EACnD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA6BA,MAAM,IAAI,SAAmE;AAC3E,WAAO,KAAK,OAAO,KAAK,4BAA4B,OAAO;AAAA,EAC7D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAiBA,MAAM,QAAQ,SAAsE;AAClF,WAAO,KAAK,OAAO,KAAK,iCAAiC,OAAO;AAAA,EAClE;AACF;;;ACjGO,IAAM,SAAN,MAAa;AAAA,EAClB,YAAoB,QAAmB;AAAnB;AAAA,EAAoB;AAAA;AAAA,EAGxC,MAAM,OAA0B;AAC9B,WAAO,KAAK,OAAO,IAAI,gBAAgB;AAAA,EACzC;AAAA;AAAA,EAGA,MAAM,eAAuC;AAC3C,WAAO,KAAK,OAAO,IAAI,yBAAyB;AAAA,EAClD;AAAA;AAAA,EAGA,MAAM,cAAiC;AACrC,WAAO,KAAK,OAAO,IAAI,wBAAwB;AAAA,EACjD;AAAA;AAAA,EAGA,MAAM,sBAA8C;AAClD,WAAO,KAAK,OAAO,IAAI,iCAAiC;AAAA,EAC1D;AAAA;AAAA,EAGA,MAAM,SAAS,QAAqC;AAClD,WAAO,KAAK,OAAO,IAAI,wBAAwB,EAAE,OAAO,CAAC;AAAA,EAC3D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,SAAS,QAAqC;AAClD,WAAO,KAAK,OAAO,IAAI,kBAAkB,mBAAmB,MAAM,CAAC,QAAQ;AAAA,EAC7E;AAAA;AAAA,EAGA,MAAM,UAAU,SAA0C;AACxD,WAAO,KAAK,OAAO,IAAI,yBAAyB;AAAA,MAC9C,SAAS,QAAQ,KAAK,GAAG;AAAA,IAC3B,CAAC;AAAA,EACH;AAAA;AAAA,EAGA,MAAM,UACJ,SACA,SACqC;AACrC,WAAO,KAAK,OAAO,IAAI,yBAAyB;AAAA,MAC9C,SAAS,QAAQ,KAAK,GAAG;AAAA,MACzB,GAAG;AAAA,IACL,CAAC;AAAA,EACH;AAAA;AAAA,EAGA,MAAM,gBACJ,SACA,SACuC;AACvC,WAAO,KAAK,OAAO,IAAI,+BAA+B;AAAA,MACpD,SAAS,QAAQ,KAAK,GAAG;AAAA,MACzB,GAAG;AAAA,IACL,CAAC;AAAA,EACH;AAAA;AAAA,EAGA,MAAM,WAAW,QAAgB,SAAsD;AACrF,WAAO,KAAK,OAAO,IAAI,kBAAkB,mBAAmB,MAAM,CAAC,YAAY,OAAO;AAAA,EACxF;AAAA;AAAA,EAGA,MAAM,WAAW,QAAgB,SAAoD;AACnF,WAAO,KAAK,OAAO,IAAI,kBAAkB,mBAAmB,MAAM,CAAC,YAAY,OAAO;AAAA,EACxF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,MAAM,aAAa,QAA0D;AAC3E,WAAO,KAAK,OAAO;AAAA,MACjB,kBAAkB,mBAAmB,MAAM,CAAC;AAAA,IAC9C;AAAA,EACF;AAAA;AAAA,EAGA,MAAM,YAAY,QAAwC;AACxD,WAAO,KAAK,OAAO,IAAI,kBAAkB,mBAAmB,MAAM,CAAC,WAAW;AAAA,EAChF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,aAAa,QAAgB,SAAmD;AACpF,UAAM,EAAE,cAAc,eAAe,GAAG,OAAO,IAAI,WAAW,CAAC;AAC/D,WAAO,KAAK,OAAO,IAAI,kBAAkB,mBAAmB,MAAM,CAAC,eAAe,MAAM;AAAA,EAC1F;AAAA;AAAA,EAGA,MAAM,oBACJ,QACA,YACA,SAC2B;AAC3B,WAAO,KAAK,OAAO;AAAA,MACjB,kBAAkB,mBAAmB,MAAM,CAAC,YAAY,mBAAmB,UAAU,CAAC;AAAA,MACtF;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,SAAS,QAAgB,SAA+C;AAC5E,UAAM,OAAO,MAAM,KAAK,OAAO,IAAsB,wBAAwB;AAAA,MAC3E;AAAA,MACA,GAAG;AAAA,IACL,CAAC;AACD,WAAO,EAAE,QAAQ,WAAW,SAAS,aAAa,MAAM,KAAK;AAAA,EAC/D;AAAA;AAAA,EAGA,MAAM,kBAAyC;AAC7C,WAAO,KAAK,OAAO,IAAI,8BAA8B;AAAA,EACvD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,gBAAgB,QAAgB,SAAyD;AAC7F,WAAO,KAAK,OAAO,IAAI,+BAA+B,EAAE,QAAQ,GAAG,QAAQ,CAAC;AAAA,EAC9E;AAAA;AAAA,EAGA,MAAM,uBAAuB,QAAsD;AACjF,WAAO,KAAK,OAAO,IAAI,uCAAuC,EAAE,OAAO,CAAC;AAAA,EAC1E;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,uBAAuB,QAA0C;AACrE,WAAO,KAAK,OAAO,IAAI,uCAAuC,EAAE,OAAO,CAAC;AAAA,EAC1E;AAAA;AAAA,EAGA,MAAM,qBAAqB,QAAkC;AAC3D,WAAO,KAAK,OAAO,IAAI,kDAAkD,EAAE,OAAO,CAAC;AAAA,EACrF;AAAA;AAAA,EAGA,MAAM,iBAAiB,QAAwC;AAC7D,WAAO,KAAK,OAAO,IAAI,iCAAiC,EAAE,OAAO,CAAC;AAAA,EACpE;AAAA;AAAA,EAGA,MAAM,SAAS,QAAoC;AACjD,WAAO,KAAK,OAAO,IAAI,wBAAwB,EAAE,OAAO,CAAC;AAAA,EAC3D;AAAA;AAAA,EAGA,MAAM,eAAe,QAAsC;AACzD,WAAO,KAAK,OAAO,IAAI,+BAA+B,EAAE,OAAO,CAAC;AAAA,EAClE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,MAAM,QAAQ,QAA2D;AACvE,WAAO,KAAK,OAAO;AAAA,MACjB,kBAAkB,mBAAmB,OAAO,YAAY,CAAC,CAAC;AAAA,IAC5D;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,kBAAgD;AACpD,WAAO,KAAK,OAAO,IAAI,0BAA0B;AAAA,EACnD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,YAAY,QAAyC;AACzD,WAAO,KAAK,OAAO;AAAA,MACjB,kBAAkB,mBAAmB,OAAO,YAAY,CAAC,CAAC;AAAA,IAC5D;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAuBA,MAAM,kBAAkB,QAAiE;AACvF,WAAO,KAAK,OAAO;AAAA,MACjB,kBAAkB,mBAAmB,OAAO,YAAY,CAAC,CAAC;AAAA,IAC5D;AAAA,EACF;AACF;;;AC7QO,IAAM,UAAN,MAAc;AAAA,EACnB,YAAoB,QAAmB;AAAnB;AAAA,EAAoB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUxC,MAAM,OAAmC;AACvC,WAAO,KAAK,OAAO,IAAI,iBAAiB;AAAA,EAC1C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,MAAM,IAAI,SAAyC;AACjD,WAAO,KAAK,OAAO,IAAI,mBAAmB,OAAO,EAAE;AAAA,EACrD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAM,QAAQ,SAAiB,MAA8C;AAC3E,WAAO,KAAK,OAAO;AAAA,MACjB,mBAAmB,OAAO;AAAA,MAC1B,SAAS,SAAY,SAAY,EAAE,KAAK;AAAA,IAC1C;AAAA,EACF;AACF;;;AClDO,IAAM,WAAN,MAAe;AAAA,EACpB,YAAoB,QAAmB;AAAnB;AAAA,EAAoB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMxC,MAAM,OAAqC;AACzC,WAAO,KAAK,OAAO,IAAI,kBAAkB;AAAA,EAC3C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,MAAM,IACJ,WACA,QACkC;AAClC,WAAO,KAAK,OAAO,IAAI,oBAAoB,SAAS,IAAI,MAAM;AAAA,EAChE;AACF;;;AC9CO,IAAM,UAAU;;;AC4BvB,IAAM,mBAAmB;AACzB,IAAM,kBAAkB;AACxB,IAAM,sBAAsB;AAC5B,IAAM,gBAAgB;AACtB,IAAM,eAAe;AAErB,IAAM,+BAA+B;AAKrC,IAAM,0BAA0B;AAChC,IAAM,wBAAwB;AAC9B,IAAM,6BAA6B;AAYnC,SAAS,gBACP,KACA,UACoB;AACpB,MAAI,CAAC,IAAK,QAAO;AACjB,QAAM,SAAS,OAAO,GAAG;AACzB,MAAI,CAAC,OAAO,SAAS,MAAM,EAAG,QAAO;AACrC,SAAO,KAAK,IAAI,KAAK,IAAI,KAAK,MAAM,GAAG,QAAQ;AACjD;AAGA,SAAS,kBACP,KACA,UACA,UACQ;AACR,SAAO,gBAAgB,KAAK,QAAQ,KAAK;AAC3C;AAEA,SAAS,MAAM,IAA2B;AACxC,SAAO,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,EAAE,CAAC;AACzD;AAQO,IAAM,aAAN,MAAsC;AAAA,EAyB3C,YAAY,UAA6B,CAAC,GAAG;AAC3C,SAAK,SAAS,QAAQ;AACtB,SAAK,WAAW,QAAQ,WAAW,kBAAkB,QAAQ,QAAQ,EAAE;AACvE,SAAK,UAAU,QAAQ,WAAW;AAClC,SAAK,aAAa,QAAQ,cAAc;AAGxC,UAAM,SAAS,QAAQ,iBAAiB,QAAQ,YAAY,GAAG,EAAE,KAAK;AACtE,SAAK,YAAY,SACb,mBAAmB,OAAO,IAAI,MAAM,KACpC,mBAAmB,OAAO;AAE9B,SAAK,SAAS,IAAI,OAAO,IAAI;AAC7B,SAAK,YAAY,IAAI,UAAU,IAAI;AACnC,SAAK,OAAO,IAAI,KAAK,IAAI;AACzB,SAAK,gBAAgB,IAAI,cAAc,IAAI;AAC3C,SAAK,UAAU,IAAI,QAAQ,IAAI;AAC/B,SAAK,cAAc,IAAI,YAAY,IAAI;AACvC,SAAK,WAAW,IAAI,SAAS,IAAI;AACjC,SAAK,UAAU,IAAI,QAAQ,IAAI;AAC/B,SAAK,gBAAgB,IAAI,cAAc,IAAI;AAC3C,SAAK,aAAa,IAAI,mBAAmB,IAAI;AAC7C,SAAK,gBAAgB,IAAI,sBAAsB,IAAI;AACnD,SAAK,KAAK,IAAI,GAAG,IAAI;AACrB,SAAK,UAAU,IAAI,QAAQ,IAAI;AAC/B,SAAK,WAAW,IAAI,SAAS,IAAI;AACjC,SAAK,WAAW,IAAI,SAAS,IAAI;AACjC,SAAK,WAAW,IAAI,SAAS,IAAI;AACjC,SAAK,WAAW,IAAI,SAAS,IAAI;AAAA,EACnC;AAAA;AAAA,EAGA,MAAM,IAAiB,MAAc,QAA6B;AAChE,UAAM,MAAM,KAAK,SAAS,MAAM,MAAM;AACtC,UAAM,UAAkC;AAAA,MACtC,UAAU;AAAA,IACZ;AAEA,QAAI,KAAK,QAAQ;AACf,cAAQ,sBAAsB,IAAI,KAAK;AAAA,IACzC;AAGA,QAAI,OAAO,YAAY,eAAe,QAAQ,UAAU,MAAM;AAC5D,cAAQ,YAAY,IAAI,KAAK;AAAA,IAC/B;AAEA,QAAI,UAAU;AAEd,aAAS,UAAU,GAAG,WAAW,KAAK,YAAY,WAAW;AAC3D,UAAI,UAAU,GAAG;AACf,cAAM,MAAM,OAAO;AACnB,kBAAU;AAAA,MACZ;AAEA,YAAM,aAAa,IAAI,gBAAgB;AACvC,YAAM,QAAQ,WAAW,MAAM,WAAW,MAAM,GAAG,KAAK,OAAO;AAE/D,UAAI;AACF,cAAM,WAAW,MAAM,MAAM,KAAK;AAAA,UAChC,QAAQ;AAAA,UACR;AAAA,UACA,QAAQ,WAAW;AAAA,QACrB,CAAC;AAMD,YAAI,SAAS,WAAW,KAAK;AAC3B,gBAAM,cAAc;AAAA,YAClB,SAAS,QAAQ,IAAI,aAAa;AAAA,YAClC;AAAA,YACA;AAAA,UACF;AACA,cAAI;AAAE,kBAAM,SAAS,MAAM,OAAO;AAAA,UAAG,QAAQ;AAAA,UAAe;AAC5D,cAAI,UAAU,KAAK,YAAY;AAC7B,sBAAU,cAAc;AACxB;AAAA,UACF;AACA,gBAAM,IAAI;AAAA,YACR;AAAA,YACA;AAAA,UACF;AAAA,QACF;AAEA,YAAI,CAAC,SAAS,IAAI;AAChB,gBAAM,cAAc,SAAS,WAAW,OAAO,SAAS,UAAU;AAClE,cAAI,eAAe,UAAU,KAAK,YAAY;AAC5C,gBAAI,SAAS,WAAW,KAAK;AAC3B,wBAAU;AAAA,gBACR,SAAS,QAAQ,IAAI,aAAa;AAAA,gBAClC;AAAA,gBACA;AAAA,cACF,IAAI;AAAA,YACN,OAAO;AACL,wBAAU,KAAK,IAAI,gBAAgB,KAAK,IAAI,GAAG,OAAO,GAAG,YAAY,IAAI,KAAK,OAAO,IAAI;AAAA,YAC3F;AACA,gBAAI;AAAE,oBAAM,SAAS,MAAM,OAAO;AAAA,YAAG,QAAQ;AAAA,YAAe;AAC5D;AAAA,UACF;AACA,gBAAM,KAAK,oBAAoB,QAAQ;AAAA,QACzC;AAEA,eAAQ,MAAM,SAAS,KAAK;AAAA,MAC9B,SAAS,OAAO;AACd,YAAI,iBAAiB,gBAAiB,OAAM;AAC5C,YAAI,iBAAiB,SAAS,MAAM,SAAS,cAAc;AACzD,gBAAM,IAAI,gBAAgB,2BAA2B,KAAK,OAAO,IAAI;AAAA,QACvE;AACA,cAAM,IAAI;AAAA,UACR,iBAAiB,QAAQ,MAAM,UAAU;AAAA,QAC3C;AAAA,MACF,UAAE;AACA,qBAAa,KAAK;AAAA,MACpB;AAAA,IACF;AAEA,UAAM,IAAI,gBAAgB,uBAAuB;AAAA,EACnD;AAAA;AAAA,EAGA,MAAM,KAAkB,MAAc,MAA2B;AAC/D,UAAM,MAAM,KAAK,SAAS,IAAI;AAC9B,UAAM,UAAkC;AAAA,MACtC,UAAU;AAAA,MACV,gBAAgB;AAAA,IAClB;AAEA,QAAI,KAAK,QAAQ;AACf,cAAQ,sBAAsB,IAAI,KAAK;AAAA,IACzC;AAEA,QAAI,OAAO,YAAY,eAAe,QAAQ,UAAU,MAAM;AAC5D,cAAQ,YAAY,IAAI,KAAK;AAAA,IAC/B;AAEA,UAAM,aAAa,IAAI,gBAAgB;AACvC,UAAM,QAAQ,WAAW,MAAM,WAAW,MAAM,GAAG,KAAK,OAAO;AAE/D,QAAI;AACF,YAAM,WAAW,MAAM,MAAM,KAAK;AAAA,QAChC,QAAQ;AAAA,QACR;AAAA,QACA,MAAM,KAAK,UAAU,IAAI;AAAA,QACzB,QAAQ,WAAW;AAAA,MACrB,CAAC;AAED,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,KAAK,oBAAoB,QAAQ;AAAA,MACzC;AAEA,aAAQ,MAAM,SAAS,KAAK;AAAA,IAC9B,SAAS,OAAO;AACd,UAAI,iBAAiB,gBAAiB,OAAM;AAC5C,UAAI,iBAAiB,SAAS,MAAM,SAAS,cAAc;AACzD,cAAM,IAAI,gBAAgB,2BAA2B,KAAK,OAAO,IAAI;AAAA,MACvE;AACA,YAAM,IAAI;AAAA,QACR,iBAAiB,QAAQ,MAAM,UAAU;AAAA,MAC3C;AAAA,IACF,UAAE;AACA,mBAAa,KAAK;AAAA,IACpB;AAAA,EACF;AAAA,EAEQ,SAAS,MAAc,QAAyB;AACtD,UAAM,MAAM,IAAI,IAAI,MAAM,KAAK,OAAO;AACtC,QAAI,QAAQ;AACV,iBAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,MAAiC,GAAG;AAC5E,YAAI,UAAU,UAAa,UAAU,MAAM;AACzC,cAAI,aAAa,IAAI,KAAK,OAAO,KAAK,CAAC;AAAA,QACzC;AAAA,MACF;AAAA,IACF;AACA,WAAO,IAAI,SAAS;AAAA,EACtB;AAAA,EAEA,MAAc,oBAAoB,UAAoC;AACpE,QAAI,OAA6C,CAAC;AAClD,QAAI;AACF,aAAO,MAAM,SAAS,KAAK;AAAA,IAC7B,QAAQ;AAAA,IAER;AAEA,UAAM,UAAU,KAAK,WAAW,SAAS,cAAc;AACvD,UAAM,OAAO,KAAK;AAElB,YAAQ,SAAS,QAAQ;AAAA,MACvB,KAAK;AAAA,MACL,KAAK;AACH,cAAM,IAAI,oBAAoB,SAAS,SAAS,QAAQ,IAAI;AAAA,MAC9D,KAAK;AACH,cAAM,IAAI,cAAc,SAAS,IAAI;AAAA,MACvC,KAAK,KAAK;AAGR,cAAM,aAAa;AAAA,UACjB,SAAS,QAAQ,IAAI,aAAa;AAAA,UAClC;AAAA,QACF;AACA,cAAM,IAAI,eAAe,SAAS,MAAM,UAAU;AAAA,MACpD;AAAA,MACA;AACE,cAAM,IAAI,SAAS,SAAS,SAAS,QAAQ,IAAI;AAAA,IACrD;AAAA,EACF;AACF;","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sentisense",
3
- "version": "0.44.0",
3
+ "version": "0.45.0",
4
4
  "description": "Official JavaScript/TypeScript SDK for the SentiSense market intelligence API",
5
5
  "author": "SentiSense <support@sentisense.ai>",
6
6
  "license": "MIT",