sentisense 0.47.2 → 0.49.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/README.md +33 -0
- package/dist/cli.cjs +84 -1
- package/dist/index.cjs +84 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +225 -2
- package/dist/index.d.ts +225 -2
- package/dist/index.mjs +84 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs.map
CHANGED
|
@@ -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/options.ts","../src/resources/screener.ts","../src/resources/stocks.ts","../src/resources/indexes.ts","../src/resources/trackers.ts","../src/version.ts","../src/client.ts"],"sourcesContent":["export { 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 StockSocialDominance,\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 OptionsHistory,\n OptionsHistoryWindow,\n GetOptionsHistoryOptions,\n OptionsOverview,\n OptionsOverviewRow,\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 { OptionsOverview, PreviewResponse } from \"../types.js\";\n\n/**\n * Market-wide options intelligence.\n *\n * Per-ticker options live on `client.stocks` (`getOptionsSummary`, `getOptionsHistory`),\n * next to everything else keyed by a symbol. This resource holds the surfaces that have no\n * ticker at all, the same split the market-wide mood and screener resources use.\n */\nexport class Options {\n constructor(private client: APIClient) {}\n\n /**\n * Get the market-wide options radar: where implied volatility, put/call flow and skew are\n * unusual today, ranked.\n *\n * End of day, not live. `asOf` is the latest completed session and the build refreshes the\n * following morning, so this is positioning, not a quote feed.\n *\n * **The response carries two separately-ranked boards.** `data.rows` is the covered stock\n * universe and `data.etfRows` is the covered ETF universe. Do not merge them: each row's\n * readings are percentiles of that ticker's own trailing history, so a rank built across\n * both boards compares numbers measured against different baselines. The aggregates are\n * split the same way, with the `etf`-prefixed fields describing the ETF board alone.\n *\n * `data` is `null` before the first nightly build populates it, which is a cold-start\n * state rather than an error.\n *\n * Tiering: a PRO key receives every row. A FREE key receives the top 25 stock rows plus\n * all the aggregates, with `isPreview` true and the envelope's `totalCount` reporting the\n * full stock board; `data.etfTotalCount` does the same for the ETF board.\n *\n * Drill into any row with `client.stocks.getOptionsSummary(ticker)` for its full dossier,\n * or `client.stocks.getOptionsHistory(ticker)` to chart how a reading has trended.\n */\n async getOverview(): Promise<PreviewResponse<OptionsOverview | null>> {\n return this.client.get(\"/api/v1/options/overview\");\n }\n}\n","import type { APIClient } from \"../client.js\";\nimport type {\n EtfScreenerExecuteResponse,\n EtfScreenerRow,\n FeaturedScreen,\n ScreenerExecuteOptions,\n ScreenerExecuteResponse,\n ScreenerFieldCatalog,\n ScreenerFieldDescriptor,\n ScreenerFieldOption,\n ScreenerFilter,\n ScreenerPlan,\n ScreenerRow,\n ScreenerScreensResponse,\n ScreenerSort,\n} from \"../types.js\";\n\n/**\n * Screener: filter the tracked universe on the SentiSense Score, attention,\n * analyst consensus, technicals and price in a single query. It is the one\n * surface where our own signals sit in the same `WHERE` clause as the market\n * data, which is the point: screening on analyst ratings alone is something a\n * dozen free tools do, screening on analyst ratings *where the Score disagrees*\n * is not.\n *\n * Every screen is a {@link ScreenerPlan}. Take one from {@link screens} or\n * build your own, then hand it to {@link run} or {@link runEtfs}.\n *\n * Three field semantics are worth knowing before you write a filter, because\n * guessing them wrong produces a screen that looks fine and means nothing:\n *\n * - **`ANALYST_RATING_MEAN` is inverted.** It is the vendor's 1-to-5 scale\n * where `1.0` is strong buy, so bullish is `LTE 2.5`, not `GTE`. Prefer\n * `ANALYST_BUY_RATIO_PCT`, which runs the intuitive direction.\n * - **`MA_CROSS_STATE` is ordinal**, not a percentage: `1` golden cross (50-day\n * above 200-day), `-1` death cross, `0` neither. Use `EQ`.\n * - **`SENTIMENT_DIRECTION` is the sign of the 7-day SentiSense Score**\n * (`1` / `0` / `-1`) with a neutral band of plus-or-minus 5. Despite the name\n * it is not sentiment polarity, and `0` matches only an exact zero, so it\n * returns almost nothing.\n *\n * The Score fields (`SENTI_SCORE_7D`, `SENTI_SCORE_1M`, `SCORE_CHANGE_7D`) are\n * the SentiSense Score, not polarity: unbounded, banded at 5 / 13 / 23 either\n * side of zero. Filter on those band edges, not on values like `0.5`, which\n * behave as \"any positive score\".\n *\n * Nulls never match, in either direction: `RETURN_1Y >= 0` and `RETURN_1Y < 0`\n * do not partition the universe, because a stock listed four months ago is in\n * neither result. If a screen returns fewer rows than you expect, check\n * coverage before you check your thresholds.\n *\n * Screens read a snapshot that refreshes every 20 minutes, so this is not a\n * quote feed. Use `client.stocks.getQuote()` for live prices.\n */\nexport class Screener {\n constructor(private client: APIClient) {}\n\n /**\n * Every filterable field, with its unit, operators and description, for both\n * universes.\n *\n * Build a filter UI from this rather than hardcoding the list and you inherit\n * new fields as they ship. The ETF `STRING` fields (`ISSUER`, `ASSET_CLASS`,\n * `TRACKED_INDEX`) come back with their `values` populated from the live\n * universe, so pickers stay current without a redeploy.\n */\n async fields(): Promise<ScreenerFieldCatalog> {\n return this.client.get(\"/api/v1/screener/fields\");\n }\n\n /**\n * The curated screens shipped in the product, each with a runnable plan.\n *\n * Each `plan` round-trips straight into {@link run} (or {@link runEtfs} when\n * `plan.universe === \"ETF\"`) with nothing to rebuild.\n *\n * Their filters identify the field with `field` rather than `fieldName`.\n * Both keys are accepted on the way in, so read either when inspecting a plan\n * you did not build yourself.\n */\n async screens(): Promise<ScreenerScreensResponse> {\n return this.client.get(\"/api/v1/screener/screens\");\n }\n\n /**\n * Run a screen against the stock universe.\n *\n * `tickers` is optional: omit it to screen the whole tracked universe, pass a\n * list to screen a watchlist. `limit` sits next to the plan rather than\n * inside it, because a plan is a stored object and paging is a transport\n * concern; it defaults to 100 and caps at 500.\n *\n * Read `matched` before you read `results`: it is the count before `limit`\n * was applied, so a `matched` above your `limit` means you are holding the\n * top slice under the plan's sort, not the whole answer.\n *\n * @example\n * ```ts\n * const res = await client.screener.run({\n * plan: {\n * filters: [\n * { fieldName: \"SENTI_SCORE_7D\", op: \"GTE\", value: 13 },\n * { fieldName: \"ANALYST_BUY_RATIO_PCT\", op: \"LTE\", value: 30 },\n * { fieldName: \"ANALYST_COUNT\", op: \"GTE\", value: 5 },\n * ],\n * sort: { fieldName: \"SENTI_SCORE_7D\", dir: \"DESC\" },\n * },\n * limit: 25,\n * });\n * ```\n */\n async run(options: ScreenerExecuteOptions): Promise<ScreenerExecuteResponse> {\n return this.client.post(\"/api/v1/screener/execute\", options);\n }\n\n /**\n * Run a screen against the ETF universe.\n *\n * Same request shape as {@link run}, against a different field vocabulary:\n * take the ETF names from `fields().etf`. `IN` / `NOT_IN` take a `values`\n * array instead of `value` and are the operators for the string fields\n * (`ISSUER`, `ASSET_CLASS`, `TRACKED_INDEX`).\n *\n * `CONSTITUENTS_WEIGHTED_SENTISENSE` is the holdings-weighted SentiSense\n * Score across what the fund owns and is usually the one you want;\n * `DIRECT_SENTISENSE` is the Score from chatter about the fund ticker itself,\n * which on a broad index fund is mostly macro noise. `WEIGHT_COVERED_PCT`\n * tells you how much of the fund's weight had constituent data behind the\n * weighted number.\n */\n async runEtfs(options: ScreenerExecuteOptions): Promise<EtfScreenerExecuteResponse> {\n return this.client.post(\"/api/v1/screener/etfs/execute\", options);\n }\n}\n\n// Re-export for convenience so callers can `import type { ScreenerPlan }`\n// from the resource module instead of `../types`.\nexport type {\n EtfScreenerExecuteResponse,\n EtfScreenerRow,\n FeaturedScreen,\n ScreenerExecuteOptions,\n ScreenerExecuteResponse,\n ScreenerFieldCatalog,\n ScreenerFieldDescriptor,\n ScreenerFieldOption,\n ScreenerFilter,\n ScreenerPlan,\n ScreenerRow,\n ScreenerScreensResponse,\n ScreenerSort,\n};\n","import type { APIClient } from \"../client.js\";\nimport type {\n AISummary,\n ChartData,\n ChartDataPoint,\n CompanyKpisData,\n FloatInfo,\n Fundamentals,\n FundamentalsPeriodsResponse,\n TtmFundamentals,\n GetAISummaryOptions,\n GetChartOptions,\n GetDescriptionsOptions,\n GetFundamentalsOptions,\n GetImagesOptions,\n GetMetricsBreakdownOptions,\n GetProfileOptions,\n GetOptionsHistoryOptions,\n GetSimilarOptions,\n KpiCoverageResponse,\n KpiTypeEntry,\n MarketStatus,\n MetricsBreakdown,\n OptionsHistory,\n OptionsSummary,\n PreviewResponse,\n SimilarStock,\n ShortInterest,\n ShortVolume,\n StockDetail,\n StockEntity,\n StockSentiment,\n StockImage,\n StockPrice,\n StockProfile,\n StockQuote,\n} from \"../types.js\";\n\n/**\n * Fill the legacy `name` alias from the fields the API actually sends.\n *\n * `/stocks/detailed` and `/stocks/popular/detailed` return `simpleName` and\n * `companyName`; they have never sent `name`. Callers reading `.name` got\n * `undefined`, so it is backfilled here rather than left to crash.\n */\nfunction withLegacyName(rows: StockDetail[]): StockDetail[] {\n if (!Array.isArray(rows)) return rows;\n return rows.map((row) =>\n row && !row.name ? { ...row, name: row.simpleName || row.companyName || \"\" } : row,\n );\n}\n\nexport class Stocks {\n constructor(private client: APIClient) {}\n\n /** List all available ticker symbols. */\n async list(): Promise<string[]> {\n return this.client.get(\"/api/v1/stocks\");\n }\n\n /** List all stocks with company names, kbEntityId, urlSlug. */\n async listDetailed(): Promise<StockDetail[]> {\n const rows = await this.client.get<StockDetail[]>(\"/api/v1/stocks/detailed\");\n return withLegacyName(rows);\n }\n\n /** Get popular ticker symbols. */\n async listPopular(): Promise<string[]> {\n return this.client.get(\"/api/v1/stocks/popular\");\n }\n\n /** Get popular stocks with details. */\n async listPopularDetailed(): Promise<StockDetail[]> {\n const rows = await this.client.get<StockDetail[]>(\"/api/v1/stocks/popular/detailed\");\n return withLegacyName(rows);\n }\n\n /** Get real-time price for a single ticker. */\n async getPrice(ticker: string): Promise<StockPrice> {\n return this.client.get(\"/api/v1/stocks/price\", { ticker });\n }\n\n /**\n * Get aggregate quote snapshot: live price, today OHLC, 52-week range,\n * market cap, P/E, EPS TTM, and dividend yield in a single call.\n * All fields except `ticker` may be null when upstream data is unavailable.\n */\n async getQuote(ticker: string): Promise<StockQuote> {\n return this.client.get(`/api/v1/stocks/${encodeURIComponent(ticker)}/quote`);\n }\n\n /** Get real-time prices for multiple tickers. */\n async getPrices(tickers: string[]): Promise<StockPrice[]> {\n return this.client.get(\"/api/v1/stocks/prices\", {\n tickers: tickers.join(\",\"),\n });\n }\n\n /** Get batch company logo URLs. */\n async getImages(\n tickers: string[],\n options?: GetImagesOptions,\n ): Promise<Record<string, StockImage>> {\n return this.client.get(\"/api/v1/stocks/images\", {\n tickers: tickers.join(\",\"),\n ...options,\n });\n }\n\n /** Get company profiles with branding, market cap, sector. */\n async getDescriptions(\n tickers: string[],\n options?: GetDescriptionsOptions,\n ): Promise<Record<string, StockProfile>> {\n return this.client.get(\"/api/v1/stocks/descriptions\", {\n tickers: tickers.join(\",\"),\n ...options,\n });\n }\n\n /** Get peer/similar stocks. */\n async getSimilar(ticker: string, options?: GetSimilarOptions): Promise<SimilarStock[]> {\n return this.client.get(`/api/v1/stocks/${encodeURIComponent(ticker)}/similar`, options);\n }\n\n /** Get company profile (CEO, sector, industry, market data). */\n async getProfile(ticker: string, options?: GetProfileOptions): Promise<StockProfile> {\n return this.client.get(`/api/v1/stocks/${encodeURIComponent(ticker)}/profile`, options);\n }\n\n /**\n * Get the headline sentiment picture for a stock in one call.\n *\n * Returns the SentiSense Score with its 30-day regime, mention volume and social\n * dominance, per-source tone in `bySource`, plus related tickers, story drivers, a\n * narrative and an FAQ. Available in full on every API-key tier.\n *\n * Use `entityMetrics.getMetrics(ticker, \"sentiment\", ...)` instead when you need a time\n * series over a specific window rather than the headline read. Returns 404 for tickers\n * with no sentiment coverage.\n */\n async getSentiment(ticker: string): Promise<PreviewResponse<StockSentiment>> {\n return this.client.get(\n `/api/v1/stocks/${encodeURIComponent(ticker)}/sentiment`,\n );\n }\n\n /** Get related KB entities (people, products, partners). */\n async getEntities(ticker: string): Promise<StockEntity[]> {\n return this.client.get(`/api/v1/stocks/${encodeURIComponent(ticker)}/entities`);\n }\n\n /**\n * Get AI-generated stock analysis report. Requires PRO tier.\n *\n * `depth: \"deep\"` returns the full curated report and consumes one report view on\n * metered tiers; the default `\"basic\"` returns the one-paragraph summary.\n *\n * The deprecated `forceRefresh` option is accepted and discarded, not forwarded.\n */\n async getAISummary(ticker: string, options?: GetAISummaryOptions): Promise<AISummary> {\n const { forceRefresh: _forceRefresh, ...params } = options ?? {};\n return this.client.get(`/api/v1/stocks/${encodeURIComponent(ticker)}/ai-summary`, params);\n }\n\n /** Get sentiment/mention metrics breakdown by entity. */\n async getMetricsBreakdown(\n ticker: string,\n metricType: string,\n options?: GetMetricsBreakdownOptions,\n ): Promise<MetricsBreakdown> {\n return this.client.get(\n `/api/v1/stocks/${encodeURIComponent(ticker)}/metrics/${encodeURIComponent(metricType)}/breakdown`,\n options,\n );\n }\n\n /**\n * Get historical OHLCV chart data.\n *\n * The API returns a bare array of points; this normalizes it to\n * `{ ticker, timeframe, data }`. `timeframe` echoes the requested value\n * (defaulting to \"1M\", matching the server default when omitted).\n */\n async getChart(ticker: string, options?: GetChartOptions): Promise<ChartData> {\n const data = await this.client.get<ChartDataPoint[]>(\"/api/v1/stocks/chart\", {\n ticker,\n ...options,\n });\n return { ticker, timeframe: options?.timeframe ?? \"1M\", data };\n }\n\n /** Get current market open/closed/pre-market/after-hours status. */\n async getMarketStatus(): Promise<MarketStatus> {\n return this.client.get(\"/api/v1/stocks/market-status\");\n }\n\n /**\n * Get financial statement data for one reporting period: income statement, balance sheet,\n * and cash flow, including `capitalExpenditure` and `freeCashFlow`.\n *\n * Capital expenditure is signed as filed, so normally negative. See {@link Fundamentals}\n * for the free-cash-flow relationship and when it is `null`.\n */\n async getFundamentals(ticker: string, options?: GetFundamentalsOptions): Promise<Fundamentals> {\n return this.client.get(\"/api/v1/stocks/fundamentals\", { ticker, ...options });\n }\n\n /** Get available fiscal periods. The periods are in `periods`. */\n async getFundamentalsPeriods(ticker: string): Promise<FundamentalsPeriodsResponse> {\n return this.client.get(\"/api/v1/stocks/fundamentals/periods\", { ticker });\n }\n\n /**\n * Get the trailing-twelve-month fundamentals snapshot: TTM ratios, a different\n * shape from the per-period statement data `getFundamentals()` returns.\n */\n async getCurrentFundamentals(ticker: string): Promise<TtmFundamentals> {\n return this.client.get(\"/api/v1/stocks/fundamentals/current\", { ticker });\n }\n\n /** Get historical revenue data. */\n async getHistoricalRevenue(ticker: string): Promise<unknown> {\n return this.client.get(\"/api/v1/stocks/fundamentals/historical/revenue\", { ticker });\n }\n\n /** Get short interest metrics (FINRA). */\n async getShortInterest(ticker: string): Promise<ShortInterest> {\n return this.client.get(\"/api/v1/stocks/short-interest\", { ticker });\n }\n\n /** Get float information. */\n async getFloat(ticker: string): Promise<FloatInfo> {\n return this.client.get(\"/api/v1/stocks/float\", { ticker });\n }\n\n /** Get short volume trading data. */\n async getShortVolume(ticker: string): Promise<ShortVolume> {\n return this.client.get(\"/api/v1/stocks/short-volume\", { ticker });\n }\n\n /**\n * Get company-specific KPI time-series for a ticker. Returns curated GAAP and\n * non-GAAP metrics from earnings filings (e.g. iPhone unit sales, Tesla deliveries,\n * AWS revenue).\n *\n * Free users receive metadata only with an empty `kpis` list; PRO users receive\n * the full series. Returns 404 for tickers that do not yet have curated coverage.\n *\n * Coverage today: near-complete for the S&P 500 plus extended universe\n * (~500 tickers). Use `listKpiCoverage()` to enumerate.\n */\n async getKpis(ticker: string): Promise<PreviewResponse<CompanyKpisData>> {\n return this.client.get(\n `/api/v1/stocks/${encodeURIComponent(ticker.toUpperCase())}/kpis`,\n );\n }\n\n /**\n * List every ticker with curated KPI coverage. Returns `{count, tickers: [...]}`\n * with lightweight metadata (ticker, companyName, lastUpdated, kpiCount).\n * Sorted alphabetically by ticker.\n *\n * Auth: API key required, but the call does NOT consume your monthly quota\n * (rate-limit-per-minute still applies).\n */\n async listKpiCoverage(): Promise<KpiCoverageResponse> {\n return this.client.get(\"/api/v1/stocks/with-kpis\");\n }\n\n /**\n * List the KPI metadata tuples available for a ticker (`id, name, category,\n * chartType`) without paying the cost of the full series payload. Mirrors\n * the `/api/v1/insights/stock/{ticker}/types` precedent.\n *\n * Auth: API key required, no quota cost. 404 if the ticker has no curated KPIs.\n */\n async getKpiTypes(ticker: string): Promise<KpiTypeEntry[]> {\n return this.client.get(\n `/api/v1/stocks/${encodeURIComponent(ticker.toUpperCase())}/kpis/types`,\n );\n }\n\n /**\n * Get the end-of-day options dossier for one stock or ETF: the session's aggregate, its\n * percentile context, the open-interest wall structure with max pain, and the contracts\n * whose volume ran far ahead of their open interest.\n *\n * End of day, not live. `asOf` is the prior trading session and the data refreshes the\n * following morning, so this is positioning, not a quote feed.\n *\n * **`data` is `null` for a ticker outside the covered universe**, which is the most\n * actively optioned US names plus the tracked ETFs, and for a covered ticker with no\n * snapshot yet. An unknown symbol behaves the same way rather than answering 404, so treat\n * a null as \"no coverage\", never as an error. A covered ticker still building its baseline\n * returns its raw readings with the percentiles omitted.\n *\n * Percentiles compare a ticker to its own trailing history, never to another ticker, so an\n * ETF's readings are not comparable with a single stock's.\n *\n * Tiering: a PRO key always receives the full dossier. A FREE key receives it for the first\n * ten calls each calendar month and a headline-only preview after that, with `isPreview`\n * true; calls that return a null `data` never spend that allowance.\n */\n async getOptionsSummary(ticker: string): Promise<PreviewResponse<OptionsSummary | null>> {\n return this.client.get(\n `/api/v1/stocks/${encodeURIComponent(ticker.toUpperCase())}/options/summary`,\n );\n }\n\n /**\n * Get the daily options aggregates for one stock or ETF as a time series, oldest first.\n * Use it to chart how a reading has trended: implied volatility, put/call flow, skew.\n *\n * Each element has the same shape as the dossier's `latest` aggregate, so a chart built\n * off `getOptionsSummary` reads this series without a second mapping.\n *\n * **A null payload is not how this one reports no coverage.** Unlike\n * {@link Stocks.getOptionsSummary}, an uncovered ticker, an unknown symbol and a covered\n * ticker with nothing stored yet all answer with a populated object whose `series` is\n * empty. Check the array's length, not the payload.\n *\n * The window served is not always the window requested: an unrecognised value clamps to\n * `\"1y\"` rather than erroring, and a FREE key always receives `\"1y\"`. Read `data.window`\n * for what you actually got. `\"5y\"` means all stored history, currently a little over two\n * years, so it can answer with nearly the same series as `\"2y\"`.\n */\n async getOptionsHistory(\n ticker: string,\n options?: GetOptionsHistoryOptions,\n ): Promise<PreviewResponse<OptionsHistory>> {\n return this.client.get(\n `/api/v1/stocks/${encodeURIComponent(ticker.toUpperCase())}/options/history`,\n options,\n );\n }\n}\n","import type { APIClient } from \"../client.js\";\nimport type {\n IndexConstituent,\n IndexHistoryPoint,\n IndexHistoryResponse,\n IndexListing,\n IndexListResponse,\n IndexSnapshot,\n} from \"../types.js\";\n\n/**\n * Indexes: composite scalars tracked over time, each blending its own inputs\n * into one number on a stated scale. Every index answers on the same envelope,\n * so you write one renderer and get every current and future SentiSense index.\n *\n * Two archetypes share that envelope. A **basket** index weight-averages\n * tracked entities and fills `constituents` / `basketSize` / `coverage` /\n * `totalMentions`; a **composite** index is built from signals instead and\n * returns `null` for all four by construction. See {@link IndexSnapshot}.\n *\n * @see IndexSnapshot\n */\nexport class Indexes {\n constructor(private client: APIClient) {}\n\n /**\n * List every index the platform publishes: id, display name, one-line\n * description, the scale it lives on, its access tier, and where its richest\n * view lives.\n *\n * Iterate this rather than hardcoding ids. Every `indexId` it advertises\n * resolves on {@link get} and {@link history}.\n */\n async list(): Promise<IndexListResponse> {\n return this.client.get(\"/api/v1/indexes\");\n }\n\n /**\n * Latest reading for one index.\n *\n * Check `constituents` for `null` before iterating: it is `null` on a\n * composite index like `market-mood`, which has no constituents by\n * construction. For Market Mood this is the narrowed view; the phase band,\n * weekly change, per-signal breakdown and per-sector map live on\n * `client.marketMood.get()`, and both report the same headline number.\n *\n * @param indexId slug from {@link list}, e.g. `\"fed-sentiment\"`.\n */\n async get(indexId: string): Promise<IndexSnapshot> {\n return this.client.get(`/api/v1/indexes/${indexId}`);\n }\n\n /**\n * Historical scalar series for one index, for charting.\n *\n * Thin or low-coverage buckets are withheld, so the series can be shorter\n * than `days` and can contain gaps. Plot against each point's `date`.\n *\n * @param indexId slug from {@link list}.\n * @param days days of history to return. Defaults to the API's own 180.\n */\n async history(indexId: string, days?: number): Promise<IndexHistoryResponse> {\n return this.client.get(\n `/api/v1/indexes/${indexId}/history`,\n days === undefined ? undefined : { days },\n );\n }\n}\n\n// Re-export for convenience so callers can `import type { IndexListing }`\n// from the resource module instead of `../types`.\nexport type {\n IndexConstituent,\n IndexHistoryPoint,\n IndexHistoryResponse,\n IndexListing,\n IndexListResponse,\n IndexSnapshot,\n};\n","import type { APIClient } from \"../client.js\";\nimport type {\n TrackerListing,\n TrackerListResponse,\n TrackerSnapshot,\n TrackerSnapshotResponse,\n} from \"../types.js\";\n\n/**\n * Trackers: observational data products published as a standardized\n * `TrackerSnapshot` envelope. Every tracker (institution rankings,\n * hedge-fund reported returns, social trackers, surveillance dashboards)\n * returns the same shape, so consumers write one renderer per `viewType` and\n * get every current and future SentiSense tracker for free.\n *\n * @see TrackerSnapshot\n */\nexport class Trackers {\n constructor(private client: APIClient) {}\n\n /**\n * List every publicly-visible tracker: id, display name, category,\n * one-line description, and the methodology anchor to link out to.\n */\n async list(): Promise<TrackerListResponse> {\n return this.client.get(\"/api/v1/trackers\");\n }\n\n /**\n * Standardized snapshot envelope for one tracker.\n *\n * Returns the envelope as-is: `{ isPreview, previewReason, totalCount?, data }`.\n * When `data.viewType === \"table\"` the rows live at `data.rows[]`; when\n * `\"choropleth\"` they live at `data.geo[]`; etc. Dispatch on `viewType`\n * in your renderer.\n *\n * @param trackerId slug from {@link list}, e.g. `\"institution-concentration\"`.\n * @param params provider-specific query params (e.g. `{ scope: \"us\" }` for\n * geographically-scoped trackers like hantavirus). Unknown keys are ignored.\n */\n async get(\n trackerId: string,\n params?: Record<string, string | number | boolean>,\n ): Promise<TrackerSnapshotResponse> {\n return this.client.get(`/api/v1/trackers/${trackerId}`, params);\n }\n}\n\n// Re-export for convenience so callers can `import type { TrackerListing }`\n// from the resource module instead of `../types`.\nexport type {\n TrackerListing,\n TrackerListResponse,\n TrackerSnapshot,\n TrackerSnapshotResponse,\n};\n","export const VERSION = \"0.47.1\";\n","import {\n APIError,\n AuthenticationError,\n DeepHistoryUnavailableError,\n NotFoundError,\n RateLimitError,\n SentiSenseError,\n} from \"./errors.js\";\nimport { Analyst } from \"./resources/analyst.js\";\nimport { Calendar } from \"./resources/calendar.js\";\nimport { Documents } from \"./resources/documents.js\";\nimport { Earnings } from \"./resources/earnings.js\";\nimport { EntityMetrics } from \"./resources/entityMetrics.js\";\nimport { Etfs } from \"./resources/etfs.js\";\nimport { Insider } from \"./resources/insider.js\";\nimport { Politicians } from \"./resources/politicians.js\";\nimport { Insights } from \"./resources/insights.js\";\nimport { Institutional } from \"./resources/institutional.js\";\nimport { KB } from \"./resources/kb.js\";\nimport { MarketMoodResource } from \"./resources/marketMood.js\";\nimport { MarketSummaryResource } from \"./resources/marketSummary.js\";\nimport { Options } from \"./resources/options.js\";\nimport { Screener } from \"./resources/screener.js\";\nimport { Stocks } from \"./resources/stocks.js\";\nimport { Indexes } from \"./resources/indexes.js\";\nimport { Trackers } from \"./resources/trackers.js\";\nimport type { SentiSenseOptions } from \"./types.js\";\nimport { VERSION } from \"./version.js\";\n\nconst DEFAULT_BASE_URL = \"https://app.sentisense.ai\";\nconst DEFAULT_TIMEOUT = 30_000;\nconst DEFAULT_MAX_RETRIES = 3;\nconst BASE_DELAY_MS = 1_000;\nconst MAX_DELAY_MS = 60_000;\n// Used when a 202 arrives without a usable Retry-After header.\nconst DEEP_HISTORY_FALLBACK_WAIT_S = 3;\n\n// Upper bounds on any server-supplied Retry-After. Rate limiting gets the longer ceiling\n// because a genuine limit window is legitimately minutes, while a deep-history warm-up is\n// seconds. Without a ceiling an oversized header value strands the caller indefinitely.\nconst MAX_DEEP_HISTORY_WAIT_S = 30;\nconst MAX_RATE_LIMIT_WAIT_S = 120;\nconst RATE_LIMIT_FALLBACK_WAIT_S = 60;\n\n/**\n * A `Retry-After` header as a usable number of seconds, clamped to `[0.5, maxWaitS]`, or\n * `undefined` when there is no usable value.\n *\n * `Retry-After` is vendor-controlled and may legally carry an HTTP-date rather than a\n * number of seconds, in which case parsing yields `NaN`. Left unguarded that produced a\n * `NaN` delay which compared false against every threshold and retried instantly in a busy\n * loop, and a `NaN` on the error object that silently broke a caller's own backoff.\n * Anything that is not a finite number is treated as absent.\n */\nfunction clampRetryAfter(\n raw: string | null,\n maxWaitS: number,\n): number | undefined {\n if (!raw) return undefined;\n const parsed = Number(raw);\n if (!Number.isFinite(parsed)) return undefined;\n return Math.min(Math.max(0.5, parsed), maxWaitS);\n}\n\n/** Same clamp, resolved to `defaultS` when the header gives us nothing to go on. */\nfunction retryAfterSeconds(\n raw: string | null,\n defaultS: number,\n maxWaitS: number,\n): number {\n return clampRetryAfter(raw, maxWaitS) ?? defaultS;\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/** @internal HTTP interface exposed to resource classes. */\nexport interface APIClient {\n get<T = unknown>(path: string, params?: object): Promise<T>;\n post<T = unknown>(path: string, body: unknown): Promise<T>;\n}\n\nexport class SentiSense implements APIClient {\n private baseUrl: string;\n private apiKey: string | undefined;\n private timeout: number;\n private maxRetries: number;\n private userAgent: string;\n\n readonly stocks: Stocks;\n readonly documents: Documents;\n readonly etfs: Etfs;\n readonly institutional: Institutional;\n readonly insider: Insider;\n readonly politicians: Politicians;\n readonly insights: Insights;\n readonly analyst: Analyst;\n readonly entityMetrics: EntityMetrics;\n readonly marketMood: MarketMoodResource;\n readonly marketSummary: MarketSummaryResource;\n readonly kb: KB;\n readonly indexes: Indexes;\n readonly trackers: Trackers;\n readonly calendar: Calendar;\n readonly earnings: Earnings;\n readonly screener: Screener;\n readonly options: Options;\n\n constructor(options: SentiSenseOptions = {}) {\n this.apiKey = options.apiKey;\n this.baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\\/+$/, \"\");\n this.timeout = options.timeout ?? DEFAULT_TIMEOUT;\n this.maxRetries = options.maxRetries ?? DEFAULT_MAX_RETRIES;\n // A header value cannot carry CR/LF, so collapse them rather than letting a caller's\n // string decide where the header block ends.\n const suffix = options.userAgentSuffix?.replace(/[\\r\\n]+/g, \" \").trim();\n this.userAgent = suffix\n ? `sentisense-node/${VERSION} ${suffix}`\n : `sentisense-node/${VERSION}`;\n\n this.stocks = new Stocks(this);\n this.documents = new Documents(this);\n this.etfs = new Etfs(this);\n this.institutional = new Institutional(this);\n this.insider = new Insider(this);\n this.politicians = new Politicians(this);\n this.insights = new Insights(this);\n this.analyst = new Analyst(this);\n this.entityMetrics = new EntityMetrics(this);\n this.marketMood = new MarketMoodResource(this);\n this.marketSummary = new MarketSummaryResource(this);\n this.kb = new KB(this);\n this.indexes = new Indexes(this);\n this.trackers = new Trackers(this);\n this.calendar = new Calendar(this);\n this.earnings = new Earnings(this);\n this.screener = new Screener(this);\n this.options = new Options(this);\n }\n\n /** @internal */\n async get<T = unknown>(path: string, params?: object): Promise<T> {\n const url = this.buildUrl(path, params);\n const headers: Record<string, string> = {\n \"Accept\": \"application/json\",\n };\n\n if (this.apiKey) {\n headers[\"X-SentiSense-API-Key\"] = this.apiKey;\n }\n\n // User-Agent is only set in Node.js (browsers disallow it)\n if (typeof process !== \"undefined\" && process.versions?.node) {\n headers[\"User-Agent\"] = this.userAgent;\n }\n\n let delayMs = 0;\n\n for (let attempt = 0; attempt <= this.maxRetries; attempt++) {\n if (delayMs > 0) {\n await sleep(delayMs);\n delayMs = 0;\n }\n\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await fetch(url, {\n method: \"GET\",\n headers,\n signal: controller.signal,\n });\n\n // 202 means a deep chart range is still being built server-side. It is a 2xx, so\n // without this it would fall through and return an empty array: the caller would\n // see \"no data\" rather than \"not ready yet\", which is the exact confusion the\n // status code exists to prevent. Retry honouring Retry-After, then surface it.\n if (response.status === 202) {\n const waitSeconds = retryAfterSeconds(\n response.headers.get(\"Retry-After\"),\n DEEP_HISTORY_FALLBACK_WAIT_S,\n MAX_DEEP_HISTORY_WAIT_S,\n );\n try { await response.body?.cancel(); } catch { /* ignore */ }\n if (attempt < this.maxRetries) {\n delayMs = waitSeconds * 1000;\n continue;\n }\n throw new DeepHistoryUnavailableError(\n \"Deep history is still being assembled. Retry in a few seconds.\",\n waitSeconds,\n );\n }\n\n if (!response.ok) {\n const isRetryable = response.status === 429 || response.status >= 500;\n if (isRetryable && attempt < this.maxRetries) {\n if (response.status === 429) {\n delayMs = retryAfterSeconds(\n response.headers.get(\"Retry-After\"),\n RATE_LIMIT_FALLBACK_WAIT_S,\n MAX_RATE_LIMIT_WAIT_S,\n ) * 1000;\n } else {\n delayMs = Math.min(BASE_DELAY_MS * Math.pow(2, attempt), MAX_DELAY_MS) + Math.random() * 1000;\n }\n try { await response.body?.cancel(); } catch { /* ignore */ }\n continue;\n }\n await this.handleErrorResponse(response);\n }\n\n return (await response.json()) as T;\n } catch (error) {\n if (error instanceof SentiSenseError) throw error;\n if (error instanceof Error && error.name === \"AbortError\") {\n throw new SentiSenseError(`Request timed out after ${this.timeout}ms`);\n }\n throw new SentiSenseError(\n error instanceof Error ? error.message : \"Unknown error\",\n );\n } finally {\n clearTimeout(timer);\n }\n }\n\n throw new SentiSenseError(\"All retries exhausted\");\n }\n\n /** @internal */\n async post<T = unknown>(path: string, body: unknown): Promise<T> {\n const url = this.buildUrl(path);\n const headers: Record<string, string> = {\n \"Accept\": \"application/json\",\n \"Content-Type\": \"application/json\",\n };\n\n if (this.apiKey) {\n headers[\"X-SentiSense-API-Key\"] = this.apiKey;\n }\n\n if (typeof process !== \"undefined\" && process.versions?.node) {\n headers[\"User-Agent\"] = this.userAgent;\n }\n\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await fetch(url, {\n method: \"POST\",\n headers,\n body: JSON.stringify(body),\n signal: controller.signal,\n });\n\n if (!response.ok) {\n await this.handleErrorResponse(response);\n }\n\n return (await response.json()) as T;\n } catch (error) {\n if (error instanceof SentiSenseError) throw error;\n if (error instanceof Error && error.name === \"AbortError\") {\n throw new SentiSenseError(`Request timed out after ${this.timeout}ms`);\n }\n throw new SentiSenseError(\n error instanceof Error ? error.message : \"Unknown error\",\n );\n } finally {\n clearTimeout(timer);\n }\n }\n\n private buildUrl(path: string, params?: object): string {\n const url = new URL(path, this.baseUrl);\n if (params) {\n for (const [key, value] of Object.entries(params as Record<string, unknown>)) {\n if (value !== undefined && value !== null) {\n url.searchParams.set(key, String(value));\n }\n }\n }\n return url.toString();\n }\n\n private async handleErrorResponse(response: Response): Promise<never> {\n let body: { error?: string; message?: string } = {};\n try {\n body = await response.json();\n } catch {\n // Response may not be JSON\n }\n\n const message = body.message ?? response.statusText ?? \"API request failed\";\n const code = body.error;\n\n switch (response.status) {\n case 401:\n case 403:\n throw new AuthenticationError(message, response.status, code);\n case 404:\n throw new NotFoundError(message, code);\n case 429: {\n // Same clamp the retry loop uses, so a caller running its own backoff off\n // `error.retryAfter` gets a number it can pass to setTimeout, or nothing at all.\n const retryAfter = clampRetryAfter(\n response.headers.get(\"Retry-After\"),\n MAX_RATE_LIMIT_WAIT_S,\n );\n throw new RateLimitError(message, code, retryAfter);\n }\n default:\n throw new APIError(message, response.status, code);\n }\n }\n}\n"],"mappings":"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","names":[]}
|
|
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/options.ts","../src/resources/screener.ts","../src/resources/stocks.ts","../src/resources/indexes.ts","../src/resources/trackers.ts","../src/version.ts","../src/client.ts"],"sourcesContent":["export { 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 AnalystNote,\n AnalystFirmRating,\n AnalystCoverageAnalyst,\n AnalystCoverageFirm,\n AnalystCoverage,\n AnalystFirmTenure,\n AnalystCoverageBookEntry,\n AnalystProfile,\n AnalystCall,\n GetAnalystActionsOptions,\n GetAnalystMarketActivityOptions,\n GetAnalystCoverageOptions,\n GetAnalystCallsOptions,\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 StockSocialDominance,\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 OptionsHistory,\n OptionsHistoryWindow,\n GetOptionsHistoryOptions,\n OptionsOverview,\n OptionsOverviewRow,\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/** One price target note. */\nexport interface AnalystNote {\n /** ISO date the note was published, `\"YYYY-MM-DD\"`. */\n publishedDate: string;\n /**\n * The individual named on the note, or `null` when the report named nobody.\n * Absent means the report did not identify one, never that the note did not happen.\n */\n analyst: string | null;\n priceTarget: number | null;\n adjPriceTarget: number | null;\n priceWhenPosted: number | null;\n newsTitle: string | null;\n newsUrl: string | null;\n newsPublisher: string | null;\n}\n\n/** A firm's most recent rating action. Published at firm level, with no individual attached. */\nexport interface AnalystFirmRating {\n rating: string | null;\n priorRating: string | null;\n /** UPGRADE, DOWNGRADE, INITIATE, REITERATE, OTHER */\n actionType: string | null;\n /** ISO date of the action, `\"YYYY-MM-DD\"`. */\n date: string | null;\n}\n\n/** A named analyst on a firm's desk, as it appears on a coverage row. */\nexport interface AnalystCoverageAnalyst {\n /**\n * Addresses `analyst.profile(slug)` and `analyst.calls(slug)`. `null` for a named\n * analyst we hold no profile for; the row keeps the `name` rather than being dropped.\n */\n slug: string | null;\n name: string;\n noteCount: number;\n firstNote: string | null;\n lastNote: string | null;\n latestPriceTarget: number | null;\n}\n\n/** One firm covering the ticker. */\nexport interface AnalystCoverageFirm {\n firm: string;\n /** Individuals we can name on this desk. Possibly empty: not every note names one. */\n analysts: AnalystCoverageAnalyst[];\n /** This firm's price target notes in the window. `0` on a rating-only firm. */\n noteCount: number;\n attributedNoteCount: number;\n unattributedNoteCount: number;\n /** ISO dates bounding this firm's notes. `null` on a rating-only firm. */\n firstNote: string | null;\n lastNote: string | null;\n /** The firm's most recent note. `null` on a rating-only firm, so read `noteCount` first. */\n latestNote: AnalystNote | null;\n firmRating: AnalystFirmRating | null;\n}\n\nexport interface AnalystCoverage {\n ticker: string;\n /** Window actually applied after clamping, in days. */\n windowDays: number;\n /** ISO date the response was built. */\n asOf: string;\n /** Firms with at least one note **or** one rating action in the window. */\n firmCount: number;\n /**\n * How many of `firmCount` appear on a rating action alone. Firms that published a\n * target are `firmCount - ratingOnlyFirmCount`.\n */\n ratingOnlyFirmCount: number;\n namedAnalystCount: number;\n noteCount: number;\n /** Notes that name an individual. */\n attributedNoteCount: number;\n /** Notes that name no individual. */\n unattributedNoteCount: number;\n /** Plain-language statement of what an absent name means. */\n attributionNote: string;\n /** Firm rows, most recently active first. PRO: all. FREE: 5. */\n coverage: AnalystCoverageFirm[];\n}\n\n/** One firm an analyst has published under. */\nexport interface AnalystFirmTenure {\n firm: string;\n /** ISO date of the earliest note we hold from this analyst at this firm. */\n firstSeen: string;\n /** ISO date of the most recent one. */\n lastSeen: string;\n mostRecent: boolean;\n}\n\n/** One ticker in an analyst's coverage book. */\nexport interface AnalystCoverageBookEntry {\n ticker: string;\n noteCount: number;\n firstNote: string | null;\n lastNote: string | null;\n latestPriceTarget: number | null;\n latestFirm: string | null;\n}\n\nexport interface AnalystProfile {\n slug: string;\n name: string;\n /** `\"sell_side_equity\"` */\n role: string;\n /** Where this analyst last published, which is not necessarily where they work today. */\n mostRecentFirm: string | null;\n firms: AnalystFirmTenure[];\n firstSeen: string | null;\n lastSeen: string | null;\n /** Price target notes attributed to this analyst. */\n noteCount: number;\n /** Distinct tickers covered. */\n tickerCount: number;\n /** PRO: the full book. FREE: the 5 most recently covered tickers. */\n coverage: AnalystCoverageBookEntry[];\n}\n\n/** One row of an analyst's call history. */\nexport interface AnalystCall {\n /** ISO date the note was published, `\"YYYY-MM-DD\"`. Day granularity on purpose. */\n publishedDate: string;\n ticker: string;\n /** The firm this analyst published under at the time. */\n firm: string;\n priceTarget: number | null;\n adjPriceTarget: number | null;\n priceWhenPosted: number | null;\n newsTitle: string | null;\n newsUrl: string | null;\n newsPublisher: string | null;\n}\n\nexport interface GetAnalystCoverageOptions {\n /**\n * Coverage window in days, 1 to 1825. Omitted, the API applies its own default of\n * 365. Values above the cap are clamped rather than rejected, and `data.windowDays`\n * reports the window actually applied.\n */\n lookbackDays?: number;\n}\n\nexport interface GetAnalystCallsOptions {\n /** Page size, 1 to 200. Omitted, the API applies its own default of 25. */\n limit?: number;\n /** Rows to skip. Omitted, the API starts at 0. */\n offset?: 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 /**\n * Get who covers a ticker and what they most recently said, grouped by firm, most\n * recently active firm first.\n *\n * This is the one-call answer to \"who covers AMD and what do they say\". Each row in\n * `data.coverage` is a firm, the individual analysts we can name on that firm's desk,\n * that firm's most recent price target note, and that firm's most recent rating action.\n *\n * A PRO key receives every firm. A FREE key receives the 5 most recently active firms\n * with every response-level count intact, so the counts describe the full window even\n * when the rows do not.\n *\n * Two shapes to read rather than assume. **A firm can cover a stock without publishing\n * a price target**, because coverage means a note or a rating action in the window: that\n * row carries `noteCount: 0`, a `null` `latestNote` and a populated `firmRating`, so\n * read `noteCount` on the row instead of expecting a note. And **not every note names\n * its analyst**, at a rate that is a property of the publisher and varies enormously by\n * ticker, so a firm can appear with an empty `analysts` array and a non-zero\n * `noteCount`, and `latestNote.analyst` can be `null`. Read `attributedNoteCount` and\n * `unattributedNoteCount` off the response you received rather than hardcoding a rate.\n *\n * `firmRating` belongs to the firm, not to a person: rating actions are published at\n * firm level with no individual attached.\n *\n * Each named analyst carries the `slug` that addresses {@link profile} and\n * {@link calls}, so a coverage response is the natural entry point into a person.\n */\n async coverage(\n ticker: string,\n options?: GetAnalystCoverageOptions,\n ): Promise<PreviewResponse<AnalystCoverage>> {\n return this.client.get(\n `/api/v1/analyst/${encodeURIComponent(ticker.toUpperCase())}/coverage`,\n options,\n );\n }\n\n /**\n * Get one analyst: the firms they have published under, the window of notes we hold at\n * each, and the tickers they cover. Throws `NotFoundError` when the slug matches no\n * analyst.\n *\n * A PRO key receives the full book. A FREE key receives the profile with\n * `data.coverage` truncated to the 5 most recently covered tickers, and the envelope's\n * `totalCount` reporting how many there are in full.\n *\n * `firstSeen` and `lastSeen` are observation windows, not employment dates: they bound\n * the notes we hold from that analyst at that firm. `mostRecentFirm` says where they\n * last published, not where they work today. Do not render either as a hire or\n * departure date.\n *\n * This is call history, not a scorecard. There is no accuracy score, hit rate or\n * ranking here, and nothing in the response should be read as a rating of the person.\n *\n * @param slug Analyst slug, lowercased and hyphenated (e.g. `\"dan-ives\"`). You do not\n * have to guess one: every named analyst in a {@link coverage} response carries it.\n */\n async profile(slug: string): Promise<PreviewResponse<AnalystProfile>> {\n return this.client.get(\n `/api/v1/analyst/people/${encodeURIComponent(slug)}`,\n );\n }\n\n /**\n * Get one analyst's price target notes, newest first, paged. Throws `NotFoundError`\n * when the slug matches no analyst, which keeps \"this analyst has published nothing we\n * hold\" (an empty page) distinguishable from \"this analyst does not exist\".\n *\n * Ordered by published date descending with the row id as the final tie-break, a total\n * order, so walking the history with `offset` never drops or repeats a row. That\n * matters more than it looks: a single roundup article carries several of one analyst's\n * notes at an identical timestamp.\n *\n * A FREE key receives the first 25 rows as a complete response (`isPreview: false`);\n * asking for a larger `limit` or an `offset` past row 25 returns the free in-allowance\n * slice with `previewReason: \"PRO_REQUIRED\"`. A PRO key pages the whole history. The\n * envelope's `totalCount` is the analyst's whole attributed history rather than the page\n * size, so `offset + data.length < totalCount` tells you another page is available.\n *\n * Dates are day granularity on purpose. Publisher timestamps are not comparable across\n * sources, so a time of day would advertise precision the data does not have.\n */\n async calls(\n slug: string,\n options?: GetAnalystCallsOptions,\n ): Promise<PreviewResponse<AnalystCall[]>> {\n return this.client.get(\n `/api/v1/analyst/people/${encodeURIComponent(slug)}/calls`,\n options,\n );\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 * Curated landscape card image for the fund, suitable for a list row or a\n * profile header. Distinct from a square logo mark. Null when the fund has no\n * curated image assigned.\n */\n imageUrl: string | null;\n}\n\nexport interface EtfHolding {\n ticker: string;\n name: string | null;\n /** Weight in the fund as a percentage (0-100). */\n weightPct: number;\n /** ISO date \"YYYY-MM-DD\". First date this holding appeared in the composition. */\n firstSeen: string | null;\n}\n\nexport interface EtfHoldings {\n ticker: string;\n issuer: string;\n issuerEndpoint: string | null;\n /** ISO date \"YYYY-MM-DD\". Composition snapshot date from the issuer. */\n asOfDate: string;\n /** Epoch seconds when SentiSense refreshed the composition. */\n fetchedAt: number | null;\n /** ISO date \"YYYY-MM-DD\". When the composition is scheduled to be refreshed next. */\n nextRefreshDue: string;\n totalHoldings: number;\n holdings: EtfHolding[];\n /** True when this is a top-N view rather than the full fund. */\n partial?: boolean | null;\n /** Issuer's reported total holdings when `partial=true`. */\n totalKnownHoldings?: number | null;\n}\n\nexport interface EtfAggregateCoverage {\n holdingsCount: number;\n holdingsCovered: number;\n /** Sum of weights (0-100) for the covered holdings. */\n weightCovered: number;\n partial?: boolean | null;\n totalKnownHoldings?: number | null;\n}\n\nexport interface WeightedConsensus {\n upsidePercent: number | null;\n consensusLabel: string | null;\n /** Fractions of covered AUM in each bucket. Sums to ~1.0. */\n distribution: Record<string, number>;\n totalAnalysts: number;\n}\n\nexport interface EtfAnalystContributor {\n ticker: string;\n weightPct: number;\n upsidePercent: number | null;\n consensusLabel: string | null;\n /** Signed contribution to the fund's weighted upside in percentage points. */\n contributionPp: number;\n}\n\nexport interface EtfAnalystAggregate {\n ticker: string;\n /** ISO date \"YYYY-MM-DD\". Composition snapshot date. */\n asOfDate: string | null;\n /** Epoch seconds when this rollup was computed. */\n computedAt: number;\n coverage: EtfAggregateCoverage;\n weightedConsensus: WeightedConsensus;\n /** Top contributors (up to 10) by absolute contribution to the weighted upside. */\n topContributors: EtfAnalystContributor[];\n}\n\nexport interface WeightedNetFlow {\n /** Weighted net dollar flow (buys - sells). Negative = net selling. */\n netDollars: number;\n buyDollars: number;\n sellDollars: number;\n /** Unweighted; for context. */\n buyTradeCount: number;\n /** Unweighted; for context. */\n sellTradeCount: number;\n distinctInsiderCount: number;\n}\n\nexport interface EtfInsiderContributor {\n ticker: string;\n weightPct: number;\n /** Per-stock net flow over the window (signed). */\n netDollars: number;\n /** Signed contribution to the weighted headline. */\n weightedNetDollars: number;\n tradeCount: number;\n}\n\nexport interface EtfInsiderAggregate {\n ticker: string;\n /** ISO date \"YYYY-MM-DD\". Composition snapshot date. */\n asOfDate: string | null;\n /** Epoch seconds when this rollup was computed. */\n computedAt: number;\n lookbackDays: number;\n coverage: EtfAggregateCoverage;\n weightedNetFlow: WeightedNetFlow;\n /** Top contributors (up to 10) by absolute weighted-net-dollar contribution. */\n topContributors: EtfInsiderContributor[];\n}\n\nexport interface EtfSentimentReading {\n sentiSenseScore: number | null;\n /** BULLISH / NEUTRAL / BEARISH. */\n scoreLabel: string;\n /** Epoch seconds when the underlying metric was produced. */\n asOfTimestamp: number | null;\n}\n\nexport interface EtfSentimentAggregate {\n ticker: string;\n /** ISO date \"YYYY-MM-DD\". Composition snapshot date. */\n asOfDate: string | null;\n /** Epoch seconds when this aggregate was assembled. */\n computedAt: number;\n coverage: EtfAggregateCoverage;\n /** Holdings-weighted SentiSense across the fund's constituents. */\n constituentsWeighted: EtfSentimentReading;\n /** Direct reading from mentions of the fund's own ticker. Null for low-mention funds. */\n direct: EtfSentimentReading | null;\n}\n\nexport interface GetEtfInsiderAggregateOptions {\n /** Trailing window for the trade aggregation. Typical values: 30, 90. Default 30. */\n lookbackDays?: number;\n}\n\n/**\n * ETF discovery, composition (holdings), and holdings-weighted aggregate views.\n *\n * Funds aren't rated by analysts directly, don't have insiders of their own, and\n * may not get many direct news mentions -- but the companies inside them do. The\n * aggregate endpoints synthesize fund-level views from each constituent's per-stock\n * data, weighted by allocation, with a coverage block so consumers see how much of\n * the fund's AUM the underlying data covered.\n *\n * Beta as of 2026-05-15: starting with a limited set of widely-traded funds.\n */\nexport class Etfs {\n constructor(private client: APIClient) {}\n\n /**\n * List every ETF tracked by SentiSense, sorted by ticker.\n */\n async list(): Promise<EtfInfo[]> {\n return this.client.get(\"/api/v1/etfs\");\n }\n\n /**\n * Get the full holdings composition for an ETF, including per-holding weights\n * and freshness metadata. Returns 404 for unknown ETFs or commodity-only funds.\n */\n async holdings(ticker: string): Promise<EtfHoldings> {\n return this.client.get(\n `/api/v1/etfs/${encodeURIComponent(ticker.toUpperCase())}/holdings`,\n );\n }\n\n /**\n * Get the holdings-weighted analyst consensus for an ETF, including the\n * top per-holding contributors that drive the weighted upside.\n */\n async analystAggregate(\n ticker: string,\n ): Promise<PreviewResponse<EtfAnalystAggregate>> {\n return this.client.get(\n `/api/v1/etfs/${encodeURIComponent(ticker.toUpperCase())}/aggregates/analyst`,\n );\n }\n\n /**\n * Get the holdings-weighted SEC Form 4 insider aggregate for an ETF over a\n * configurable trailing window, including per-holding `topContributors` with\n * signed contribution to the weighted headline.\n */\n async insiderAggregate(\n ticker: string,\n options?: GetEtfInsiderAggregateOptions,\n ): Promise<PreviewResponse<EtfInsiderAggregate>> {\n return this.client.get(\n `/api/v1/etfs/${encodeURIComponent(ticker.toUpperCase())}/aggregates/insider`,\n options,\n );\n }\n\n /**\n * Get two SentiSense Score readings side-by-side: `constituentsWeighted`\n * (precomputed daily weighted average across the fund's holdings) and `direct`\n * (score from mentions of the fund's own ticker). The two can diverge, and the\n * gap is itself information.\n */\n async sentimentAggregate(\n ticker: string,\n ): Promise<PreviewResponse<EtfSentimentAggregate>> {\n return this.client.get(\n `/api/v1/etfs/${encodeURIComponent(ticker.toUpperCase())}/aggregates/sentiment`,\n );\n }\n}\n","import type { APIClient } from \"../client.js\";\nimport type {\n InsiderActivityResponse,\n InsiderTrade,\n ClusterBuy,\n GetInsiderOptions,\n PreviewResponse,\n} from \"../types.js\";\n\nexport class Insider {\n constructor(private client: APIClient) {}\n\n /**\n * Get market-wide insider activity: top buys and sells aggregated by ticker.\n *\n * PRO-gated. Free-tier users receive a preview (top 5 per direction)\n * with `isPreview: true` in the response.\n */\n async getActivity(options?: GetInsiderOptions): Promise<PreviewResponse<InsiderActivityResponse>> {\n return this.client.get(\"/api/v1/insider/activity\", options);\n }\n\n /**\n * Get individual insider transactions for a specific stock.\n *\n * PRO-gated. Free users receive a preview of the top 5 transactions.\n */\n async getTrades(ticker: string, options?: GetInsiderOptions): Promise<PreviewResponse<InsiderTrade[]>> {\n return this.client.get(\n `/api/v1/insider/trades/${encodeURIComponent(ticker.toUpperCase())}`,\n options,\n );\n }\n\n /**\n * Get cluster buy signals: stocks where 3+ distinct insiders bought recently.\n *\n * PRO-gated. Free users receive a preview of the top 3 signals.\n */\n async getClusterBuys(options?: GetInsiderOptions): Promise<PreviewResponse<ClusterBuy[]>> {\n return this.client.get(\"/api/v1/insider/cluster-buys\", options);\n }\n}\n","import type { APIClient } from \"../client.js\";\nimport type {\n CongressTrade,\n PoliticianSummary,\n PoliticianDetail,\n GetPoliticianActivityOptions,\n GetPoliticiansOptions,\n GetPoliticianDirectoryOptions,\n GetPoliticianMemberOptions,\n PoliticianDirectory,\n PoliticianDirectoryResponse,\n PreviewResponse,\n} from \"../types.js\";\n\nexport class Politicians {\n constructor(private client: APIClient) {}\n\n /**\n * Get recent congressional STOCK Act trading activity across all politicians.\n *\n * PRO-gated. Free-tier users receive a preview (top 5 trades)\n * with `isPreview: true` in the response.\n *\n * The feed is longer than one response: a default 90-day window is routinely well over a\n * thousand disclosures, and without `limit` the server sends the first 200 with no marker\n * that it stopped. `totalCount` on the envelope is the real size on every tier, so page\n * with `limit` and `offset` rather than reading `data.length` as the total.\n *\n * ```typescript\n * const first = await client.politicians.getActivity({ limit: 100 });\n * for (let offset = 100; offset < first.totalCount!; offset += 100) {\n * const page = await client.politicians.getActivity({ limit: 100, offset });\n * // ... page.data\n * }\n * ```\n */\n async getActivity(\n options?: GetPoliticianActivityOptions,\n ): Promise<PreviewResponse<CongressTrade[]>> {\n return this.client.get(\"/api/v1/politicians/activity\", options);\n }\n\n /**\n * Get congressional trades for a specific stock.\n *\n * PRO-gated. Free users receive a preview of the top 3 trades.\n */\n async getFilings(\n ticker: string,\n options?: GetPoliticiansOptions,\n ): Promise<PreviewResponse<CongressTrade[]>> {\n return this.client.get(\n `/api/v1/politicians/filings/${encodeURIComponent(ticker.toUpperCase())}`,\n options,\n );\n }\n\n /**\n * Discover tracked members of Congress and the page slug identifying each, so you\n * can find who to query without knowing slugs upfront.\n *\n * Summary only, no trade data; use `getMember` for a member's filings.\n *\n * Unlike `getMembers`, this includes members who have **left Congress**, carrying\n * `former` and `servedUntil`. That roster lists who currently holds office, so a\n * former member is otherwise reachable only if you already know their slug.\n *\n * Requires an API key but does not consume monthly quota (per-minute rate limits\n * still apply), and is not tier-gated. Returns the unwrapped list payload.\n */\n async getDirectory(\n options?: GetPoliticianDirectoryOptions,\n ): Promise<PoliticianDirectory> {\n const resp = await this.client.get<PoliticianDirectoryResponse>(\n \"/api/v1/politicians/directory\",\n { ...options },\n );\n return resp.data;\n }\n\n /**\n * Get all tracked politicians with trading summary statistics.\n *\n * PRO-gated. Free users receive a preview of the top 5 members.\n *\n * Serves only members currently in office. Use `getDirectory` to enumerate\n * everyone tracked, former members included.\n */\n async getMembers(): Promise<PreviewResponse<PoliticianSummary[]>> {\n return this.client.get(\"/api/v1/politicians/members\");\n }\n\n /**\n * Get detailed profile for a single politician: summary, recent trades, top tickers.\n *\n * PRO-gated. Free users receive a preview-wrapped response.\n *\n * `data.recentTrades` is one page of the member's history, not all of it. Most members\n * have a few dozen disclosures and arrive complete in the default page; a handful have\n * thousands. `totalCount` on the envelope is the size of the whole history on every\n * tier, so page with `limit` and `offset` rather than reading `recentTrades.length` as\n * the total. `data.profile` and `data.topTickers` describe the whole history whatever\n * page you ask for, so `profile.totalTrades` does not shrink with a small `limit`.\n *\n * ```typescript\n * const first = await client.politicians.getMember(\"Ro-Khanna\", { limit: 500 });\n * for (let offset = 500; offset < first.totalCount!; offset += 500) {\n * const page = await client.politicians.getMember(\"Ro-Khanna\", { limit: 500, offset });\n * // ... page.data.recentTrades\n * }\n * ```\n */\n async getMember(\n slug: string,\n options?: GetPoliticianMemberOptions,\n ): Promise<PreviewResponse<PoliticianDetail>> {\n return this.client.get(\n `/api/v1/politicians/member/${encodeURIComponent(slug)}`,\n options,\n );\n }\n}\n","import type { APIClient } from \"../client.js\";\nimport type {\n Insight,\n GetInsightsOptions,\n PreviewResponse,\n} from \"../types.js\";\n\nexport interface GetStockInsightsRangeOptions {\n startDate: string;\n endDate: string;\n urgency?: \"low\" | \"medium\" | \"high\";\n insightType?: string;\n}\n\nexport interface GetLatestInsightsOptions {\n limit?: number;\n urgency?: \"low\" | \"medium\" | \"high\";\n}\n\nexport interface GetUserInsightsOptions {\n limit?: number;\n category?: string;\n}\n\nexport class Insights {\n constructor(private client: APIClient) {}\n\n /**\n * Get AI-generated insights for a specific stock, sorted by urgency then confidence.\n *\n * Returns the preview envelope: read the insights as `.data`. PRO callers get the\n * full list with `isPreview: false`; free callers get the top 3 with `isPreview: true`\n * and `totalCount` carrying the untruncated size.\n */\n async stock(\n ticker: string,\n options?: GetInsightsOptions,\n ): Promise<PreviewResponse<Insight[]>> {\n return this.client.get(\n `/api/v1/insights/stock/${encodeURIComponent(ticker.toUpperCase())}`,\n options,\n );\n }\n\n /**\n * Get AI insights for a stock within a date range.\n *\n * Returns the preview envelope: read the insights as `.data`. Free callers receive\n * the top 3, PRO callers the full list. The server returns 400 if `startDate` is\n * after `endDate`.\n */\n async stockRange(\n ticker: string,\n options: GetStockInsightsRangeOptions,\n ): Promise<PreviewResponse<Insight[]>> {\n return this.client.get(\n `/api/v1/insights/stock/${encodeURIComponent(ticker.toUpperCase())}/range`,\n options,\n );\n }\n\n /**\n * Get AI-generated market-level insights, sorted by urgency then confidence.\n *\n * Returns the preview envelope: read the insights as `.data`. PRO callers get the\n * full list with `isPreview: false`; free callers get the top 5 with `isPreview: true`\n * and `totalCount` carrying the untruncated size.\n */\n async market(): Promise<PreviewResponse<Insight[]>> {\n return this.client.get(\"/api/v1/insights/market\");\n }\n\n /**\n * Get the latest AI insights across all tracked stocks, newest first.\n *\n * Returns the preview envelope: read the insights as `.data`. Free callers receive\n * the top 5, PRO callers up to `limit` (clamped to 1-200).\n */\n async latest(\n options?: GetLatestInsightsOptions,\n ): Promise<PreviewResponse<Insight[]>> {\n return this.client.get(\"/api/v1/insights/latest\", options);\n }\n\n /**\n * Get personalized insights for the authenticated user.\n *\n * Biased toward the user's watchlist and portfolio when available; falls back\n * to market-level insights otherwise. API key authentication required.\n * Returns the preview envelope: read the insights as `.data`.\n */\n async user(\n options?: GetUserInsightsOptions,\n ): Promise<PreviewResponse<Insight[]>> {\n return this.client.get(\"/api/v1/insights/user\", options);\n }\n\n /**\n * Get available insight types for a specific stock.\n * API key required.\n *\n * Returns an array of insight type strings (e.g., `[\"sentiment_shift\", \"options_activity\"]`).\n */\n async types(ticker: string): Promise<string[]> {\n return this.client.get(\n `/api/v1/insights/stock/${encodeURIComponent(ticker.toUpperCase())}/types`,\n );\n }\n}\n","import type { APIClient } from \"../client.js\";\nimport type {\n GetFlowsOptions,\n GetHoldersOptions,\n Holder,\n InstitutionList,\n InstitutionListResponse,\n InstitutionalFlows,\n ListInstitutionsOptions,\n PreviewResponse,\n Quarter,\n TickerHolders,\n} from \"../types.js\";\n\nexport class Institutional {\n constructor(private client: APIClient) {}\n\n /** Get available 13F reporting quarters. */\n async getQuarters(): Promise<Quarter[]> {\n return this.client.get(\"/api/v1/institutional/quarters\");\n }\n\n /**\n * Get aggregate institutional activity per ticker for a quarter.\n *\n * `reportDate` is optional: omit it to get the latest available quarter, which may be\n * a still-open one holding only early filers. The response then carries `reportDate`\n * plus `isPending` and filer coverage counts so a partial quarter is clearly labeled.\n *\n * Returns the preview envelope, so the flows are one level down:\n * `const { data } = await client.institutional.getFlows(); data.inflows`.\n */\n async getFlows(\n reportDate?: string,\n options?: GetFlowsOptions,\n ): Promise<PreviewResponse<InstitutionalFlows>> {\n return this.client.get(\"/api/v1/institutional/flows\", {\n reportDate,\n ...options,\n });\n }\n\n /**\n * Get institutional holders for a specific stock.\n *\n * Returns the preview envelope wrapping a {@link TickerHolders} object, so the rows\n * are two levels down: `(await getHolders(t, d)).data.holders`, alongside ticker-level\n * totals like `holderCount`. Free callers get a truncated `holders` array with\n * `isPreview: true`.\n *\n * A widely held ticker returns thousands of rows: a megacap quarter is about\n * 6,000 holders and 1.5 MB. Pass `limit` unless you really want all of them.\n * Omitting `options` sends the original unbounded request.\n *\n * `limit` is the switch for the whole option set. With it, the response also carries\n * `returnedCount`, `offset`, and a `notableChanges` summary, so you can walk the list\n * without re-counting it. Without it, `offset` / `sortBy` / `sortDir` are ignored by the\n * server and you get the full unsorted list back with a 200.\n */\n async getHolders(\n ticker: string,\n reportDate: string,\n options?: GetHoldersOptions,\n ): Promise<PreviewResponse<TickerHolders>> {\n return this.client.get(\n `/api/v1/institutional/holders/${encodeURIComponent(ticker)}`,\n { reportDate, ...options },\n );\n }\n\n /**\n * Get activist investor positions (NEW or INCREASED).\n *\n * Returns the preview envelope, so read the rows as `.data`.\n */\n async getActivists(reportDate: string): Promise<PreviewResponse<Holder[]>> {\n return this.client.get(\"/api/v1/institutional/activist\", { reportDate });\n }\n\n /**\n * Discover institutions: a paginated, AUM-ranked list of filers (slug + metadata)\n * so you can find what to query without knowing slugs upfront.\n *\n * Each institution is rolled up by parent filer, so a multi-filer manager\n * (e.g. Vanguard) appears once with combined AUM. Summary only; use\n * `getInstitutionDetail` for a filer's full holdings.\n *\n * Requires an API key but does not consume monthly quota (per-minute rate\n * limits still apply). Returns the unwrapped list payload.\n */\n async listInstitutions(options?: ListInstitutionsOptions): Promise<InstitutionList> {\n const resp = await this.client.get<InstitutionListResponse>(\n \"/api/v1/institutional/institutions\",\n { ...options },\n );\n return resp.data;\n }\n\n /**\n * Get the full profile, summary stats, and current-quarter holdings for a\n * specific institutional filer.\n *\n * Resolved by URL slug (e.g. `Berkshire-Hathaway`) or numeric SEC CIK.\n * Free users receive the profile and top 10 holdings; PRO users receive the\n * full holdings array. Returns 404 if the slug or CIK is unknown.\n */\n async getInstitutionDetail(slugOrCik: string): Promise<unknown> {\n return this.client.get(\n `/api/v1/institutional/institution/${encodeURIComponent(slugOrCik)}`,\n );\n }\n}\n","import type { APIClient } from \"../client.js\";\nimport type { KBEntity } from \"../types.js\";\n\nexport class KB {\n constructor(private client: APIClient) {}\n\n /** Get popular entities for search suggestions. */\n async getPopularEntities(): Promise<KBEntity[]> {\n return this.client.get(\"/api/v1/kb/entities/popular\");\n }\n}\n","import type { APIClient } from \"../client.js\";\nimport type { MarketMood } from \"../types.js\";\n\nexport class MarketMoodResource {\n constructor(private client: APIClient) {}\n\n /** Get market mood data (scores, history, sectors). */\n async get(): Promise<MarketMood> {\n return this.client.get(\"/api/v2/market-mood\");\n }\n\n // TODO: accept a `days` param to control history length (the endpoint supports ?days=N).\n //\n // Market Mood is also reachable through `client.indexes`, which serves it in the shared\n // index envelope alongside fed-sentiment and ai-sentiment. Use this resource when you want\n // the phase band, weekly change, per-signal breakdown and per-sector map; use `indexes`\n // when you want every index to answer the same shape. Both report the same headline number.\n}\n","import type { APIClient } from \"../client.js\";\nimport type { MarketSummary } from \"../types.js\";\n\nexport class MarketSummaryResource {\n constructor(private client: APIClient) {}\n\n /** Get the AI-generated market summary with headline and analysis. */\n async get(): Promise<MarketSummary> {\n return this.client.get(\"/api/v1/market-summary\");\n }\n}\n","import type { APIClient } from \"../client.js\";\nimport type { OptionsOverview, PreviewResponse } from \"../types.js\";\n\n/**\n * Market-wide options intelligence.\n *\n * Per-ticker options live on `client.stocks` (`getOptionsSummary`, `getOptionsHistory`),\n * next to everything else keyed by a symbol. This resource holds the surfaces that have no\n * ticker at all, the same split the market-wide mood and screener resources use.\n */\nexport class Options {\n constructor(private client: APIClient) {}\n\n /**\n * Get the market-wide options radar: where implied volatility, put/call flow and skew are\n * unusual today, ranked.\n *\n * End of day, not live. `asOf` is the latest completed session and the build refreshes the\n * following morning, so this is positioning, not a quote feed.\n *\n * **The response carries two separately-ranked boards.** `data.rows` is the covered stock\n * universe and `data.etfRows` is the covered ETF universe. Do not merge them: each row's\n * readings are percentiles of that ticker's own trailing history, so a rank built across\n * both boards compares numbers measured against different baselines. The aggregates are\n * split the same way, with the `etf`-prefixed fields describing the ETF board alone.\n *\n * `data` is `null` before the first nightly build populates it, which is a cold-start\n * state rather than an error.\n *\n * Tiering: a PRO key receives every row. A FREE key receives the top 25 stock rows plus\n * all the aggregates, with `isPreview` true and the envelope's `totalCount` reporting the\n * full stock board; `data.etfTotalCount` does the same for the ETF board.\n *\n * Drill into any row with `client.stocks.getOptionsSummary(ticker)` for its full dossier,\n * or `client.stocks.getOptionsHistory(ticker)` to chart how a reading has trended.\n */\n async getOverview(): Promise<PreviewResponse<OptionsOverview | null>> {\n return this.client.get(\"/api/v1/options/overview\");\n }\n}\n","import type { APIClient } from \"../client.js\";\nimport type {\n EtfScreenerExecuteResponse,\n EtfScreenerRow,\n FeaturedScreen,\n ScreenerExecuteOptions,\n ScreenerExecuteResponse,\n ScreenerFieldCatalog,\n ScreenerFieldDescriptor,\n ScreenerFieldOption,\n ScreenerFilter,\n ScreenerPlan,\n ScreenerRow,\n ScreenerScreensResponse,\n ScreenerSort,\n} from \"../types.js\";\n\n/**\n * Screener: filter the tracked universe on the SentiSense Score, attention,\n * analyst consensus, technicals and price in a single query. It is the one\n * surface where our own signals sit in the same `WHERE` clause as the market\n * data, which is the point: screening on analyst ratings alone is something a\n * dozen free tools do, screening on analyst ratings *where the Score disagrees*\n * is not.\n *\n * Every screen is a {@link ScreenerPlan}. Take one from {@link screens} or\n * build your own, then hand it to {@link run} or {@link runEtfs}.\n *\n * Three field semantics are worth knowing before you write a filter, because\n * guessing them wrong produces a screen that looks fine and means nothing:\n *\n * - **`ANALYST_RATING_MEAN` is inverted.** It is the vendor's 1-to-5 scale\n * where `1.0` is strong buy, so bullish is `LTE 2.5`, not `GTE`. Prefer\n * `ANALYST_BUY_RATIO_PCT`, which runs the intuitive direction.\n * - **`MA_CROSS_STATE` is ordinal**, not a percentage: `1` golden cross (50-day\n * above 200-day), `-1` death cross, `0` neither. Use `EQ`.\n * - **`SENTIMENT_DIRECTION` is the sign of the 7-day SentiSense Score**\n * (`1` / `0` / `-1`) with a neutral band of plus-or-minus 5. Despite the name\n * it is not sentiment polarity, and `0` matches only an exact zero, so it\n * returns almost nothing.\n *\n * The Score fields (`SENTI_SCORE_7D`, `SENTI_SCORE_1M`, `SCORE_CHANGE_7D`) are\n * the SentiSense Score, not polarity: unbounded, banded at 5 / 13 / 23 either\n * side of zero. Filter on those band edges, not on values like `0.5`, which\n * behave as \"any positive score\".\n *\n * Nulls never match, in either direction: `RETURN_1Y >= 0` and `RETURN_1Y < 0`\n * do not partition the universe, because a stock listed four months ago is in\n * neither result. If a screen returns fewer rows than you expect, check\n * coverage before you check your thresholds.\n *\n * Screens read a snapshot that refreshes every 20 minutes, so this is not a\n * quote feed. Use `client.stocks.getQuote()` for live prices.\n */\nexport class Screener {\n constructor(private client: APIClient) {}\n\n /**\n * Every filterable field, with its unit, operators and description, for both\n * universes.\n *\n * Build a filter UI from this rather than hardcoding the list and you inherit\n * new fields as they ship. The ETF `STRING` fields (`ISSUER`, `ASSET_CLASS`,\n * `TRACKED_INDEX`) come back with their `values` populated from the live\n * universe, so pickers stay current without a redeploy.\n */\n async fields(): Promise<ScreenerFieldCatalog> {\n return this.client.get(\"/api/v1/screener/fields\");\n }\n\n /**\n * The curated screens shipped in the product, each with a runnable plan.\n *\n * Each `plan` round-trips straight into {@link run} (or {@link runEtfs} when\n * `plan.universe === \"ETF\"`) with nothing to rebuild.\n *\n * Their filters identify the field with `field` rather than `fieldName`.\n * Both keys are accepted on the way in, so read either when inspecting a plan\n * you did not build yourself.\n */\n async screens(): Promise<ScreenerScreensResponse> {\n return this.client.get(\"/api/v1/screener/screens\");\n }\n\n /**\n * Run a screen against the stock universe.\n *\n * `tickers` is optional: omit it to screen the whole tracked universe, pass a\n * list to screen a watchlist. `limit` sits next to the plan rather than\n * inside it, because a plan is a stored object and paging is a transport\n * concern; it defaults to 100 and caps at 500.\n *\n * Read `matched` before you read `results`: it is the count before `limit`\n * was applied, so a `matched` above your `limit` means you are holding the\n * top slice under the plan's sort, not the whole answer.\n *\n * @example\n * ```ts\n * const res = await client.screener.run({\n * plan: {\n * filters: [\n * { fieldName: \"SENTI_SCORE_7D\", op: \"GTE\", value: 13 },\n * { fieldName: \"ANALYST_BUY_RATIO_PCT\", op: \"LTE\", value: 30 },\n * { fieldName: \"ANALYST_COUNT\", op: \"GTE\", value: 5 },\n * ],\n * sort: { fieldName: \"SENTI_SCORE_7D\", dir: \"DESC\" },\n * },\n * limit: 25,\n * });\n * ```\n */\n async run(options: ScreenerExecuteOptions): Promise<ScreenerExecuteResponse> {\n return this.client.post(\"/api/v1/screener/execute\", options);\n }\n\n /**\n * Run a screen against the ETF universe.\n *\n * Same request shape as {@link run}, against a different field vocabulary:\n * take the ETF names from `fields().etf`. `IN` / `NOT_IN` take a `values`\n * array instead of `value` and are the operators for the string fields\n * (`ISSUER`, `ASSET_CLASS`, `TRACKED_INDEX`).\n *\n * `CONSTITUENTS_WEIGHTED_SENTISENSE` is the holdings-weighted SentiSense\n * Score across what the fund owns and is usually the one you want;\n * `DIRECT_SENTISENSE` is the Score from chatter about the fund ticker itself,\n * which on a broad index fund is mostly macro noise. `WEIGHT_COVERED_PCT`\n * tells you how much of the fund's weight had constituent data behind the\n * weighted number.\n */\n async runEtfs(options: ScreenerExecuteOptions): Promise<EtfScreenerExecuteResponse> {\n return this.client.post(\"/api/v1/screener/etfs/execute\", options);\n }\n}\n\n// Re-export for convenience so callers can `import type { ScreenerPlan }`\n// from the resource module instead of `../types`.\nexport type {\n EtfScreenerExecuteResponse,\n EtfScreenerRow,\n FeaturedScreen,\n ScreenerExecuteOptions,\n ScreenerExecuteResponse,\n ScreenerFieldCatalog,\n ScreenerFieldDescriptor,\n ScreenerFieldOption,\n ScreenerFilter,\n ScreenerPlan,\n ScreenerRow,\n ScreenerScreensResponse,\n ScreenerSort,\n};\n","import type { APIClient } from \"../client.js\";\nimport type {\n AISummary,\n ChartData,\n ChartDataPoint,\n CompanyKpisData,\n FloatInfo,\n Fundamentals,\n FundamentalsPeriodsResponse,\n TtmFundamentals,\n GetAISummaryOptions,\n GetChartOptions,\n GetDescriptionsOptions,\n GetFundamentalsOptions,\n GetImagesOptions,\n GetMetricsBreakdownOptions,\n GetProfileOptions,\n GetOptionsHistoryOptions,\n GetSimilarOptions,\n KpiCoverageResponse,\n KpiTypeEntry,\n MarketStatus,\n MetricsBreakdown,\n OptionsHistory,\n OptionsSummary,\n PreviewResponse,\n SimilarStock,\n ShortInterest,\n ShortVolume,\n StockDetail,\n StockEntity,\n StockSentiment,\n StockImage,\n StockPrice,\n StockProfile,\n StockQuote,\n} from \"../types.js\";\n\n/**\n * Fill the legacy `name` alias from the fields the API actually sends.\n *\n * `/stocks/detailed` and `/stocks/popular/detailed` return `simpleName` and\n * `companyName`; they have never sent `name`. Callers reading `.name` got\n * `undefined`, so it is backfilled here rather than left to crash.\n */\nfunction withLegacyName(rows: StockDetail[]): StockDetail[] {\n if (!Array.isArray(rows)) return rows;\n return rows.map((row) =>\n row && !row.name ? { ...row, name: row.simpleName || row.companyName || \"\" } : row,\n );\n}\n\nexport class Stocks {\n constructor(private client: APIClient) {}\n\n /** List all available ticker symbols. */\n async list(): Promise<string[]> {\n return this.client.get(\"/api/v1/stocks\");\n }\n\n /** List all stocks with company names, kbEntityId, urlSlug. */\n async listDetailed(): Promise<StockDetail[]> {\n const rows = await this.client.get<StockDetail[]>(\"/api/v1/stocks/detailed\");\n return withLegacyName(rows);\n }\n\n /** Get popular ticker symbols. */\n async listPopular(): Promise<string[]> {\n return this.client.get(\"/api/v1/stocks/popular\");\n }\n\n /** Get popular stocks with details. */\n async listPopularDetailed(): Promise<StockDetail[]> {\n const rows = await this.client.get<StockDetail[]>(\"/api/v1/stocks/popular/detailed\");\n return withLegacyName(rows);\n }\n\n /** Get real-time price for a single ticker. */\n async getPrice(ticker: string): Promise<StockPrice> {\n return this.client.get(\"/api/v1/stocks/price\", { ticker });\n }\n\n /**\n * Get aggregate quote snapshot: live price, today OHLC, 52-week range,\n * market cap, P/E, EPS TTM, and dividend yield in a single call.\n * All fields except `ticker` may be null when upstream data is unavailable.\n */\n async getQuote(ticker: string): Promise<StockQuote> {\n return this.client.get(`/api/v1/stocks/${encodeURIComponent(ticker)}/quote`);\n }\n\n /** Get real-time prices for multiple tickers. */\n async getPrices(tickers: string[]): Promise<StockPrice[]> {\n return this.client.get(\"/api/v1/stocks/prices\", {\n tickers: tickers.join(\",\"),\n });\n }\n\n /** Get batch company logo URLs. */\n async getImages(\n tickers: string[],\n options?: GetImagesOptions,\n ): Promise<Record<string, StockImage>> {\n return this.client.get(\"/api/v1/stocks/images\", {\n tickers: tickers.join(\",\"),\n ...options,\n });\n }\n\n /** Get company profiles with branding, market cap, sector. */\n async getDescriptions(\n tickers: string[],\n options?: GetDescriptionsOptions,\n ): Promise<Record<string, StockProfile>> {\n return this.client.get(\"/api/v1/stocks/descriptions\", {\n tickers: tickers.join(\",\"),\n ...options,\n });\n }\n\n /** Get peer/similar stocks. */\n async getSimilar(ticker: string, options?: GetSimilarOptions): Promise<SimilarStock[]> {\n return this.client.get(`/api/v1/stocks/${encodeURIComponent(ticker)}/similar`, options);\n }\n\n /** Get company profile (CEO, sector, industry, market data). */\n async getProfile(ticker: string, options?: GetProfileOptions): Promise<StockProfile> {\n return this.client.get(`/api/v1/stocks/${encodeURIComponent(ticker)}/profile`, options);\n }\n\n /**\n * Get the headline sentiment picture for a stock in one call.\n *\n * Returns the SentiSense Score with its 30-day regime, mention volume and social\n * dominance, per-source tone in `bySource`, plus related tickers, story drivers, a\n * narrative and an FAQ. Available in full on every API-key tier.\n *\n * Use `entityMetrics.getMetrics(ticker, \"sentiment\", ...)` instead when you need a time\n * series over a specific window rather than the headline read. Returns 404 for tickers\n * with no sentiment coverage.\n */\n async getSentiment(ticker: string): Promise<PreviewResponse<StockSentiment>> {\n return this.client.get(\n `/api/v1/stocks/${encodeURIComponent(ticker)}/sentiment`,\n );\n }\n\n /** Get related KB entities (people, products, partners). */\n async getEntities(ticker: string): Promise<StockEntity[]> {\n return this.client.get(`/api/v1/stocks/${encodeURIComponent(ticker)}/entities`);\n }\n\n /**\n * Get AI-generated stock analysis report. Requires PRO tier.\n *\n * `depth: \"deep\"` returns the full curated report and consumes one report view on\n * metered tiers; the default `\"basic\"` returns the one-paragraph summary.\n *\n * The deprecated `forceRefresh` option is accepted and discarded, not forwarded.\n */\n async getAISummary(ticker: string, options?: GetAISummaryOptions): Promise<AISummary> {\n const { forceRefresh: _forceRefresh, ...params } = options ?? {};\n return this.client.get(`/api/v1/stocks/${encodeURIComponent(ticker)}/ai-summary`, params);\n }\n\n /** Get sentiment/mention metrics breakdown by entity. */\n async getMetricsBreakdown(\n ticker: string,\n metricType: string,\n options?: GetMetricsBreakdownOptions,\n ): Promise<MetricsBreakdown> {\n return this.client.get(\n `/api/v1/stocks/${encodeURIComponent(ticker)}/metrics/${encodeURIComponent(metricType)}/breakdown`,\n options,\n );\n }\n\n /**\n * Get historical OHLCV chart data.\n *\n * The API returns a bare array of points; this normalizes it to\n * `{ ticker, timeframe, data }`. `timeframe` echoes the requested value\n * (defaulting to \"1M\", matching the server default when omitted).\n */\n async getChart(ticker: string, options?: GetChartOptions): Promise<ChartData> {\n const data = await this.client.get<ChartDataPoint[]>(\"/api/v1/stocks/chart\", {\n ticker,\n ...options,\n });\n return { ticker, timeframe: options?.timeframe ?? \"1M\", data };\n }\n\n /** Get current market open/closed/pre-market/after-hours status. */\n async getMarketStatus(): Promise<MarketStatus> {\n return this.client.get(\"/api/v1/stocks/market-status\");\n }\n\n /**\n * Get financial statement data for one reporting period: income statement, balance sheet,\n * and cash flow, including `capitalExpenditure` and `freeCashFlow`.\n *\n * Capital expenditure is signed as filed, so normally negative. See {@link Fundamentals}\n * for the free-cash-flow relationship and when it is `null`.\n */\n async getFundamentals(ticker: string, options?: GetFundamentalsOptions): Promise<Fundamentals> {\n return this.client.get(\"/api/v1/stocks/fundamentals\", { ticker, ...options });\n }\n\n /** Get available fiscal periods. The periods are in `periods`. */\n async getFundamentalsPeriods(ticker: string): Promise<FundamentalsPeriodsResponse> {\n return this.client.get(\"/api/v1/stocks/fundamentals/periods\", { ticker });\n }\n\n /**\n * Get the trailing-twelve-month fundamentals snapshot: TTM ratios, a different\n * shape from the per-period statement data `getFundamentals()` returns.\n */\n async getCurrentFundamentals(ticker: string): Promise<TtmFundamentals> {\n return this.client.get(\"/api/v1/stocks/fundamentals/current\", { ticker });\n }\n\n /** Get historical revenue data. */\n async getHistoricalRevenue(ticker: string): Promise<unknown> {\n return this.client.get(\"/api/v1/stocks/fundamentals/historical/revenue\", { ticker });\n }\n\n /** Get short interest metrics (FINRA). */\n async getShortInterest(ticker: string): Promise<ShortInterest> {\n return this.client.get(\"/api/v1/stocks/short-interest\", { ticker });\n }\n\n /** Get float information. */\n async getFloat(ticker: string): Promise<FloatInfo> {\n return this.client.get(\"/api/v1/stocks/float\", { ticker });\n }\n\n /** Get short volume trading data. */\n async getShortVolume(ticker: string): Promise<ShortVolume> {\n return this.client.get(\"/api/v1/stocks/short-volume\", { ticker });\n }\n\n /**\n * Get company-specific KPI time-series for a ticker. Returns curated GAAP and\n * non-GAAP metrics from earnings filings (e.g. iPhone unit sales, Tesla deliveries,\n * AWS revenue).\n *\n * Free users receive metadata only with an empty `kpis` list; PRO users receive\n * the full series. Returns 404 for tickers that do not yet have curated coverage.\n *\n * Coverage today: near-complete for the S&P 500 plus extended universe\n * (~500 tickers). Use `listKpiCoverage()` to enumerate.\n */\n async getKpis(ticker: string): Promise<PreviewResponse<CompanyKpisData>> {\n return this.client.get(\n `/api/v1/stocks/${encodeURIComponent(ticker.toUpperCase())}/kpis`,\n );\n }\n\n /**\n * List every ticker with curated KPI coverage. Returns `{count, tickers: [...]}`\n * with lightweight metadata (ticker, companyName, lastUpdated, kpiCount).\n * Sorted alphabetically by ticker.\n *\n * Auth: API key required, but the call does NOT consume your monthly quota\n * (rate-limit-per-minute still applies).\n */\n async listKpiCoverage(): Promise<KpiCoverageResponse> {\n return this.client.get(\"/api/v1/stocks/with-kpis\");\n }\n\n /**\n * List the KPI metadata tuples available for a ticker (`id, name, category,\n * chartType`) without paying the cost of the full series payload. Mirrors\n * the `/api/v1/insights/stock/{ticker}/types` precedent.\n *\n * Auth: API key required, no quota cost. 404 if the ticker has no curated KPIs.\n */\n async getKpiTypes(ticker: string): Promise<KpiTypeEntry[]> {\n return this.client.get(\n `/api/v1/stocks/${encodeURIComponent(ticker.toUpperCase())}/kpis/types`,\n );\n }\n\n /**\n * Get the end-of-day options dossier for one stock or ETF: the session's aggregate, its\n * percentile context, the open-interest wall structure with max pain, and the contracts\n * whose volume ran far ahead of their open interest.\n *\n * End of day, not live. `asOf` is the prior trading session and the data refreshes the\n * following morning, so this is positioning, not a quote feed.\n *\n * **`data` is `null` for a ticker outside the covered universe**, which is the most\n * actively optioned US names plus the tracked ETFs, and for a covered ticker with no\n * snapshot yet. An unknown symbol behaves the same way rather than answering 404, so treat\n * a null as \"no coverage\", never as an error. A covered ticker still building its baseline\n * returns its raw readings with the percentiles omitted.\n *\n * Percentiles compare a ticker to its own trailing history, never to another ticker, so an\n * ETF's readings are not comparable with a single stock's.\n *\n * Tiering: a PRO key always receives the full dossier. A FREE key receives it for the first\n * ten calls each calendar month and a headline-only preview after that, with `isPreview`\n * true; calls that return a null `data` never spend that allowance.\n */\n async getOptionsSummary(ticker: string): Promise<PreviewResponse<OptionsSummary | null>> {\n return this.client.get(\n `/api/v1/stocks/${encodeURIComponent(ticker.toUpperCase())}/options/summary`,\n );\n }\n\n /**\n * Get the daily options aggregates for one stock or ETF as a time series, oldest first.\n * Use it to chart how a reading has trended: implied volatility, put/call flow, skew.\n *\n * Each element has the same shape as the dossier's `latest` aggregate, so a chart built\n * off `getOptionsSummary` reads this series without a second mapping.\n *\n * **A null payload is not how this one reports no coverage.** Unlike\n * {@link Stocks.getOptionsSummary}, an uncovered ticker, an unknown symbol and a covered\n * ticker with nothing stored yet all answer with a populated object whose `series` is\n * empty. Check the array's length, not the payload.\n *\n * The window served is not always the window requested: an unrecognised value clamps to\n * `\"1y\"` rather than erroring, and a FREE key always receives `\"1y\"`. Read `data.window`\n * for what you actually got. `\"5y\"` means all stored history, currently a little over two\n * years, so it can answer with nearly the same series as `\"2y\"`.\n */\n async getOptionsHistory(\n ticker: string,\n options?: GetOptionsHistoryOptions,\n ): Promise<PreviewResponse<OptionsHistory>> {\n return this.client.get(\n `/api/v1/stocks/${encodeURIComponent(ticker.toUpperCase())}/options/history`,\n options,\n );\n }\n}\n","import type { APIClient } from \"../client.js\";\nimport type {\n IndexConstituent,\n IndexHistoryPoint,\n IndexHistoryResponse,\n IndexListing,\n IndexListResponse,\n IndexSnapshot,\n} from \"../types.js\";\n\n/**\n * Indexes: composite scalars tracked over time, each blending its own inputs\n * into one number on a stated scale. Every index answers on the same envelope,\n * so you write one renderer and get every current and future SentiSense index.\n *\n * Two archetypes share that envelope. A **basket** index weight-averages\n * tracked entities and fills `constituents` / `basketSize` / `coverage` /\n * `totalMentions`; a **composite** index is built from signals instead and\n * returns `null` for all four by construction. See {@link IndexSnapshot}.\n *\n * @see IndexSnapshot\n */\nexport class Indexes {\n constructor(private client: APIClient) {}\n\n /**\n * List every index the platform publishes: id, display name, one-line\n * description, the scale it lives on, its access tier, and where its richest\n * view lives.\n *\n * Iterate this rather than hardcoding ids. Every `indexId` it advertises\n * resolves on {@link get} and {@link history}.\n */\n async list(): Promise<IndexListResponse> {\n return this.client.get(\"/api/v1/indexes\");\n }\n\n /**\n * Latest reading for one index.\n *\n * Check `constituents` for `null` before iterating: it is `null` on a\n * composite index like `market-mood`, which has no constituents by\n * construction. For Market Mood this is the narrowed view; the phase band,\n * weekly change, per-signal breakdown and per-sector map live on\n * `client.marketMood.get()`, and both report the same headline number.\n *\n * @param indexId slug from {@link list}, e.g. `\"fed-sentiment\"`.\n */\n async get(indexId: string): Promise<IndexSnapshot> {\n return this.client.get(`/api/v1/indexes/${indexId}`);\n }\n\n /**\n * Historical scalar series for one index, for charting.\n *\n * Thin or low-coverage buckets are withheld, so the series can be shorter\n * than `days` and can contain gaps. Plot against each point's `date`.\n *\n * @param indexId slug from {@link list}.\n * @param days days of history to return. Defaults to the API's own 180.\n */\n async history(indexId: string, days?: number): Promise<IndexHistoryResponse> {\n return this.client.get(\n `/api/v1/indexes/${indexId}/history`,\n days === undefined ? undefined : { days },\n );\n }\n}\n\n// Re-export for convenience so callers can `import type { IndexListing }`\n// from the resource module instead of `../types`.\nexport type {\n IndexConstituent,\n IndexHistoryPoint,\n IndexHistoryResponse,\n IndexListing,\n IndexListResponse,\n IndexSnapshot,\n};\n","import type { APIClient } from \"../client.js\";\nimport type {\n TrackerListing,\n TrackerListResponse,\n TrackerSnapshot,\n TrackerSnapshotResponse,\n} from \"../types.js\";\n\n/**\n * Trackers: observational data products published as a standardized\n * `TrackerSnapshot` envelope. Every tracker (institution rankings,\n * hedge-fund reported returns, social trackers, surveillance dashboards)\n * returns the same shape, so consumers write one renderer per `viewType` and\n * get every current and future SentiSense tracker for free.\n *\n * @see TrackerSnapshot\n */\nexport class Trackers {\n constructor(private client: APIClient) {}\n\n /**\n * List every publicly-visible tracker: id, display name, category,\n * one-line description, and the methodology anchor to link out to.\n */\n async list(): Promise<TrackerListResponse> {\n return this.client.get(\"/api/v1/trackers\");\n }\n\n /**\n * Standardized snapshot envelope for one tracker.\n *\n * Returns the envelope as-is: `{ isPreview, previewReason, totalCount?, data }`.\n * When `data.viewType === \"table\"` the rows live at `data.rows[]`; when\n * `\"choropleth\"` they live at `data.geo[]`; etc. Dispatch on `viewType`\n * in your renderer.\n *\n * @param trackerId slug from {@link list}, e.g. `\"institution-concentration\"`.\n * @param params provider-specific query params (e.g. `{ scope: \"us\" }` for\n * geographically-scoped trackers like hantavirus). Unknown keys are ignored.\n */\n async get(\n trackerId: string,\n params?: Record<string, string | number | boolean>,\n ): Promise<TrackerSnapshotResponse> {\n return this.client.get(`/api/v1/trackers/${trackerId}`, params);\n }\n}\n\n// Re-export for convenience so callers can `import type { TrackerListing }`\n// from the resource module instead of `../types`.\nexport type {\n TrackerListing,\n TrackerListResponse,\n TrackerSnapshot,\n TrackerSnapshotResponse,\n};\n","export const VERSION = \"0.49.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 { Options } from \"./resources/options.js\";\nimport { Screener } from \"./resources/screener.js\";\nimport { Stocks } from \"./resources/stocks.js\";\nimport { Indexes } from \"./resources/indexes.js\";\nimport { Trackers } from \"./resources/trackers.js\";\nimport type { SentiSenseOptions } from \"./types.js\";\nimport { VERSION } from \"./version.js\";\n\nconst DEFAULT_BASE_URL = \"https://app.sentisense.ai\";\nconst DEFAULT_TIMEOUT = 30_000;\nconst DEFAULT_MAX_RETRIES = 3;\nconst BASE_DELAY_MS = 1_000;\nconst MAX_DELAY_MS = 60_000;\n// Used when a 202 arrives without a usable Retry-After header.\nconst DEEP_HISTORY_FALLBACK_WAIT_S = 3;\n\n// Upper bounds on any server-supplied Retry-After. Rate limiting gets the longer ceiling\n// because a genuine limit window is legitimately minutes, while a deep-history warm-up is\n// seconds. Without a ceiling an oversized header value strands the caller indefinitely.\nconst MAX_DEEP_HISTORY_WAIT_S = 30;\nconst MAX_RATE_LIMIT_WAIT_S = 120;\nconst RATE_LIMIT_FALLBACK_WAIT_S = 60;\n\n/**\n * A `Retry-After` header as a usable number of seconds, clamped to `[0.5, maxWaitS]`, or\n * `undefined` when there is no usable value.\n *\n * `Retry-After` is vendor-controlled and may legally carry an HTTP-date rather than a\n * number of seconds, in which case parsing yields `NaN`. Left unguarded that produced a\n * `NaN` delay which compared false against every threshold and retried instantly in a busy\n * loop, and a `NaN` on the error object that silently broke a caller's own backoff.\n * Anything that is not a finite number is treated as absent.\n */\nfunction clampRetryAfter(\n raw: string | null,\n maxWaitS: number,\n): number | undefined {\n if (!raw) return undefined;\n const parsed = Number(raw);\n if (!Number.isFinite(parsed)) return undefined;\n return Math.min(Math.max(0.5, parsed), maxWaitS);\n}\n\n/** Same clamp, resolved to `defaultS` when the header gives us nothing to go on. */\nfunction retryAfterSeconds(\n raw: string | null,\n defaultS: number,\n maxWaitS: number,\n): number {\n return clampRetryAfter(raw, maxWaitS) ?? defaultS;\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/** @internal HTTP interface exposed to resource classes. */\nexport interface APIClient {\n get<T = unknown>(path: string, params?: object): Promise<T>;\n post<T = unknown>(path: string, body: unknown): Promise<T>;\n}\n\nexport class SentiSense implements APIClient {\n private baseUrl: string;\n private apiKey: string | undefined;\n private timeout: number;\n private maxRetries: number;\n private userAgent: string;\n\n readonly stocks: Stocks;\n readonly documents: Documents;\n readonly etfs: Etfs;\n readonly institutional: Institutional;\n readonly insider: Insider;\n readonly politicians: Politicians;\n readonly insights: Insights;\n readonly analyst: Analyst;\n readonly entityMetrics: EntityMetrics;\n readonly marketMood: MarketMoodResource;\n readonly marketSummary: MarketSummaryResource;\n readonly kb: KB;\n readonly indexes: Indexes;\n readonly trackers: Trackers;\n readonly calendar: Calendar;\n readonly earnings: Earnings;\n readonly screener: Screener;\n readonly options: Options;\n\n constructor(options: SentiSenseOptions = {}) {\n this.apiKey = options.apiKey;\n this.baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\\/+$/, \"\");\n this.timeout = options.timeout ?? DEFAULT_TIMEOUT;\n this.maxRetries = options.maxRetries ?? DEFAULT_MAX_RETRIES;\n // A header value cannot carry CR/LF, so collapse them rather than letting a caller's\n // string decide where the header block ends.\n const suffix = options.userAgentSuffix?.replace(/[\\r\\n]+/g, \" \").trim();\n this.userAgent = suffix\n ? `sentisense-node/${VERSION} ${suffix}`\n : `sentisense-node/${VERSION}`;\n\n this.stocks = new Stocks(this);\n this.documents = new Documents(this);\n this.etfs = new Etfs(this);\n this.institutional = new Institutional(this);\n this.insider = new Insider(this);\n this.politicians = new Politicians(this);\n this.insights = new Insights(this);\n this.analyst = new Analyst(this);\n this.entityMetrics = new EntityMetrics(this);\n this.marketMood = new MarketMoodResource(this);\n this.marketSummary = new MarketSummaryResource(this);\n this.kb = new KB(this);\n this.indexes = new Indexes(this);\n this.trackers = new Trackers(this);\n this.calendar = new Calendar(this);\n this.earnings = new Earnings(this);\n this.screener = new Screener(this);\n this.options = new Options(this);\n }\n\n /** @internal */\n async get<T = unknown>(path: string, params?: object): Promise<T> {\n const url = this.buildUrl(path, params);\n const headers: Record<string, string> = {\n \"Accept\": \"application/json\",\n };\n\n if (this.apiKey) {\n headers[\"X-SentiSense-API-Key\"] = this.apiKey;\n }\n\n // User-Agent is only set in Node.js (browsers disallow it)\n if (typeof process !== \"undefined\" && process.versions?.node) {\n headers[\"User-Agent\"] = this.userAgent;\n }\n\n let delayMs = 0;\n\n for (let attempt = 0; attempt <= this.maxRetries; attempt++) {\n if (delayMs > 0) {\n await sleep(delayMs);\n delayMs = 0;\n }\n\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await fetch(url, {\n method: \"GET\",\n headers,\n signal: controller.signal,\n });\n\n // 202 means a deep chart range is still being built server-side. It is a 2xx, so\n // without this it would fall through and return an empty array: the caller would\n // see \"no data\" rather than \"not ready yet\", which is the exact confusion the\n // status code exists to prevent. Retry honouring Retry-After, then surface it.\n if (response.status === 202) {\n const waitSeconds = retryAfterSeconds(\n response.headers.get(\"Retry-After\"),\n DEEP_HISTORY_FALLBACK_WAIT_S,\n MAX_DEEP_HISTORY_WAIT_S,\n );\n try { await response.body?.cancel(); } catch { /* ignore */ }\n if (attempt < this.maxRetries) {\n delayMs = waitSeconds * 1000;\n continue;\n }\n throw new DeepHistoryUnavailableError(\n \"Deep history is still being assembled. Retry in a few seconds.\",\n waitSeconds,\n );\n }\n\n if (!response.ok) {\n const isRetryable = response.status === 429 || response.status >= 500;\n if (isRetryable && attempt < this.maxRetries) {\n if (response.status === 429) {\n delayMs = retryAfterSeconds(\n response.headers.get(\"Retry-After\"),\n RATE_LIMIT_FALLBACK_WAIT_S,\n MAX_RATE_LIMIT_WAIT_S,\n ) * 1000;\n } else {\n delayMs = Math.min(BASE_DELAY_MS * Math.pow(2, attempt), MAX_DELAY_MS) + Math.random() * 1000;\n }\n try { await response.body?.cancel(); } catch { /* ignore */ }\n continue;\n }\n await this.handleErrorResponse(response);\n }\n\n return (await response.json()) as T;\n } catch (error) {\n if (error instanceof SentiSenseError) throw error;\n if (error instanceof Error && error.name === \"AbortError\") {\n throw new SentiSenseError(`Request timed out after ${this.timeout}ms`);\n }\n throw new SentiSenseError(\n error instanceof Error ? error.message : \"Unknown error\",\n );\n } finally {\n clearTimeout(timer);\n }\n }\n\n throw new SentiSenseError(\"All retries exhausted\");\n }\n\n /** @internal */\n async post<T = unknown>(path: string, body: unknown): Promise<T> {\n const url = this.buildUrl(path);\n const headers: Record<string, string> = {\n \"Accept\": \"application/json\",\n \"Content-Type\": \"application/json\",\n };\n\n if (this.apiKey) {\n headers[\"X-SentiSense-API-Key\"] = this.apiKey;\n }\n\n if (typeof process !== \"undefined\" && process.versions?.node) {\n headers[\"User-Agent\"] = this.userAgent;\n }\n\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await fetch(url, {\n method: \"POST\",\n headers,\n body: JSON.stringify(body),\n signal: controller.signal,\n });\n\n if (!response.ok) {\n await this.handleErrorResponse(response);\n }\n\n return (await response.json()) as T;\n } catch (error) {\n if (error instanceof SentiSenseError) throw error;\n if (error instanceof Error && error.name === \"AbortError\") {\n throw new SentiSenseError(`Request timed out after ${this.timeout}ms`);\n }\n throw new SentiSenseError(\n error instanceof Error ? error.message : \"Unknown error\",\n );\n } finally {\n clearTimeout(timer);\n }\n }\n\n private buildUrl(path: string, params?: object): string {\n const url = new URL(path, this.baseUrl);\n if (params) {\n for (const [key, value] of Object.entries(params as Record<string, unknown>)) {\n if (value !== undefined && value !== null) {\n url.searchParams.set(key, String(value));\n }\n }\n }\n return url.toString();\n }\n\n private async handleErrorResponse(response: Response): Promise<never> {\n let body: { error?: string; message?: string } = {};\n try {\n body = await response.json();\n } catch {\n // Response may not be JSON\n }\n\n const message = body.message ?? response.statusText ?? \"API request failed\";\n const code = body.error;\n\n switch (response.status) {\n case 401:\n case 403:\n throw new AuthenticationError(message, response.status, code);\n case 404:\n throw new NotFoundError(message, code);\n case 429: {\n // Same clamp the retry loop uses, so a caller running its own backoff off\n // `error.retryAfter` gets a number it can pass to setTimeout, or nothing at all.\n const retryAfter = clampRetryAfter(\n response.headers.get(\"Retry-After\"),\n MAX_RATE_LIMIT_WAIT_S,\n );\n throw new RateLimitError(message, code, retryAfter);\n }\n default:\n throw new APIError(message, response.status, code);\n }\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAO,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;;;AC8JO,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;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,SACJ,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;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAsBA,MAAM,QAAQ,MAAwD;AACpE,WAAO,KAAK,OAAO;AAAA,MACjB,0BAA0B,mBAAmB,IAAI,CAAC;AAAA,IACpD;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAqBA,MAAM,MACJ,MACA,SACyC;AACzC,WAAO,KAAK,OAAO;AAAA,MACjB,0BAA0B,mBAAmB,IAAI,CAAC;AAAA,MAClD;AAAA,IACF;AAAA,EACF;AACF;;;ACrWO,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;;;ACwGO,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;;;AC/MO,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;;;ACAO,IAAM,UAAN,MAAc;AAAA,EACnB,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;AAAA;AAAA;AAAA,EAyBxC,MAAM,cAAgE;AACpE,WAAO,KAAK,OAAO,IAAI,0BAA0B;AAAA,EACnD;AACF;;;ACeO,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;;;ACxFA,SAAS,eAAe,MAAoC;AAC1D,MAAI,CAAC,MAAM,QAAQ,IAAI,EAAG,QAAO;AACjC,SAAO,KAAK;AAAA,IAAI,CAAC,QACf,OAAO,CAAC,IAAI,OAAO,EAAE,GAAG,KAAK,MAAM,IAAI,cAAc,IAAI,eAAe,GAAG,IAAI;AAAA,EACjF;AACF;AAEO,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,UAAM,OAAO,MAAM,KAAK,OAAO,IAAmB,yBAAyB;AAC3E,WAAO,eAAe,IAAI;AAAA,EAC5B;AAAA;AAAA,EAGA,MAAM,cAAiC;AACrC,WAAO,KAAK,OAAO,IAAI,wBAAwB;AAAA,EACjD;AAAA;AAAA,EAGA,MAAM,sBAA8C;AAClD,UAAM,OAAO,MAAM,KAAK,OAAO,IAAmB,iCAAiC;AACnF,WAAO,eAAe,IAAI;AAAA,EAC5B;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;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAmBA,MAAM,kBACJ,QACA,SAC0C;AAC1C,WAAO,KAAK,OAAO;AAAA,MACjB,kBAAkB,mBAAmB,OAAO,YAAY,CAAC,CAAC;AAAA,MAC1D;AAAA,IACF;AAAA,EACF;AACF;;;AC1TO,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;;;AC6BvB,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,EA0B3C,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;AACjC,SAAK,UAAU,IAAI,QAAQ,IAAI;AAAA,EACjC;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":[]}
|