sentisense 0.43.0 → 0.44.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 CHANGED
@@ -88,6 +88,25 @@ something supplementary does not come back, such as the Score history behind a s
88
88
  command still prints its answer and exits 0 with a `note:` line on stderr, so stdout stays
89
89
  clean for a pipe and the gap is never silent.
90
90
 
91
+ ### Saying who is calling
92
+
93
+ If you set `SENTISENSE_AGENT_NAME` (what your agent is called) and `SENTISENSE_SKILL` (the
94
+ slug of the skill driving it), requests carry that identity, so usage can be understood and
95
+ the tools improved. Both are optional, never required, and nothing is inferred when they are
96
+ absent.
97
+
98
+ ```bash
99
+ export SENTISENSE_AGENT_NAME=research-desk
100
+ export SENTISENSE_SKILL=stock-analysis
101
+ npx -y sentisense@latest quote NVDA
102
+ # User-Agent: sentisense-node/0.44.0 sentisense-cli/0.44.0 (stock-analysis; agent/research-desk)
103
+ ```
104
+
105
+ Either can also be a flag (`--agent`, `--skill`) or a stored setting
106
+ (`sentisense auth --agent research-desk --skill stock-analysis`), resolved flag first, then
107
+ environment, then config. Values are reduced to letters, digits, dot, underscore and hyphen,
108
+ and capped at 32 characters, so nothing you set can reshape the header.
109
+
91
110
  ### Exit codes
92
111
 
93
112
  Failures print two lines to stderr, what went wrong and what to do about it, and exit with a
package/dist/cli.cjs CHANGED
@@ -55,8 +55,8 @@ var EXIT = {
55
55
  };
56
56
  var EXIT_TABLE = [
57
57
  [EXIT.OK, "success"],
58
- [EXIT.ERROR, "API error or unexpected failure"],
59
- [EXIT.USAGE, "bad usage: unknown command, flag, or missing argument"],
58
+ [EXIT.ERROR, "API error, including a request the API rejected as invalid"],
59
+ [EXIT.USAGE, "bad usage, caught before any request was sent"],
60
60
  [EXIT.AUTH, "missing or rejected API key"],
61
61
  [EXIT.NOT_FOUND, "no data for that symbol or identifier"],
62
62
  [EXIT.RATE_LIMIT, "rate limited"],
@@ -83,14 +83,14 @@ var MissingKeyError = class extends Error {
83
83
  this.name = "MissingKeyError";
84
84
  }
85
85
  };
86
- function describeError(error, debug) {
87
- const report = classify(error);
86
+ function describeError(error, debug, command) {
87
+ const report = classify(error, command);
88
88
  if (debug && error instanceof Error && error.stack) {
89
89
  report.lines.push(error.stack);
90
90
  }
91
91
  return report;
92
92
  }
93
- function classify(error) {
93
+ function classify(error, command) {
94
94
  if (error instanceof MissingKeyError) {
95
95
  return {
96
96
  exitCode: EXIT.AUTH,
@@ -156,6 +156,16 @@ function classify(error) {
156
156
  ]
157
157
  };
158
158
  }
159
+ if (error.status !== void 0 && error.status >= 400 && error.status < 500) {
160
+ const help = command ? `sentisense help ${command}` : "sentisense --help";
161
+ return {
162
+ exitCode: EXIT.ERROR,
163
+ lines: [
164
+ `error: the API rejected the request (${error.status}): ${error.message}`,
165
+ `next: check the flags and values you passed. Run "${help}" for the accepted fields and examples.`
166
+ ]
167
+ };
168
+ }
159
169
  return {
160
170
  exitCode: EXIT.ERROR,
161
171
  lines: [
@@ -435,6 +445,7 @@ function readConfig(dir) {
435
445
  const config = {};
436
446
  if (typeof raw.apiKey === "string") config.apiKey = raw.apiKey;
437
447
  if (typeof raw.agentName === "string") config.agentName = raw.agentName;
448
+ if (typeof raw.skill === "string") config.skill = raw.skill;
438
449
  if (typeof raw.baseUrl === "string") config.baseUrl = raw.baseUrl;
439
450
  return config;
440
451
  } catch {
@@ -464,10 +475,11 @@ function maskKey(key) {
464
475
  var authCommand = {
465
476
  name: "auth",
466
477
  summary: "Store an API key, show what is configured, or remove it",
467
- usage: "sentisense auth [<key>] [--agent <name>] [--remove]",
478
+ usage: "sentisense auth [<key>] [--agent <name>] [--skill <slug>] [--remove]",
468
479
  examples: [
469
480
  "sentisense auth $SENTISENSE_API_KEY",
470
481
  "sentisense auth --agent research-desk",
482
+ "sentisense auth --skill stock-analysis --agent research-desk",
471
483
  "sentisense auth",
472
484
  "sentisense auth --remove"
473
485
  ],
@@ -475,8 +487,10 @@ var authCommand = {
475
487
  "Settings live in config.json under $SENTISENSE_CONFIG_DIR, $XDG_CONFIG_HOME/sentisense,",
476
488
  "or ~/.config/sentisense, written owner-readable only (0600).",
477
489
  "The key is never printed back in full, and never has to be pasted into a command again.",
478
- "An agent name is optional. When set, it rides along in the User-Agent so your own",
479
- "traffic is easy to tell apart from everything else calling the API."
490
+ "Two optional labels say who is calling: --agent is what your agent calls itself, and",
491
+ "--skill is the slug of the skill driving it. When set, they ride along in the",
492
+ "User-Agent, so usage can be understood and the tools improved. Both are voluntary and",
493
+ "nothing needs them to work."
480
494
  ],
481
495
  flags: {
482
496
  remove: { type: "boolean", describe: "Delete the stored settings" }
@@ -495,13 +509,15 @@ var authCommand = {
495
509
  }
496
510
  const key = args.positionals[0];
497
511
  const agent = typeof args.flags.agent === "string" ? args.flags.agent : void 0;
512
+ const skill = typeof args.flags.skill === "string" ? args.flags.skill : void 0;
498
513
  const baseUrl = typeof args.flags["base-url"] === "string" ? args.flags["base-url"] : void 0;
499
- if (key || agent || baseUrl) {
514
+ if (key || agent || skill || baseUrl) {
500
515
  const stored2 = readConfig(dir);
501
516
  const next = {
502
517
  ...stored2,
503
518
  ...key ? { apiKey: key } : {},
504
519
  ...agent ? { agentName: agent } : {},
520
+ ...skill ? { skill } : {},
505
521
  ...baseUrl ? { baseUrl } : {}
506
522
  };
507
523
  writeConfig(dir, next);
@@ -510,6 +526,7 @@ var authCommand = {
510
526
  path,
511
527
  apiKey: next.apiKey ? maskKey(next.apiKey) : null,
512
528
  agentName: next.agentName ?? null,
529
+ skill: next.skill ?? null,
513
530
  baseUrl: next.baseUrl ?? null
514
531
  },
515
532
  doc: doc(
@@ -519,6 +536,7 @@ var authCommand = {
519
536
  items: fields(
520
537
  next.apiKey ? field("api key", maskKey(next.apiKey)) : void 0,
521
538
  next.agentName ? field("agent", next.agentName) : void 0,
539
+ next.skill ? field("skill", next.skill) : void 0,
522
540
  next.baseUrl ? field("base url", next.baseUrl) : void 0
523
541
  )
524
542
  }
@@ -534,6 +552,7 @@ var authCommand = {
534
552
  apiKey: resolved ? maskKey(resolved) : null,
535
553
  apiKeySource: context.apiKeySource,
536
554
  agentName: context.agentName ?? null,
555
+ skill: context.skill ?? null,
537
556
  baseUrl: context.baseUrl ?? null
538
557
  },
539
558
  doc: doc(
@@ -544,6 +563,7 @@ var authCommand = {
544
563
  field("source", resolved ? context.apiKeySource : "none"),
545
564
  field("config", path),
546
565
  context.agentName ? field("agent", context.agentName) : void 0,
566
+ context.skill ? field("skill", context.skill) : void 0,
547
567
  context.baseUrl ? field("base url", context.baseUrl) : void 0
548
568
  )
549
569
  },
@@ -1008,7 +1028,7 @@ var flowsCommand = {
1008
1028
  };
1009
1029
 
1010
1030
  // src/version.ts
1011
- var VERSION = "0.43.0";
1031
+ var VERSION = "0.44.0";
1012
1032
 
1013
1033
  // src/resources/analyst.ts
1014
1034
  var Analyst = class {
@@ -2190,7 +2210,12 @@ var GLOBAL_FLAGS = {
2190
2210
  agent: {
2191
2211
  type: "string",
2192
2212
  placeholder: "name",
2193
- describe: "Label this call in the User-Agent"
2213
+ describe: "Name your agent in the User-Agent, if you want to"
2214
+ },
2215
+ skill: {
2216
+ type: "string",
2217
+ placeholder: "slug",
2218
+ describe: "Name the skill driving this call, if you want to"
2194
2219
  }
2195
2220
  };
2196
2221
  var SHORT_FLAGS = {
@@ -2325,6 +2350,7 @@ function resolveContext({ flags, env, configDir }) {
2325
2350
  const key = pick(flagString(flags, "api-key"), env.SENTISENSE_API_KEY, stored.apiKey);
2326
2351
  const base = pick(flagString(flags, "base-url"), env.SENTISENSE_BASE_URL, stored.baseUrl);
2327
2352
  const agent = pick(flagString(flags, "agent"), env.SENTISENSE_AGENT_NAME, stored.agentName);
2353
+ const skill = pick(flagString(flags, "skill"), env.SENTISENSE_SKILL, stored.skill);
2328
2354
  return {
2329
2355
  configDir: dir,
2330
2356
  apiKey: key.value,
@@ -2332,21 +2358,27 @@ function resolveContext({ flags, env, configDir }) {
2332
2358
  baseUrl: base.value,
2333
2359
  baseUrlSource: base.source,
2334
2360
  agentName: agent.value,
2335
- agentSource: agent.source
2361
+ agentSource: agent.source,
2362
+ skill: skill.value,
2363
+ skillSource: skill.source
2336
2364
  };
2337
2365
  }
2338
2366
  var DEFAULT_BASE_URL2 = "https://app.sentisense.ai";
2339
2367
  function effectiveBaseUrl(context) {
2340
2368
  return context.baseUrl ?? DEFAULT_BASE_URL2;
2341
2369
  }
2342
- function sanitizeAgent(name) {
2343
- return name.trim().replace(/\s+/g, "-").replace(/[^A-Za-z0-9._-]/g, "");
2370
+ var MAX_IDENTITY = 32;
2371
+ function sanitizeIdentity(value) {
2372
+ return value.trim().replace(/\s+/g, "-").replace(/[^A-Za-z0-9._-]/g, "").replace(/-{2,}/g, "-").slice(0, MAX_IDENTITY).replace(/^-+|-+$/g, "");
2344
2373
  }
2345
2374
  function userAgentSuffix(context) {
2346
- const parts = [`sentisense-cli/${VERSION}`];
2347
- const agent = context.agentName ? sanitizeAgent(context.agentName) : "";
2348
- if (agent) parts.push(`agent/${agent}`);
2349
- return parts.join(" ");
2375
+ const product = `sentisense-cli/${VERSION}`;
2376
+ const slug = sanitizeIdentity(context.skill ?? "");
2377
+ const agent = sanitizeIdentity(context.agentName ?? "");
2378
+ const comment = [];
2379
+ if (slug) comment.push(slug);
2380
+ if (agent) comment.push(`agent/${agent}`);
2381
+ return comment.length === 0 ? product : `${product} (${comment.join("; ")})`;
2350
2382
  }
2351
2383
  function createClient(context, options = {}) {
2352
2384
  if (!options.anonymous && !context.apiKey) throw new MissingKeyError();
@@ -3604,6 +3636,12 @@ function mainHelp() {
3604
3636
  "",
3605
3637
  'Run "sentisense help <command>" for flags, examples, and exit codes.',
3606
3638
  "",
3639
+ "Saying who is calling (optional):",
3640
+ " SENTISENSE_AGENT_NAME=<name> what your agent calls itself",
3641
+ " SENTISENSE_SKILL=<slug> the skill driving it",
3642
+ " Set either and requests carry that identity, so usage can be understood and the",
3643
+ " tools improved. Nothing needs them, and nothing is inferred when they are absent.",
3644
+ "",
3607
3645
  "Research data, not investment advice."
3608
3646
  ];
3609
3647
  return `${lines.join("\n")}
@@ -3872,7 +3910,7 @@ async function runCli(argv, io) {
3872
3910
  return result.exitCode ?? EXIT.OK;
3873
3911
  } catch (error) {
3874
3912
  const debug = argv.includes("--debug");
3875
- const report = describeError(error, debug);
3913
+ const report = describeError(error, debug, name);
3876
3914
  for (const line of report.lines) io.stderr(`${line}
3877
3915
  `);
3878
3916
  return report.exitCode;
package/dist/index.cjs CHANGED
@@ -1036,7 +1036,7 @@ var Trackers = class {
1036
1036
  };
1037
1037
 
1038
1038
  // src/version.ts
1039
- var VERSION = "0.43.0";
1039
+ var VERSION = "0.44.0";
1040
1040
 
1041
1041
  // src/client.ts
1042
1042
  var DEFAULT_BASE_URL = "https://app.sentisense.ai";
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/errors.ts","../src/resources/analyst.ts","../src/resources/calendar.ts","../src/resources/documents.ts","../src/resources/earnings.ts","../src/resources/entityMetrics.ts","../src/resources/etfs.ts","../src/resources/insider.ts","../src/resources/politicians.ts","../src/resources/insights.ts","../src/resources/institutional.ts","../src/resources/kb.ts","../src/resources/marketMood.ts","../src/resources/marketSummary.ts","../src/resources/screener.ts","../src/resources/stocks.ts","../src/resources/indexes.ts","../src/resources/trackers.ts","../src/version.ts","../src/client.ts"],"sourcesContent":["export { SentiSense } from \"./client.js\";\nexport { SentiSense as default } from \"./client.js\";\n\nexport type {\n AnalystConsensus,\n AnalystAction,\n AnalystEstimate,\n AnalystEarningsSurprise,\n AnalystEstimatesResponse,\n GetAnalystActionsOptions,\n GetAnalystMarketActivityOptions,\n} from \"./resources/analyst.js\";\n\n// Screener types\nexport type {\n EtfScreenerExecuteResponse,\n EtfScreenerRow,\n FeaturedScreen,\n ScreenerExecuteOptions,\n ScreenerExecuteResponse,\n ScreenerFieldCatalog,\n ScreenerFieldDescriptor,\n ScreenerFieldOption,\n ScreenerFilter,\n ScreenerPlan,\n ScreenerRow,\n ScreenerScreensResponse,\n ScreenerSort,\n} from \"./resources/screener.js\";\n\nexport type {\n GetStockInsightsRangeOptions,\n GetLatestInsightsOptions,\n GetUserInsightsOptions,\n} from \"./resources/insights.js\";\n\n// ETF aggregate types\nexport type {\n EtfInfo,\n EtfHolding,\n EtfHoldings,\n EtfAggregateCoverage,\n WeightedConsensus,\n EtfAnalystContributor,\n EtfAnalystAggregate,\n WeightedNetFlow,\n EtfInsiderContributor,\n EtfInsiderAggregate,\n EtfSentimentReading,\n EtfSentimentAggregate,\n GetEtfInsiderAggregateOptions,\n} from \"./resources/etfs.js\";\n\n// KPI types\nexport type {\n KpiDataPoint,\n KpiSeries,\n CompanyKpisData,\n KpiCoverageEntry,\n KpiCoverageResponse,\n KpiTypeEntry,\n} from \"./types.js\";\n\nexport {\n SentiSenseError,\n AuthenticationError,\n NotFoundError,\n DeepHistoryUnavailableError,\n RateLimitError,\n APIError,\n} from \"./errors.js\";\n\nexport type {\n SentiSenseOptions,\n Insight,\n InsightPreviewResponse,\n LockedInsight,\n GetInsightsOptions,\n InsiderActivitySummary,\n InsiderActivityResponse,\n InsiderTrade,\n ClusterBuy,\n GetInsiderOptions,\n AssetMetadata,\n CongressTrade,\n PoliticianSummary,\n PoliticianDetail,\n PoliticianDirectoryEntry,\n PoliticianDirectory,\n PoliticianDirectoryResponse,\n GetPoliticianActivityOptions,\n GetPoliticianMemberOptions,\n GetPoliticiansOptions,\n GetPoliticianDirectoryOptions,\n EarningsEvent,\n CalendarMeta,\n EarningsCalendarResponse,\n GetEarningsCalendarOptions,\n EarningsKpiHighlight,\n EarningsSource,\n EarningsQuarter,\n RecentEarningsEntry,\n GetEarningsSummariesOptions,\n GetRecentEarningsOptions,\n PreviewResponse,\n StockPrice,\n StockQuote,\n StockDetail,\n SimilarStock,\n StockImage,\n StockProfile,\n StockEntity,\n ChartData,\n ChartDataPoint,\n MarketStatus,\n OptionsSummary,\n OptionsAggregate,\n OptionsContext,\n OptionsOiWalls,\n OptionsWall,\n OptionsUnusualContract,\n Fundamentals,\n TtmFundamentals,\n FundamentalsPeriod,\n FundamentalsPeriodsResponse,\n ShortInterest,\n FloatInfo,\n ShortVolume,\n AISummary,\n MetricsBreakdown,\n Document,\n DocumentSearchResponse,\n DocumentSource,\n SentimentEntry,\n Story,\n StoryCluster,\n Quarter,\n InstitutionalFlow,\n InstitutionalFlows,\n InstitutionalFlowsResponse,\n Holder,\n HolderNotableChanges,\n TickerHolders,\n GetHoldersOptions,\n InstitutionSummary,\n InstitutionList,\n InstitutionListResponse,\n ListInstitutionsOptions,\n MetricType,\n MetricsOptions,\n MetricDistributionOptions,\n ServingMetric,\n MetricDistribution,\n MarketMood,\n MarketSummary,\n KBEntity,\n IndexListing,\n IndexListResponse,\n IndexConstituent,\n IndexSnapshot,\n IndexHistoryPoint,\n IndexHistoryResponse,\n TrackerListing,\n TrackerListResponse,\n TrackerSnapshot,\n TrackerSnapshotResponse,\n TrackerTableRow,\n TrackerMetricValue,\n TrackerHeadlineMetric,\n TrackerGeoEntry,\n TrackerTimeSeriesPoint,\n TrackerEvent,\n TrackerSignal,\n TrackerSourceRef,\n} from \"./types.js\";\n\nexport { VERSION } from \"./version.js\";\n","export class SentiSenseError extends Error {\n status?: number;\n code?: string;\n\n constructor(message: string, status?: number, code?: string) {\n super(message);\n this.name = \"SentiSenseError\";\n this.status = status;\n this.code = code;\n }\n}\n\nexport class AuthenticationError extends SentiSenseError {\n constructor(message: string, status: number, code?: string) {\n super(message, status, code);\n this.name = \"AuthenticationError\";\n }\n}\n\nexport class NotFoundError extends SentiSenseError {\n constructor(message: string, code?: string) {\n super(message, 404, code);\n this.name = \"NotFoundError\";\n }\n}\n\n/**\n * Thrown when a deep chart range is still being assembled.\n *\n * The API answers 202 for \"10Y\" and \"MAX\" the first time a rarely-requested stock is asked\n * for. It deliberately does not substitute a shorter range, so a successful response always\n * carries the timeframe you asked for. Retry after a few seconds.\n */\nexport class DeepHistoryUnavailableError extends SentiSenseError {\n retryAfter?: number;\n\n constructor(message: string, retryAfter?: number) {\n super(message, 202);\n this.name = \"DeepHistoryUnavailableError\";\n this.retryAfter = retryAfter;\n }\n}\n\nexport class RateLimitError extends SentiSenseError {\n /**\n * Seconds to wait before retrying, from the server's `Retry-After` header, clamped to\n * `[0.5, 120]`. Always either a finite number or `undefined`: an absent header, or one\n * carrying an HTTP-date instead of a number of seconds, leaves it undefined rather than\n * `NaN`, so `setTimeout(fn, err.retryAfter * 1000)` can never fire immediately.\n */\n retryAfter?: number;\n\n constructor(message: string, code?: string, retryAfter?: number) {\n super(message, 429, code);\n this.name = \"RateLimitError\";\n this.retryAfter = retryAfter;\n }\n}\n\nexport class APIError extends SentiSenseError {\n constructor(message: string, status: number, code?: string) {\n super(message, status, code);\n this.name = \"APIError\";\n }\n}\n","import type { APIClient } from \"../client.js\";\nimport type { PreviewResponse } from \"../types.js\";\n\nexport interface AnalystConsensus {\n ticker: string;\n currentPrice: number | null;\n targetLow: number | null;\n targetMean: number | null;\n targetHigh: number | null;\n targetMedian: number | null;\n numberOfAnalysts: number;\n upsidePercent: number | null;\n consensusLabel: string | null;\n recommendationMean: number | null;\n /** PRO-only; zero in the free preview. */\n strongBuy: number;\n /** PRO-only; zero in the free preview. */\n buy: number;\n /** PRO-only; zero in the free preview. */\n hold: number;\n /** PRO-only; zero in the free preview. */\n sell: number;\n /** PRO-only; zero in the free preview. */\n strongSell: number;\n updatedAt: string | null;\n}\n\nexport interface AnalystAction {\n ticker: string;\n actionDate: string;\n firm: string;\n /** UPGRADE, DOWNGRADE, INITIATE, REITERATE, OTHER */\n actionType: string;\n fromGrade: string | null;\n toGrade: string | null;\n}\n\nexport interface AnalystEstimate {\n /** Fiscal period descriptor (provider-specific shape). */\n [key: string]: unknown;\n}\n\nexport interface AnalystEarningsSurprise {\n /** Past report descriptor (provider-specific shape). */\n [key: string]: unknown;\n}\n\nexport interface AnalystEstimatesResponse {\n estimates: AnalystEstimate[];\n surprises: AnalystEarningsSurprise[];\n}\n\nexport interface GetAnalystActionsOptions {\n /** Days of history to return. Default 90. */\n lookbackDays?: number;\n}\n\nexport interface GetAnalystMarketActivityOptions {\n /** Days of history to return. Default 30. */\n lookbackDays?: number;\n}\n\n/**\n * Wall Street analyst coverage: aggregate price targets, recommendation distribution,\n * recent upgrade/downgrade actions, and forward EPS estimates with earnings surprise history.\n *\n * Free users receive the price target band (low/mean/high + analyst count + consensus label)\n * in full -- it powers the public projection cone. The buy/hold/sell distribution counts\n * and full action/estimate history are PRO-only.\n */\nexport class Analyst {\n constructor(private client: APIClient) {}\n\n /**\n * Get the aggregate Wall Street consensus for a ticker. Returns 404 if no\n * coverage exists.\n */\n async consensus(\n ticker: string,\n ): Promise<PreviewResponse<AnalystConsensus>> {\n return this.client.get(\n `/api/v1/analyst/${encodeURIComponent(ticker.toUpperCase())}/consensus`,\n );\n }\n\n /**\n * Get recent analyst upgrade/downgrade actions for a ticker, newest first.\n * Free users receive the 3 most recent.\n */\n async actions(\n ticker: string,\n options?: GetAnalystActionsOptions,\n ): Promise<PreviewResponse<AnalystAction[]>> {\n return this.client.get(\n `/api/v1/analyst/${encodeURIComponent(ticker.toUpperCase())}/actions`,\n options,\n );\n }\n\n /**\n * Get forward EPS estimates and earnings surprise history for a ticker.\n * Free users receive 1 estimate (current quarter) plus the 2 most recent surprises.\n */\n async estimates(\n ticker: string,\n ): Promise<PreviewResponse<AnalystEstimatesResponse>> {\n return this.client.get(\n `/api/v1/analyst/${encodeURIComponent(ticker.toUpperCase())}/estimates`,\n );\n }\n\n /**\n * Get market-wide recent analyst actions across all covered tickers, newest first.\n * Free users receive the 5 most recent.\n */\n async marketActivity(\n options?: GetAnalystMarketActivityOptions,\n ): Promise<PreviewResponse<AnalystAction[]>> {\n return this.client.get(\"/api/v1/analyst/activity\", options);\n }\n}\n","import type { APIClient } from \"../client.js\";\nimport type {\n EarningsCalendarResponse,\n GetEarningsCalendarOptions,\n PreviewResponse,\n} from \"../types.js\";\n\nexport class Calendar {\n constructor(private client: APIClient) {}\n\n /**\n * Upcoming company earnings, sorted by date.\n *\n * Key-required. A FREE key returns the current week (`isPreview: true`); a PRO\n * key returns the full forward window (about 30 days). Field richness is\n * identical across tiers: the gate is how far ahead you can see, not which\n * columns you get. On a preview, `totalCount` is the full-window event count.\n */\n async getEarnings(\n options?: GetEarningsCalendarOptions,\n ): Promise<PreviewResponse<EarningsCalendarResponse>> {\n return this.client.get(\"/api/v1/calendar/earnings\", options);\n }\n}\n","import type { APIClient } from \"../client.js\";\nimport type {\n DocumentSearchResponse,\n DocumentSource,\n GetByEntityOptions,\n GetBySourceOptions,\n GetByTickerOptions,\n GetByTickerRangeOptions,\n GetStoriesByTickerOptions,\n GetStoriesOptions,\n SearchDocumentsOptions,\n Story,\n} from \"../types.js\";\n\nexport class Documents {\n constructor(private client: APIClient) {}\n\n /** Get document metrics for a stock. The rows are in `documents`. */\n async getByTicker(ticker: string, options?: GetByTickerOptions): Promise<DocumentSearchResponse> {\n return this.client.get(`/api/v1/documents/ticker/${encodeURIComponent(ticker)}`, options);\n }\n\n /** Get document metrics for a stock within a date range. The rows are in `documents`. */\n async getByTickerRange(ticker: string, options: GetByTickerRangeOptions): Promise<DocumentSearchResponse> {\n return this.client.get(\n `/api/v1/documents/ticker/${encodeURIComponent(ticker)}/range`,\n options,\n );\n }\n\n /** Get document metrics for a KB entity. The rows are in `documents`. */\n async getByEntity(entityId: string, options?: GetByEntityOptions): Promise<DocumentSearchResponse> {\n return this.client.get(\n `/api/v1/documents/entity/${encodeURIComponent(entityId)}`,\n options,\n );\n }\n\n /** Smart search with natural language query parsing. The rows are in `documents`. */\n async search(query: string, options?: SearchDocumentsOptions): Promise<DocumentSearchResponse> {\n return this.client.get(\"/api/v1/documents/search\", { query, ...options });\n }\n\n /** Get latest document metrics from a source type. The rows are in `documents`. */\n async getBySource(source: DocumentSource, options?: GetBySourceOptions): Promise<DocumentSearchResponse> {\n return this.client.get(\n `/api/v1/documents/source/${encodeURIComponent(source)}`,\n options,\n );\n }\n\n /** Get AI-curated news story clusters. */\n async getStories(options?: GetStoriesOptions): Promise<Story[]> {\n return this.client.get(\"/api/v1/documents/stories\", options);\n }\n\n /** Get full story detail by cluster ID. */\n async getStoryDetail(clusterId: string): Promise<unknown> {\n return this.client.get(`/api/v1/documents/stories/${encodeURIComponent(clusterId)}`);\n }\n\n /** Get stories for a specific stock. */\n async getStoriesByTicker(\n ticker: string,\n options?: GetStoriesByTickerOptions,\n ): Promise<Story[]> {\n return this.client.get(\n `/api/v1/documents/stories/ticker/${encodeURIComponent(ticker)}`,\n options,\n );\n }\n\n}\n","import type { APIClient } from \"../client.js\";\nimport type {\n EarningsQuarter,\n GetEarningsSummariesOptions,\n GetRecentEarningsOptions,\n PreviewResponse,\n RecentEarningsEntry,\n} from \"../types.js\";\n\n/**\n * Earnings: what a company actually reported, after the fact.\n *\n * A quarter's results arrive as a press release, a filing, and a call, none of\n * which is a data structure. {@link getSummaries} is the assembled version, one\n * object per fiscal quarter, and {@link getRecent} is the cross-ticker view of\n * who reported lately. Pair them to drive a post-earnings sweep: list the\n * window, then pull each ticker's analysis report.\n *\n * The forward-looking half of the family lives on `client.calendar.getEarnings()`,\n * which covers scheduled dates and consensus EPS rather than results.\n *\n * @see EarningsQuarter\n */\nexport class Earnings {\n constructor(private client: APIClient) {}\n\n /**\n * Per-quarter earnings analysis report for one ticker, newest first.\n *\n * Each quarter carries the editorial headline, the KPI cards that matter for\n * that company with year-over-year deltas, the guidance language as\n * management phrased it, and a summary of the earnings call.\n *\n * Branch on `isPreview`: a PRO key receives every hydrated quarter in full, a\n * FREE key receives the latest quarter shaped rather than truncated, plus\n * `totalCount`. {@link EarningsQuarter} documents which fields each tier\n * carries.\n *\n * A quarter typically appears within 48 hours of the company reporting, and\n * the call summary can arrive after the press-release content for the same\n * quarter, so read `generatedAt` and `transcriptGeneratedAt` rather than\n * assuming a fixed lag. A ticker with no stored quarter answers with an empty\n * `data` array, not a 404.\n *\n * Use canonical ticker symbols: `GOOGL` (not `GOOG`), `BRK.B` (not `BRK-B`).\n */\n async getSummaries(\n ticker: string,\n options?: GetEarningsSummariesOptions,\n ): Promise<PreviewResponse<EarningsQuarter[]>> {\n return this.client.get(\n `/api/v1/stocks/${encodeURIComponent(ticker.toUpperCase())}/earnings-summaries`,\n options,\n );\n }\n\n /**\n * Which covered companies reported on or after `today - days`, newest first.\n *\n * Every API key receives the full window it asks for, so `isPreview` is\n * always `false` here. The window is bounded by `reportDate`, so a quarter\n * reported inside it appears even when its call summary lands later, and an\n * empty `data` array means nobody in the covered set reported in that window.\n *\n * This is the backward-looking feed; `client.calendar.getEarnings()` is the\n * forward-looking one.\n */\n async getRecent(\n options?: GetRecentEarningsOptions,\n ): Promise<PreviewResponse<RecentEarningsEntry[]>> {\n return this.client.get(\"/api/v1/earnings/recent\", options);\n }\n}\n","import type { APIClient } from \"../client.js\";\nimport type {\n MetricType,\n MetricsOptions,\n MetricDistributionOptions,\n ServingMetric,\n MetricDistribution,\n} from \"../types.js\";\n\nexport class EntityMetrics {\n constructor(private client: APIClient) {}\n\n /**\n * Get time-series metric data for an entity using the v2 Serving Metrics API.\n *\n * @param symbol Ticker symbol (e.g. \"AAPL\") or entity urlSlug (e.g. \"Nancy-Pelosi\",\n * case-insensitive; discover slugs via stocks.getEntities()).\n * @param options Metric type and optional time range / resolution.\n */\n async getMetrics(\n symbol: string,\n options: MetricsOptions = {},\n ): Promise<ServingMetric[]> {\n const { metricType = \"sentiment\", startTime, endTime, maxDataPoints } = options;\n return this.client.get(\n `/api/v2/metrics/entity/${encodeURIComponent(symbol)}/metric/${encodeURIComponent(metricType)}`,\n {\n ...(startTime !== undefined && { startTime }),\n ...(endTime !== undefined && { endTime }),\n ...(maxDataPoints !== undefined && { maxDataPoints }),\n },\n );\n }\n\n /**\n * Get distribution data for a metric, broken down by a dimension (default: source).\n *\n * @param symbol Ticker symbol (e.g. \"AAPL\") or entity urlSlug.\n * @param metricType The metric to break down (e.g. \"mentions\", \"sentiment\").\n * @param options Optional dimension parameter.\n */\n async getDistribution(\n symbol: string,\n metricType: MetricType,\n options: MetricDistributionOptions = {},\n ): Promise<MetricDistribution> {\n const { dimension = \"source\" } = options;\n return this.client.get(\n `/api/v2/metrics/entity/${encodeURIComponent(symbol)}/distribution/${encodeURIComponent(metricType)}`,\n { dimension },\n );\n }\n}\n","import type { APIClient } from \"../client.js\";\nimport type { PreviewResponse } from \"../types.js\";\n\nexport interface EtfInfo {\n ticker: string;\n name: string;\n kbEntityId: string | null;\n urlSlug: string | null;\n issuer: string | null;\n trackedIndex: string | null;\n assetClass: string | null;\n}\n\nexport interface EtfHolding {\n ticker: string;\n name: string | null;\n /** Weight in the fund as a percentage (0-100). */\n weightPct: number;\n /** ISO date \"YYYY-MM-DD\". First date this holding appeared in the composition. */\n firstSeen: string | null;\n}\n\nexport interface EtfHoldings {\n ticker: string;\n issuer: string;\n issuerEndpoint: string | null;\n /** ISO date \"YYYY-MM-DD\". Composition snapshot date from the issuer. */\n asOfDate: string;\n /** Epoch seconds when SentiSense refreshed the composition. */\n fetchedAt: number | null;\n /** ISO date \"YYYY-MM-DD\". When the composition is scheduled to be refreshed next. */\n nextRefreshDue: string;\n totalHoldings: number;\n holdings: EtfHolding[];\n /** True when this is a top-N view rather than the full fund. */\n partial?: boolean | null;\n /** Issuer's reported total holdings when `partial=true`. */\n totalKnownHoldings?: number | null;\n}\n\nexport interface EtfAggregateCoverage {\n holdingsCount: number;\n holdingsCovered: number;\n /** Sum of weights (0-100) for the covered holdings. */\n weightCovered: number;\n partial?: boolean | null;\n totalKnownHoldings?: number | null;\n}\n\nexport interface WeightedConsensus {\n upsidePercent: number | null;\n consensusLabel: string | null;\n /** Fractions of covered AUM in each bucket. Sums to ~1.0. */\n distribution: Record<string, number>;\n totalAnalysts: number;\n}\n\nexport interface EtfAnalystContributor {\n ticker: string;\n weightPct: number;\n upsidePercent: number | null;\n consensusLabel: string | null;\n /** Signed contribution to the fund's weighted upside in percentage points. */\n contributionPp: number;\n}\n\nexport interface EtfAnalystAggregate {\n ticker: string;\n /** ISO date \"YYYY-MM-DD\". Composition snapshot date. */\n asOfDate: string | null;\n /** Epoch seconds when this rollup was computed. */\n computedAt: number;\n coverage: EtfAggregateCoverage;\n weightedConsensus: WeightedConsensus;\n /** Top contributors (up to 10) by absolute contribution to the weighted upside. */\n topContributors: EtfAnalystContributor[];\n}\n\nexport interface WeightedNetFlow {\n /** Weighted net dollar flow (buys - sells). Negative = net selling. */\n netDollars: number;\n buyDollars: number;\n sellDollars: number;\n /** Unweighted; for context. */\n buyTradeCount: number;\n /** Unweighted; for context. */\n sellTradeCount: number;\n distinctInsiderCount: number;\n}\n\nexport interface EtfInsiderContributor {\n ticker: string;\n weightPct: number;\n /** Per-stock net flow over the window (signed). */\n netDollars: number;\n /** Signed contribution to the weighted headline. */\n weightedNetDollars: number;\n tradeCount: number;\n}\n\nexport interface EtfInsiderAggregate {\n ticker: string;\n /** ISO date \"YYYY-MM-DD\". Composition snapshot date. */\n asOfDate: string | null;\n /** Epoch seconds when this rollup was computed. */\n computedAt: number;\n lookbackDays: number;\n coverage: EtfAggregateCoverage;\n weightedNetFlow: WeightedNetFlow;\n /** Top contributors (up to 10) by absolute weighted-net-dollar contribution. */\n topContributors: EtfInsiderContributor[];\n}\n\nexport interface EtfSentimentReading {\n sentiSenseScore: number | null;\n /** BULLISH / NEUTRAL / BEARISH. */\n scoreLabel: string;\n /** Epoch seconds when the underlying metric was produced. */\n asOfTimestamp: number | null;\n}\n\nexport interface EtfSentimentAggregate {\n ticker: string;\n /** ISO date \"YYYY-MM-DD\". Composition snapshot date. */\n asOfDate: string | null;\n /** Epoch seconds when this aggregate was assembled. */\n computedAt: number;\n coverage: EtfAggregateCoverage;\n /** Holdings-weighted SentiSense across the fund's constituents. */\n constituentsWeighted: EtfSentimentReading;\n /** Direct reading from mentions of the fund's own ticker. Null for low-mention funds. */\n direct: EtfSentimentReading | null;\n}\n\nexport interface GetEtfInsiderAggregateOptions {\n /** Trailing window for the trade aggregation. Typical values: 30, 90. Default 30. */\n lookbackDays?: number;\n}\n\n/**\n * ETF discovery, composition (holdings), and holdings-weighted aggregate views.\n *\n * Funds aren't rated by analysts directly, don't have insiders of their own, and\n * may not get many direct news mentions -- but the companies inside them do. The\n * aggregate endpoints synthesize fund-level views from each constituent's per-stock\n * data, weighted by allocation, with a coverage block so consumers see how much of\n * the fund's AUM the underlying data covered.\n *\n * Beta as of 2026-05-15: starting with a limited set of widely-traded funds.\n */\nexport class Etfs {\n constructor(private client: APIClient) {}\n\n /**\n * List every ETF tracked by SentiSense, sorted by ticker.\n */\n async list(): Promise<EtfInfo[]> {\n return this.client.get(\"/api/v1/etfs\");\n }\n\n /**\n * Get the full holdings composition for an ETF, including per-holding weights\n * and freshness metadata. Returns 404 for unknown ETFs or commodity-only funds.\n */\n async holdings(ticker: string): Promise<EtfHoldings> {\n return this.client.get(\n `/api/v1/etfs/${encodeURIComponent(ticker.toUpperCase())}/holdings`,\n );\n }\n\n /**\n * Get the holdings-weighted analyst consensus for an ETF, including the\n * top per-holding contributors that drive the weighted upside.\n */\n async analystAggregate(\n ticker: string,\n ): Promise<PreviewResponse<EtfAnalystAggregate>> {\n return this.client.get(\n `/api/v1/etfs/${encodeURIComponent(ticker.toUpperCase())}/aggregates/analyst`,\n );\n }\n\n /**\n * Get the holdings-weighted SEC Form 4 insider aggregate for an ETF over a\n * configurable trailing window, including per-holding `topContributors` with\n * signed contribution to the weighted headline.\n */\n async insiderAggregate(\n ticker: string,\n options?: GetEtfInsiderAggregateOptions,\n ): Promise<PreviewResponse<EtfInsiderAggregate>> {\n return this.client.get(\n `/api/v1/etfs/${encodeURIComponent(ticker.toUpperCase())}/aggregates/insider`,\n options,\n );\n }\n\n /**\n * Get two SentiSense Score readings side-by-side: `constituentsWeighted`\n * (precomputed daily weighted average across the fund's holdings) and `direct`\n * (score from mentions of the fund's own ticker). The two can diverge, and the\n * gap is itself information.\n */\n async sentimentAggregate(\n ticker: string,\n ): Promise<PreviewResponse<EtfSentimentAggregate>> {\n return this.client.get(\n `/api/v1/etfs/${encodeURIComponent(ticker.toUpperCase())}/aggregates/sentiment`,\n );\n }\n}\n","import type { APIClient } from \"../client.js\";\nimport type {\n InsiderActivityResponse,\n InsiderTrade,\n ClusterBuy,\n GetInsiderOptions,\n PreviewResponse,\n} from \"../types.js\";\n\nexport class Insider {\n constructor(private client: APIClient) {}\n\n /**\n * Get market-wide insider activity: top buys and sells aggregated by ticker.\n *\n * PRO-gated. Free-tier users receive a preview (top 5 per direction)\n * with `isPreview: true` in the response.\n */\n async getActivity(options?: GetInsiderOptions): Promise<PreviewResponse<InsiderActivityResponse>> {\n return this.client.get(\"/api/v1/insider/activity\", options);\n }\n\n /**\n * Get individual insider transactions for a specific stock.\n *\n * PRO-gated. Free users receive a preview of the top 5 transactions.\n */\n async getTrades(ticker: string, options?: GetInsiderOptions): Promise<PreviewResponse<InsiderTrade[]>> {\n return this.client.get(\n `/api/v1/insider/trades/${encodeURIComponent(ticker.toUpperCase())}`,\n options,\n );\n }\n\n /**\n * Get cluster buy signals: stocks where 3+ distinct insiders bought recently.\n *\n * PRO-gated. Free users receive a preview of the top 3 signals.\n */\n async getClusterBuys(options?: GetInsiderOptions): Promise<PreviewResponse<ClusterBuy[]>> {\n return this.client.get(\"/api/v1/insider/cluster-buys\", options);\n }\n}\n","import type { APIClient } from \"../client.js\";\nimport type {\n CongressTrade,\n PoliticianSummary,\n PoliticianDetail,\n GetPoliticianActivityOptions,\n GetPoliticiansOptions,\n GetPoliticianDirectoryOptions,\n GetPoliticianMemberOptions,\n PoliticianDirectory,\n PoliticianDirectoryResponse,\n PreviewResponse,\n} from \"../types.js\";\n\nexport class Politicians {\n constructor(private client: APIClient) {}\n\n /**\n * Get recent congressional STOCK Act trading activity across all politicians.\n *\n * PRO-gated. Free-tier users receive a preview (top 5 trades)\n * with `isPreview: true` in the response.\n *\n * The feed is longer than one response: a default 90-day window is routinely well over a\n * thousand disclosures, and without `limit` the server sends the first 200 with no marker\n * that it stopped. `totalCount` on the envelope is the real size on every tier, so page\n * with `limit` and `offset` rather than reading `data.length` as the total.\n *\n * ```typescript\n * const first = await client.politicians.getActivity({ limit: 100 });\n * for (let offset = 100; offset < first.totalCount!; offset += 100) {\n * const page = await client.politicians.getActivity({ limit: 100, offset });\n * // ... page.data\n * }\n * ```\n */\n async getActivity(\n options?: GetPoliticianActivityOptions,\n ): Promise<PreviewResponse<CongressTrade[]>> {\n return this.client.get(\"/api/v1/politicians/activity\", options);\n }\n\n /**\n * Get congressional trades for a specific stock.\n *\n * PRO-gated. Free users receive a preview of the top 3 trades.\n */\n async getFilings(\n ticker: string,\n options?: GetPoliticiansOptions,\n ): Promise<PreviewResponse<CongressTrade[]>> {\n return this.client.get(\n `/api/v1/politicians/filings/${encodeURIComponent(ticker.toUpperCase())}`,\n options,\n );\n }\n\n /**\n * Discover tracked members of Congress and the page slug identifying each, so you\n * can find who to query without knowing slugs upfront.\n *\n * Summary only, no trade data; use `getMember` for a member's filings.\n *\n * Unlike `getMembers`, this includes members who have **left Congress**, carrying\n * `former` and `servedUntil`. That roster lists who currently holds office, so a\n * former member is otherwise reachable only if you already know their slug.\n *\n * Requires an API key but does not consume monthly quota (per-minute rate limits\n * still apply), and is not tier-gated. Returns the unwrapped list payload.\n */\n async getDirectory(\n options?: GetPoliticianDirectoryOptions,\n ): Promise<PoliticianDirectory> {\n const resp = await this.client.get<PoliticianDirectoryResponse>(\n \"/api/v1/politicians/directory\",\n { ...options },\n );\n return resp.data;\n }\n\n /**\n * Get all tracked politicians with trading summary statistics.\n *\n * PRO-gated. Free users receive a preview of the top 5 members.\n *\n * Serves only members currently in office. Use `getDirectory` to enumerate\n * everyone tracked, former members included.\n */\n async getMembers(): Promise<PreviewResponse<PoliticianSummary[]>> {\n return this.client.get(\"/api/v1/politicians/members\");\n }\n\n /**\n * Get detailed profile for a single politician: summary, recent trades, top tickers.\n *\n * PRO-gated. Free users receive a preview-wrapped response.\n *\n * `data.recentTrades` is one page of the member's history, not all of it. Most members\n * have a few dozen disclosures and arrive complete in the default page; a handful have\n * thousands. `totalCount` on the envelope is the size of the whole history on every\n * tier, so page with `limit` and `offset` rather than reading `recentTrades.length` as\n * the total. `data.profile` and `data.topTickers` describe the whole history whatever\n * page you ask for, so `profile.totalTrades` does not shrink with a small `limit`.\n *\n * ```typescript\n * const first = await client.politicians.getMember(\"Ro-Khanna\", { limit: 500 });\n * for (let offset = 500; offset < first.totalCount!; offset += 500) {\n * const page = await client.politicians.getMember(\"Ro-Khanna\", { limit: 500, offset });\n * // ... page.data.recentTrades\n * }\n * ```\n */\n async getMember(\n slug: string,\n options?: GetPoliticianMemberOptions,\n ): Promise<PreviewResponse<PoliticianDetail>> {\n return this.client.get(\n `/api/v1/politicians/member/${encodeURIComponent(slug)}`,\n options,\n );\n }\n}\n","import type { APIClient } from \"../client.js\";\nimport type {\n Insight,\n GetInsightsOptions,\n PreviewResponse,\n} from \"../types.js\";\n\nexport interface GetStockInsightsRangeOptions {\n startDate: string;\n endDate: string;\n urgency?: \"low\" | \"medium\" | \"high\";\n insightType?: string;\n}\n\nexport interface GetLatestInsightsOptions {\n limit?: number;\n urgency?: \"low\" | \"medium\" | \"high\";\n}\n\nexport interface GetUserInsightsOptions {\n limit?: number;\n category?: string;\n}\n\nexport class Insights {\n constructor(private client: APIClient) {}\n\n /**\n * Get AI-generated insights for a specific stock, sorted by urgency then confidence.\n *\n * Returns the preview envelope: read the insights as `.data`. PRO callers get the\n * full list with `isPreview: false`; free callers get the top 3 with `isPreview: true`\n * and `totalCount` carrying the untruncated size.\n */\n async stock(\n ticker: string,\n options?: GetInsightsOptions,\n ): Promise<PreviewResponse<Insight[]>> {\n return this.client.get(\n `/api/v1/insights/stock/${encodeURIComponent(ticker.toUpperCase())}`,\n options,\n );\n }\n\n /**\n * Get AI insights for a stock within a date range.\n *\n * Returns the preview envelope: read the insights as `.data`. Free callers receive\n * the top 3, PRO callers the full list. The server returns 400 if `startDate` is\n * after `endDate`.\n */\n async stockRange(\n ticker: string,\n options: GetStockInsightsRangeOptions,\n ): Promise<PreviewResponse<Insight[]>> {\n return this.client.get(\n `/api/v1/insights/stock/${encodeURIComponent(ticker.toUpperCase())}/range`,\n options,\n );\n }\n\n /**\n * Get AI-generated market-level insights, sorted by urgency then confidence.\n *\n * Returns the preview envelope: read the insights as `.data`. PRO callers get the\n * full list with `isPreview: false`; free callers get the top 5 with `isPreview: true`\n * and `totalCount` carrying the untruncated size.\n */\n async market(): Promise<PreviewResponse<Insight[]>> {\n return this.client.get(\"/api/v1/insights/market\");\n }\n\n /**\n * Get the latest AI insights across all tracked stocks, newest first.\n *\n * Returns the preview envelope: read the insights as `.data`. Free callers receive\n * the top 5, PRO callers up to `limit` (clamped to 1-200).\n */\n async latest(\n options?: GetLatestInsightsOptions,\n ): Promise<PreviewResponse<Insight[]>> {\n return this.client.get(\"/api/v1/insights/latest\", options);\n }\n\n /**\n * Get personalized insights for the authenticated user.\n *\n * Biased toward the user's watchlist and portfolio when available; falls back\n * to market-level insights otherwise. API key authentication required.\n * Returns the preview envelope: read the insights as `.data`.\n */\n async user(\n options?: GetUserInsightsOptions,\n ): Promise<PreviewResponse<Insight[]>> {\n return this.client.get(\"/api/v1/insights/user\", options);\n }\n\n /**\n * Get available insight types for a specific stock.\n * API key required.\n *\n * Returns an array of insight type strings (e.g., `[\"sentiment_shift\", \"options_activity\"]`).\n */\n async types(ticker: string): Promise<string[]> {\n return this.client.get(\n `/api/v1/insights/stock/${encodeURIComponent(ticker.toUpperCase())}/types`,\n );\n }\n}\n","import type { APIClient } from \"../client.js\";\nimport type {\n GetFlowsOptions,\n GetHoldersOptions,\n Holder,\n InstitutionList,\n InstitutionListResponse,\n InstitutionalFlows,\n ListInstitutionsOptions,\n PreviewResponse,\n Quarter,\n TickerHolders,\n} from \"../types.js\";\n\nexport class Institutional {\n constructor(private client: APIClient) {}\n\n /** Get available 13F reporting quarters. */\n async getQuarters(): Promise<Quarter[]> {\n return this.client.get(\"/api/v1/institutional/quarters\");\n }\n\n /**\n * Get aggregate institutional activity per ticker for a quarter.\n *\n * `reportDate` is optional: omit it to get the latest available quarter, which may be\n * a still-open one holding only early filers. The response then carries `reportDate`\n * plus `isPending` and filer coverage counts so a partial quarter is clearly labeled.\n *\n * Returns the preview envelope, so the flows are one level down:\n * `const { data } = await client.institutional.getFlows(); data.inflows`.\n */\n async getFlows(\n reportDate?: string,\n options?: GetFlowsOptions,\n ): Promise<PreviewResponse<InstitutionalFlows>> {\n return this.client.get(\"/api/v1/institutional/flows\", {\n reportDate,\n ...options,\n });\n }\n\n /**\n * Get institutional holders for a specific stock.\n *\n * Returns the preview envelope wrapping a {@link TickerHolders} object, so the rows\n * are two levels down: `(await getHolders(t, d)).data.holders`, alongside ticker-level\n * totals like `holderCount`. Free callers get a truncated `holders` array with\n * `isPreview: true`.\n *\n * A widely held ticker returns thousands of rows: a megacap quarter is about\n * 6,000 holders and 1.5 MB. Pass `limit` unless you really want all of them.\n * Omitting `options` sends the original unbounded request.\n *\n * `limit` is the switch for the whole option set. With it, the response also carries\n * `returnedCount`, `offset`, and a `notableChanges` summary, so you can walk the list\n * without re-counting it. Without it, `offset` / `sortBy` / `sortDir` are ignored by the\n * server and you get the full unsorted list back with a 200.\n */\n async getHolders(\n ticker: string,\n reportDate: string,\n options?: GetHoldersOptions,\n ): Promise<PreviewResponse<TickerHolders>> {\n return this.client.get(\n `/api/v1/institutional/holders/${encodeURIComponent(ticker)}`,\n { reportDate, ...options },\n );\n }\n\n /**\n * Get activist investor positions (NEW or INCREASED).\n *\n * Returns the preview envelope, so read the rows as `.data`.\n */\n async getActivists(reportDate: string): Promise<PreviewResponse<Holder[]>> {\n return this.client.get(\"/api/v1/institutional/activist\", { reportDate });\n }\n\n /**\n * Discover institutions: a paginated, AUM-ranked list of filers (slug + metadata)\n * so you can find what to query without knowing slugs upfront.\n *\n * Each institution is rolled up by parent filer, so a multi-filer manager\n * (e.g. Vanguard) appears once with combined AUM. Summary only; use\n * `getInstitutionDetail` for a filer's full holdings.\n *\n * Requires an API key but does not consume monthly quota (per-minute rate\n * limits still apply). Returns the unwrapped list payload.\n */\n async listInstitutions(options?: ListInstitutionsOptions): Promise<InstitutionList> {\n const resp = await this.client.get<InstitutionListResponse>(\n \"/api/v1/institutional/institutions\",\n { ...options },\n );\n return resp.data;\n }\n\n /**\n * Get the full profile, summary stats, and current-quarter holdings for a\n * specific institutional filer.\n *\n * Resolved by URL slug (e.g. `Berkshire-Hathaway`) or numeric SEC CIK.\n * Free users receive the profile and top 10 holdings; PRO users receive the\n * full holdings array. Returns 404 if the slug or CIK is unknown.\n */\n async getInstitutionDetail(slugOrCik: string): Promise<unknown> {\n return this.client.get(\n `/api/v1/institutional/institution/${encodeURIComponent(slugOrCik)}`,\n );\n }\n}\n","import type { APIClient } from \"../client.js\";\nimport type { KBEntity } from \"../types.js\";\n\nexport class KB {\n constructor(private client: APIClient) {}\n\n /** Get popular entities for search suggestions. */\n async getPopularEntities(): Promise<KBEntity[]> {\n return this.client.get(\"/api/v1/kb/entities/popular\");\n }\n}\n","import type { APIClient } from \"../client.js\";\nimport type { MarketMood } from \"../types.js\";\n\nexport class MarketMoodResource {\n constructor(private client: APIClient) {}\n\n /** Get market mood data (scores, history, sectors). */\n async get(): Promise<MarketMood> {\n return this.client.get(\"/api/v2/market-mood\");\n }\n\n // TODO: accept a `days` param to control history length (the endpoint supports ?days=N).\n //\n // Market Mood is also reachable through `client.indexes`, which serves it in the shared\n // index envelope alongside fed-sentiment and ai-sentiment. Use this resource when you want\n // the phase band, weekly change, per-signal breakdown and per-sector map; use `indexes`\n // when you want every index to answer the same shape. Both report the same headline number.\n}\n","import type { APIClient } from \"../client.js\";\nimport type { MarketSummary } from \"../types.js\";\n\nexport class MarketSummaryResource {\n constructor(private client: APIClient) {}\n\n /** Get the AI-generated market summary with headline and analysis. */\n async get(): Promise<MarketSummary> {\n return this.client.get(\"/api/v1/market-summary\");\n }\n}\n","import type { APIClient } from \"../client.js\";\nimport type {\n EtfScreenerExecuteResponse,\n EtfScreenerRow,\n FeaturedScreen,\n ScreenerExecuteOptions,\n ScreenerExecuteResponse,\n ScreenerFieldCatalog,\n ScreenerFieldDescriptor,\n ScreenerFieldOption,\n ScreenerFilter,\n ScreenerPlan,\n ScreenerRow,\n ScreenerScreensResponse,\n ScreenerSort,\n} from \"../types.js\";\n\n/**\n * Screener: filter the tracked universe on the SentiSense Score, attention,\n * analyst consensus, technicals and price in a single query. It is the one\n * surface where our own signals sit in the same `WHERE` clause as the market\n * data, which is the point: screening on analyst ratings alone is something a\n * dozen free tools do, screening on analyst ratings *where the Score disagrees*\n * is not.\n *\n * Every screen is a {@link ScreenerPlan}. Take one from {@link screens} or\n * build your own, then hand it to {@link run} or {@link runEtfs}.\n *\n * Three field semantics are worth knowing before you write a filter, because\n * guessing them wrong produces a screen that looks fine and means nothing:\n *\n * - **`ANALYST_RATING_MEAN` is inverted.** It is the vendor's 1-to-5 scale\n * where `1.0` is strong buy, so bullish is `LTE 2.5`, not `GTE`. Prefer\n * `ANALYST_BUY_RATIO_PCT`, which runs the intuitive direction.\n * - **`MA_CROSS_STATE` is ordinal**, not a percentage: `1` golden cross (50-day\n * above 200-day), `-1` death cross, `0` neither. Use `EQ`.\n * - **`SENTIMENT_DIRECTION` is the sign of the 7-day SentiSense Score**\n * (`1` / `0` / `-1`) with a neutral band of plus-or-minus 5. Despite the name\n * it is not sentiment polarity, and `0` matches only an exact zero, so it\n * returns almost nothing.\n *\n * The Score fields (`SENTI_SCORE_7D`, `SENTI_SCORE_1M`, `SCORE_CHANGE_7D`) are\n * the SentiSense Score, not polarity: unbounded, banded at 5 / 13 / 23 either\n * side of zero. Filter on those band edges, not on values like `0.5`, which\n * behave as \"any positive score\".\n *\n * Nulls never match, in either direction: `RETURN_1Y >= 0` and `RETURN_1Y < 0`\n * do not partition the universe, because a stock listed four months ago is in\n * neither result. If a screen returns fewer rows than you expect, check\n * coverage before you check your thresholds.\n *\n * Screens read a snapshot that refreshes every 20 minutes, so this is not a\n * quote feed. Use `client.stocks.getQuote()` for live prices.\n */\nexport class Screener {\n constructor(private client: APIClient) {}\n\n /**\n * Every filterable field, with its unit, operators and description, for both\n * universes.\n *\n * Build a filter UI from this rather than hardcoding the list and you inherit\n * new fields as they ship. The ETF `STRING` fields (`ISSUER`, `ASSET_CLASS`,\n * `TRACKED_INDEX`) come back with their `values` populated from the live\n * universe, so pickers stay current without a redeploy.\n */\n async fields(): Promise<ScreenerFieldCatalog> {\n return this.client.get(\"/api/v1/screener/fields\");\n }\n\n /**\n * The curated screens shipped in the product, each with a runnable plan.\n *\n * Each `plan` round-trips straight into {@link run} (or {@link runEtfs} when\n * `plan.universe === \"ETF\"`) with nothing to rebuild.\n *\n * Their filters identify the field with `field` rather than `fieldName`.\n * Both keys are accepted on the way in, so read either when inspecting a plan\n * you did not build yourself.\n */\n async screens(): Promise<ScreenerScreensResponse> {\n return this.client.get(\"/api/v1/screener/screens\");\n }\n\n /**\n * Run a screen against the stock universe.\n *\n * `tickers` is optional: omit it to screen the whole tracked universe, pass a\n * list to screen a watchlist. `limit` sits next to the plan rather than\n * inside it, because a plan is a stored object and paging is a transport\n * concern; it defaults to 100 and caps at 500.\n *\n * Read `matched` before you read `results`: it is the count before `limit`\n * was applied, so a `matched` above your `limit` means you are holding the\n * top slice under the plan's sort, not the whole answer.\n *\n * @example\n * ```ts\n * const res = await client.screener.run({\n * plan: {\n * filters: [\n * { fieldName: \"SENTI_SCORE_7D\", op: \"GTE\", value: 13 },\n * { fieldName: \"ANALYST_BUY_RATIO_PCT\", op: \"LTE\", value: 30 },\n * { fieldName: \"ANALYST_COUNT\", op: \"GTE\", value: 5 },\n * ],\n * sort: { fieldName: \"SENTI_SCORE_7D\", dir: \"DESC\" },\n * },\n * limit: 25,\n * });\n * ```\n */\n async run(options: ScreenerExecuteOptions): Promise<ScreenerExecuteResponse> {\n return this.client.post(\"/api/v1/screener/execute\", options);\n }\n\n /**\n * Run a screen against the ETF universe.\n *\n * Same request shape as {@link run}, against a different field vocabulary:\n * take the ETF names from `fields().etf`. `IN` / `NOT_IN` take a `values`\n * array instead of `value` and are the operators for the string fields\n * (`ISSUER`, `ASSET_CLASS`, `TRACKED_INDEX`).\n *\n * `CONSTITUENTS_WEIGHTED_SENTISENSE` is the holdings-weighted SentiSense\n * Score across what the fund owns and is usually the one you want;\n * `DIRECT_SENTISENSE` is the Score from chatter about the fund ticker itself,\n * which on a broad index fund is mostly macro noise. `WEIGHT_COVERED_PCT`\n * tells you how much of the fund's weight had constituent data behind the\n * weighted number.\n */\n async runEtfs(options: ScreenerExecuteOptions): Promise<EtfScreenerExecuteResponse> {\n return this.client.post(\"/api/v1/screener/etfs/execute\", options);\n }\n}\n\n// Re-export for convenience so callers can `import type { ScreenerPlan }`\n// from the resource module instead of `../types`.\nexport type {\n EtfScreenerExecuteResponse,\n EtfScreenerRow,\n FeaturedScreen,\n ScreenerExecuteOptions,\n ScreenerExecuteResponse,\n ScreenerFieldCatalog,\n ScreenerFieldDescriptor,\n ScreenerFieldOption,\n ScreenerFilter,\n ScreenerPlan,\n ScreenerRow,\n ScreenerScreensResponse,\n ScreenerSort,\n};\n","import type { APIClient } from \"../client.js\";\nimport type {\n AISummary,\n ChartData,\n ChartDataPoint,\n CompanyKpisData,\n FloatInfo,\n Fundamentals,\n FundamentalsPeriodsResponse,\n TtmFundamentals,\n GetAISummaryOptions,\n GetChartOptions,\n GetDescriptionsOptions,\n GetFundamentalsOptions,\n GetImagesOptions,\n GetMetricsBreakdownOptions,\n GetProfileOptions,\n GetSimilarOptions,\n KpiCoverageResponse,\n KpiTypeEntry,\n MarketStatus,\n MetricsBreakdown,\n OptionsSummary,\n PreviewResponse,\n SimilarStock,\n ShortInterest,\n ShortVolume,\n StockDetail,\n StockEntity,\n StockSentiment,\n StockImage,\n StockPrice,\n StockProfile,\n StockQuote,\n} from \"../types.js\";\n\nexport class Stocks {\n constructor(private client: APIClient) {}\n\n /** List all available ticker symbols. */\n async list(): Promise<string[]> {\n return this.client.get(\"/api/v1/stocks\");\n }\n\n /** List all stocks with name, kbEntityId, urlSlug. */\n async listDetailed(): Promise<StockDetail[]> {\n return this.client.get(\"/api/v1/stocks/detailed\");\n }\n\n /** Get popular ticker symbols. */\n async listPopular(): Promise<string[]> {\n return this.client.get(\"/api/v1/stocks/popular\");\n }\n\n /** Get popular stocks with details. */\n async listPopularDetailed(): Promise<StockDetail[]> {\n return this.client.get(\"/api/v1/stocks/popular/detailed\");\n }\n\n /** Get real-time price for a single ticker. */\n async getPrice(ticker: string): Promise<StockPrice> {\n return this.client.get(\"/api/v1/stocks/price\", { ticker });\n }\n\n /**\n * Get aggregate quote snapshot: live price, today OHLC, 52-week range,\n * market cap, P/E, EPS TTM, and dividend yield in a single call.\n * All fields except `ticker` may be null when upstream data is unavailable.\n */\n async getQuote(ticker: string): Promise<StockQuote> {\n return this.client.get(`/api/v1/stocks/${encodeURIComponent(ticker)}/quote`);\n }\n\n /** Get real-time prices for multiple tickers. */\n async getPrices(tickers: string[]): Promise<StockPrice[]> {\n return this.client.get(\"/api/v1/stocks/prices\", {\n tickers: tickers.join(\",\"),\n });\n }\n\n /** Get batch company logo URLs. */\n async getImages(\n tickers: string[],\n options?: GetImagesOptions,\n ): Promise<Record<string, StockImage>> {\n return this.client.get(\"/api/v1/stocks/images\", {\n tickers: tickers.join(\",\"),\n ...options,\n });\n }\n\n /** Get company profiles with branding, market cap, sector. */\n async getDescriptions(\n tickers: string[],\n options?: GetDescriptionsOptions,\n ): Promise<Record<string, StockProfile>> {\n return this.client.get(\"/api/v1/stocks/descriptions\", {\n tickers: tickers.join(\",\"),\n ...options,\n });\n }\n\n /** Get peer/similar stocks. */\n async getSimilar(ticker: string, options?: GetSimilarOptions): Promise<SimilarStock[]> {\n return this.client.get(`/api/v1/stocks/${encodeURIComponent(ticker)}/similar`, options);\n }\n\n /** Get company profile (CEO, sector, industry, market data). */\n async getProfile(ticker: string, options?: GetProfileOptions): Promise<StockProfile> {\n return this.client.get(`/api/v1/stocks/${encodeURIComponent(ticker)}/profile`, options);\n }\n\n /**\n * Get the headline sentiment picture for a stock in one call.\n *\n * Returns the SentiSense Score with its 30-day regime, mention volume and social\n * dominance, per-source tone in `bySource`, plus related tickers, story drivers, a\n * narrative and an FAQ. Available in full on every API-key tier.\n *\n * Use `entityMetrics.getMetrics(ticker, \"sentiment\", ...)` instead when you need a time\n * series over a specific window rather than the headline read. Returns 404 for tickers\n * with no sentiment coverage.\n */\n async getSentiment(ticker: string): Promise<PreviewResponse<StockSentiment>> {\n return this.client.get(\n `/api/v1/stocks/${encodeURIComponent(ticker)}/sentiment`,\n );\n }\n\n /** Get related KB entities (people, products, partners). */\n async getEntities(ticker: string): Promise<StockEntity[]> {\n return this.client.get(`/api/v1/stocks/${encodeURIComponent(ticker)}/entities`);\n }\n\n /**\n * Get AI-generated stock analysis report. Requires PRO tier.\n *\n * `depth: \"deep\"` returns the full curated report and consumes one report view on\n * metered tiers; the default `\"basic\"` returns the one-paragraph summary.\n *\n * The deprecated `forceRefresh` option is accepted and discarded, not forwarded.\n */\n async getAISummary(ticker: string, options?: GetAISummaryOptions): Promise<AISummary> {\n const { forceRefresh: _forceRefresh, ...params } = options ?? {};\n return this.client.get(`/api/v1/stocks/${encodeURIComponent(ticker)}/ai-summary`, params);\n }\n\n /** Get sentiment/mention metrics breakdown by entity. */\n async getMetricsBreakdown(\n ticker: string,\n metricType: string,\n options?: GetMetricsBreakdownOptions,\n ): Promise<MetricsBreakdown> {\n return this.client.get(\n `/api/v1/stocks/${encodeURIComponent(ticker)}/metrics/${encodeURIComponent(metricType)}/breakdown`,\n options,\n );\n }\n\n /**\n * Get historical OHLCV chart data.\n *\n * The API returns a bare array of points; this normalizes it to\n * `{ ticker, timeframe, data }`. `timeframe` echoes the requested value\n * (defaulting to \"1M\", matching the server default when omitted).\n */\n async getChart(ticker: string, options?: GetChartOptions): Promise<ChartData> {\n const data = await this.client.get<ChartDataPoint[]>(\"/api/v1/stocks/chart\", {\n ticker,\n ...options,\n });\n return { ticker, timeframe: options?.timeframe ?? \"1M\", data };\n }\n\n /** Get current market open/closed/pre-market/after-hours status. */\n async getMarketStatus(): Promise<MarketStatus> {\n return this.client.get(\"/api/v1/stocks/market-status\");\n }\n\n /**\n * Get financial statement data for one reporting period: income statement, balance sheet,\n * and cash flow, including `capitalExpenditure` and `freeCashFlow`.\n *\n * Capital expenditure is signed as filed, so normally negative. See {@link Fundamentals}\n * for the free-cash-flow relationship and when it is `null`.\n */\n async getFundamentals(ticker: string, options?: GetFundamentalsOptions): Promise<Fundamentals> {\n return this.client.get(\"/api/v1/stocks/fundamentals\", { ticker, ...options });\n }\n\n /** Get available fiscal periods. The periods are in `periods`. */\n async getFundamentalsPeriods(ticker: string): Promise<FundamentalsPeriodsResponse> {\n return this.client.get(\"/api/v1/stocks/fundamentals/periods\", { ticker });\n }\n\n /**\n * Get the trailing-twelve-month fundamentals snapshot: TTM ratios, a different\n * shape from the per-period statement data `getFundamentals()` returns.\n */\n async getCurrentFundamentals(ticker: string): Promise<TtmFundamentals> {\n return this.client.get(\"/api/v1/stocks/fundamentals/current\", { ticker });\n }\n\n /** Get historical revenue data. */\n async getHistoricalRevenue(ticker: string): Promise<unknown> {\n return this.client.get(\"/api/v1/stocks/fundamentals/historical/revenue\", { ticker });\n }\n\n /** Get short interest metrics (FINRA). */\n async getShortInterest(ticker: string): Promise<ShortInterest> {\n return this.client.get(\"/api/v1/stocks/short-interest\", { ticker });\n }\n\n /** Get float information. */\n async getFloat(ticker: string): Promise<FloatInfo> {\n return this.client.get(\"/api/v1/stocks/float\", { ticker });\n }\n\n /** Get short volume trading data. */\n async getShortVolume(ticker: string): Promise<ShortVolume> {\n return this.client.get(\"/api/v1/stocks/short-volume\", { ticker });\n }\n\n /**\n * Get company-specific KPI time-series for a ticker. Returns curated GAAP and\n * non-GAAP metrics from earnings filings (e.g. iPhone unit sales, Tesla deliveries,\n * AWS revenue).\n *\n * Free users receive metadata only with an empty `kpis` list; PRO users receive\n * the full series. Returns 404 for tickers that do not yet have curated coverage.\n *\n * Coverage today: near-complete for the S&P 500 plus extended universe\n * (~500 tickers). Use `listKpiCoverage()` to enumerate.\n */\n async getKpis(ticker: string): Promise<PreviewResponse<CompanyKpisData>> {\n return this.client.get(\n `/api/v1/stocks/${encodeURIComponent(ticker.toUpperCase())}/kpis`,\n );\n }\n\n /**\n * List every ticker with curated KPI coverage. Returns `{count, tickers: [...]}`\n * with lightweight metadata (ticker, companyName, lastUpdated, kpiCount).\n * Sorted alphabetically by ticker.\n *\n * Auth: API key required, but the call does NOT consume your monthly quota\n * (rate-limit-per-minute still applies).\n */\n async listKpiCoverage(): Promise<KpiCoverageResponse> {\n return this.client.get(\"/api/v1/stocks/with-kpis\");\n }\n\n /**\n * List the KPI metadata tuples available for a ticker (`id, name, category,\n * chartType`) without paying the cost of the full series payload. Mirrors\n * the `/api/v1/insights/stock/{ticker}/types` precedent.\n *\n * Auth: API key required, no quota cost. 404 if the ticker has no curated KPIs.\n */\n async getKpiTypes(ticker: string): Promise<KpiTypeEntry[]> {\n return this.client.get(\n `/api/v1/stocks/${encodeURIComponent(ticker.toUpperCase())}/kpis/types`,\n );\n }\n\n /**\n * Get the end-of-day options dossier for one stock or ETF: the session's aggregate, its\n * percentile context, the open-interest wall structure with max pain, and the contracts\n * whose volume ran far ahead of their open interest.\n *\n * End of day, not live. `asOf` is the prior trading session and the data refreshes the\n * following morning, so this is positioning, not a quote feed.\n *\n * **`data` is `null` for a ticker outside the covered universe**, which is the most\n * actively optioned US names plus the tracked ETFs, and for a covered ticker with no\n * snapshot yet. An unknown symbol behaves the same way rather than answering 404, so treat\n * a null as \"no coverage\", never as an error. A covered ticker still building its baseline\n * returns its raw readings with the percentiles omitted.\n *\n * Percentiles compare a ticker to its own trailing history, never to another ticker, so an\n * ETF's readings are not comparable with a single stock's.\n *\n * Tiering: a PRO key always receives the full dossier. A FREE key receives it for the first\n * ten calls each calendar month and a headline-only preview after that, with `isPreview`\n * true; calls that return a null `data` never spend that allowance.\n */\n async getOptionsSummary(ticker: string): Promise<PreviewResponse<OptionsSummary | null>> {\n return this.client.get(\n `/api/v1/stocks/${encodeURIComponent(ticker.toUpperCase())}/options/summary`,\n );\n }\n}\n","import type { APIClient } from \"../client.js\";\nimport type {\n IndexConstituent,\n IndexHistoryPoint,\n IndexHistoryResponse,\n IndexListing,\n IndexListResponse,\n IndexSnapshot,\n} from \"../types.js\";\n\n/**\n * Indexes: composite scalars tracked over time, each blending its own inputs\n * into one number on a stated scale. Every index answers on the same envelope,\n * so you write one renderer and get every current and future SentiSense index.\n *\n * Two archetypes share that envelope. A **basket** index weight-averages\n * tracked entities and fills `constituents` / `basketSize` / `coverage` /\n * `totalMentions`; a **composite** index is built from signals instead and\n * returns `null` for all four by construction. See {@link IndexSnapshot}.\n *\n * @see IndexSnapshot\n */\nexport class Indexes {\n constructor(private client: APIClient) {}\n\n /**\n * List every index the platform publishes: id, display name, one-line\n * description, the scale it lives on, its access tier, and where its richest\n * view lives.\n *\n * Iterate this rather than hardcoding ids. Every `indexId` it advertises\n * resolves on {@link get} and {@link history}.\n */\n async list(): Promise<IndexListResponse> {\n return this.client.get(\"/api/v1/indexes\");\n }\n\n /**\n * Latest reading for one index.\n *\n * Check `constituents` for `null` before iterating: it is `null` on a\n * composite index like `market-mood`, which has no constituents by\n * construction. For Market Mood this is the narrowed view; the phase band,\n * weekly change, per-signal breakdown and per-sector map live on\n * `client.marketMood.get()`, and both report the same headline number.\n *\n * @param indexId slug from {@link list}, e.g. `\"fed-sentiment\"`.\n */\n async get(indexId: string): Promise<IndexSnapshot> {\n return this.client.get(`/api/v1/indexes/${indexId}`);\n }\n\n /**\n * Historical scalar series for one index, for charting.\n *\n * Thin or low-coverage buckets are withheld, so the series can be shorter\n * than `days` and can contain gaps. Plot against each point's `date`.\n *\n * @param indexId slug from {@link list}.\n * @param days days of history to return. Defaults to the API's own 180.\n */\n async history(indexId: string, days?: number): Promise<IndexHistoryResponse> {\n return this.client.get(\n `/api/v1/indexes/${indexId}/history`,\n days === undefined ? undefined : { days },\n );\n }\n}\n\n// Re-export for convenience so callers can `import type { IndexListing }`\n// from the resource module instead of `../types`.\nexport type {\n IndexConstituent,\n IndexHistoryPoint,\n IndexHistoryResponse,\n IndexListing,\n IndexListResponse,\n IndexSnapshot,\n};\n","import type { APIClient } from \"../client.js\";\nimport type {\n TrackerListing,\n TrackerListResponse,\n TrackerSnapshot,\n TrackerSnapshotResponse,\n} from \"../types.js\";\n\n/**\n * Trackers: observational data products published as a standardized\n * `TrackerSnapshot` envelope. Every tracker (institution rankings,\n * hedge-fund reported returns, social trackers, surveillance dashboards)\n * returns the same shape, so consumers write one renderer per `viewType` and\n * get every current and future SentiSense tracker for free.\n *\n * @see TrackerSnapshot\n */\nexport class Trackers {\n constructor(private client: APIClient) {}\n\n /**\n * List every publicly-visible tracker: id, display name, category,\n * one-line description, and the methodology anchor to link out to.\n */\n async list(): Promise<TrackerListResponse> {\n return this.client.get(\"/api/v1/trackers\");\n }\n\n /**\n * Standardized snapshot envelope for one tracker.\n *\n * Returns the envelope as-is: `{ isPreview, previewReason, totalCount?, data }`.\n * When `data.viewType === \"table\"` the rows live at `data.rows[]`; when\n * `\"choropleth\"` they live at `data.geo[]`; etc. Dispatch on `viewType`\n * in your renderer.\n *\n * @param trackerId slug from {@link list}, e.g. `\"institution-concentration\"`.\n * @param params provider-specific query params (e.g. `{ scope: \"us\" }` for\n * geographically-scoped trackers like hantavirus). Unknown keys are ignored.\n */\n async get(\n trackerId: string,\n params?: Record<string, string | number | boolean>,\n ): Promise<TrackerSnapshotResponse> {\n return this.client.get(`/api/v1/trackers/${trackerId}`, params);\n }\n}\n\n// Re-export for convenience so callers can `import type { TrackerListing }`\n// from the resource module instead of `../types`.\nexport type {\n TrackerListing,\n TrackerListResponse,\n TrackerSnapshot,\n TrackerSnapshotResponse,\n};\n","export const VERSION = \"0.43.0\";\n","import {\n APIError,\n AuthenticationError,\n DeepHistoryUnavailableError,\n NotFoundError,\n RateLimitError,\n SentiSenseError,\n} from \"./errors.js\";\nimport { Analyst } from \"./resources/analyst.js\";\nimport { Calendar } from \"./resources/calendar.js\";\nimport { Documents } from \"./resources/documents.js\";\nimport { Earnings } from \"./resources/earnings.js\";\nimport { EntityMetrics } from \"./resources/entityMetrics.js\";\nimport { Etfs } from \"./resources/etfs.js\";\nimport { Insider } from \"./resources/insider.js\";\nimport { Politicians } from \"./resources/politicians.js\";\nimport { Insights } from \"./resources/insights.js\";\nimport { Institutional } from \"./resources/institutional.js\";\nimport { KB } from \"./resources/kb.js\";\nimport { MarketMoodResource } from \"./resources/marketMood.js\";\nimport { MarketSummaryResource } from \"./resources/marketSummary.js\";\nimport { Screener } from \"./resources/screener.js\";\nimport { Stocks } from \"./resources/stocks.js\";\nimport { Indexes } from \"./resources/indexes.js\";\nimport { Trackers } from \"./resources/trackers.js\";\nimport type { SentiSenseOptions } from \"./types.js\";\nimport { VERSION } from \"./version.js\";\n\nconst DEFAULT_BASE_URL = \"https://app.sentisense.ai\";\nconst DEFAULT_TIMEOUT = 30_000;\nconst DEFAULT_MAX_RETRIES = 3;\nconst BASE_DELAY_MS = 1_000;\nconst MAX_DELAY_MS = 60_000;\n// Used when a 202 arrives without a usable Retry-After header.\nconst DEEP_HISTORY_FALLBACK_WAIT_S = 3;\n\n// Upper bounds on any server-supplied Retry-After. Rate limiting gets the longer ceiling\n// because a genuine limit window is legitimately minutes, while a deep-history warm-up is\n// seconds. Without a ceiling an oversized header value strands the caller indefinitely.\nconst MAX_DEEP_HISTORY_WAIT_S = 30;\nconst MAX_RATE_LIMIT_WAIT_S = 120;\nconst RATE_LIMIT_FALLBACK_WAIT_S = 60;\n\n/**\n * A `Retry-After` header as a usable number of seconds, clamped to `[0.5, maxWaitS]`, or\n * `undefined` when there is no usable value.\n *\n * `Retry-After` is vendor-controlled and may legally carry an HTTP-date rather than a\n * number of seconds, in which case parsing yields `NaN`. Left unguarded that produced a\n * `NaN` delay which compared false against every threshold and retried instantly in a busy\n * loop, and a `NaN` on the error object that silently broke a caller's own backoff.\n * Anything that is not a finite number is treated as absent.\n */\nfunction clampRetryAfter(\n raw: string | null,\n maxWaitS: number,\n): number | undefined {\n if (!raw) return undefined;\n const parsed = Number(raw);\n if (!Number.isFinite(parsed)) return undefined;\n return Math.min(Math.max(0.5, parsed), maxWaitS);\n}\n\n/** Same clamp, resolved to `defaultS` when the header gives us nothing to go on. */\nfunction retryAfterSeconds(\n raw: string | null,\n defaultS: number,\n maxWaitS: number,\n): number {\n return clampRetryAfter(raw, maxWaitS) ?? defaultS;\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/** @internal HTTP interface exposed to resource classes. */\nexport interface APIClient {\n get<T = unknown>(path: string, params?: object): Promise<T>;\n post<T = unknown>(path: string, body: unknown): Promise<T>;\n}\n\nexport class SentiSense implements APIClient {\n private baseUrl: string;\n private apiKey: string | undefined;\n private timeout: number;\n private maxRetries: number;\n private userAgent: string;\n\n readonly stocks: Stocks;\n readonly documents: Documents;\n readonly etfs: Etfs;\n readonly institutional: Institutional;\n readonly insider: Insider;\n readonly politicians: Politicians;\n readonly insights: Insights;\n readonly analyst: Analyst;\n readonly entityMetrics: EntityMetrics;\n readonly marketMood: MarketMoodResource;\n readonly marketSummary: MarketSummaryResource;\n readonly kb: KB;\n readonly indexes: Indexes;\n readonly trackers: Trackers;\n readonly calendar: Calendar;\n readonly earnings: Earnings;\n readonly screener: Screener;\n\n constructor(options: SentiSenseOptions = {}) {\n this.apiKey = options.apiKey;\n this.baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\\/+$/, \"\");\n this.timeout = options.timeout ?? DEFAULT_TIMEOUT;\n this.maxRetries = options.maxRetries ?? DEFAULT_MAX_RETRIES;\n // A header value cannot carry CR/LF, so collapse them rather than letting a caller's\n // string decide where the header block ends.\n const suffix = options.userAgentSuffix?.replace(/[\\r\\n]+/g, \" \").trim();\n this.userAgent = suffix\n ? `sentisense-node/${VERSION} ${suffix}`\n : `sentisense-node/${VERSION}`;\n\n this.stocks = new Stocks(this);\n this.documents = new Documents(this);\n this.etfs = new Etfs(this);\n this.institutional = new Institutional(this);\n this.insider = new Insider(this);\n this.politicians = new Politicians(this);\n this.insights = new Insights(this);\n this.analyst = new Analyst(this);\n this.entityMetrics = new EntityMetrics(this);\n this.marketMood = new MarketMoodResource(this);\n this.marketSummary = new MarketSummaryResource(this);\n this.kb = new KB(this);\n this.indexes = new Indexes(this);\n this.trackers = new Trackers(this);\n this.calendar = new Calendar(this);\n this.earnings = new Earnings(this);\n this.screener = new Screener(this);\n }\n\n /** @internal */\n async get<T = unknown>(path: string, params?: object): Promise<T> {\n const url = this.buildUrl(path, params);\n const headers: Record<string, string> = {\n \"Accept\": \"application/json\",\n };\n\n if (this.apiKey) {\n headers[\"X-SentiSense-API-Key\"] = this.apiKey;\n }\n\n // User-Agent is only set in Node.js (browsers disallow it)\n if (typeof process !== \"undefined\" && process.versions?.node) {\n headers[\"User-Agent\"] = this.userAgent;\n }\n\n let delayMs = 0;\n\n for (let attempt = 0; attempt <= this.maxRetries; attempt++) {\n if (delayMs > 0) {\n await sleep(delayMs);\n delayMs = 0;\n }\n\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await fetch(url, {\n method: \"GET\",\n headers,\n signal: controller.signal,\n });\n\n // 202 means a deep chart range is still being built server-side. It is a 2xx, so\n // without this it would fall through and return an empty array: the caller would\n // see \"no data\" rather than \"not ready yet\", which is the exact confusion the\n // status code exists to prevent. Retry honouring Retry-After, then surface it.\n if (response.status === 202) {\n const waitSeconds = retryAfterSeconds(\n response.headers.get(\"Retry-After\"),\n DEEP_HISTORY_FALLBACK_WAIT_S,\n MAX_DEEP_HISTORY_WAIT_S,\n );\n try { await response.body?.cancel(); } catch { /* ignore */ }\n if (attempt < this.maxRetries) {\n delayMs = waitSeconds * 1000;\n continue;\n }\n throw new DeepHistoryUnavailableError(\n \"Deep history is still being assembled. Retry in a few seconds.\",\n waitSeconds,\n );\n }\n\n if (!response.ok) {\n const isRetryable = response.status === 429 || response.status >= 500;\n if (isRetryable && attempt < this.maxRetries) {\n if (response.status === 429) {\n delayMs = retryAfterSeconds(\n response.headers.get(\"Retry-After\"),\n RATE_LIMIT_FALLBACK_WAIT_S,\n MAX_RATE_LIMIT_WAIT_S,\n ) * 1000;\n } else {\n delayMs = Math.min(BASE_DELAY_MS * Math.pow(2, attempt), MAX_DELAY_MS) + Math.random() * 1000;\n }\n try { await response.body?.cancel(); } catch { /* ignore */ }\n continue;\n }\n await this.handleErrorResponse(response);\n }\n\n return (await response.json()) as T;\n } catch (error) {\n if (error instanceof SentiSenseError) throw error;\n if (error instanceof Error && error.name === \"AbortError\") {\n throw new SentiSenseError(`Request timed out after ${this.timeout}ms`);\n }\n throw new SentiSenseError(\n error instanceof Error ? error.message : \"Unknown error\",\n );\n } finally {\n clearTimeout(timer);\n }\n }\n\n throw new SentiSenseError(\"All retries exhausted\");\n }\n\n /** @internal */\n async post<T = unknown>(path: string, body: unknown): Promise<T> {\n const url = this.buildUrl(path);\n const headers: Record<string, string> = {\n \"Accept\": \"application/json\",\n \"Content-Type\": \"application/json\",\n };\n\n if (this.apiKey) {\n headers[\"X-SentiSense-API-Key\"] = this.apiKey;\n }\n\n if (typeof process !== \"undefined\" && process.versions?.node) {\n headers[\"User-Agent\"] = this.userAgent;\n }\n\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await fetch(url, {\n method: \"POST\",\n headers,\n body: JSON.stringify(body),\n signal: controller.signal,\n });\n\n if (!response.ok) {\n await this.handleErrorResponse(response);\n }\n\n return (await response.json()) as T;\n } catch (error) {\n if (error instanceof SentiSenseError) throw error;\n if (error instanceof Error && error.name === \"AbortError\") {\n throw new SentiSenseError(`Request timed out after ${this.timeout}ms`);\n }\n throw new SentiSenseError(\n error instanceof Error ? error.message : \"Unknown error\",\n );\n } finally {\n clearTimeout(timer);\n }\n }\n\n private buildUrl(path: string, params?: object): string {\n const url = new URL(path, this.baseUrl);\n if (params) {\n for (const [key, value] of Object.entries(params as Record<string, unknown>)) {\n if (value !== undefined && value !== null) {\n url.searchParams.set(key, String(value));\n }\n }\n }\n return url.toString();\n }\n\n private async handleErrorResponse(response: Response): Promise<never> {\n let body: { error?: string; message?: string } = {};\n try {\n body = await response.json();\n } catch {\n // Response may not be JSON\n }\n\n const message = body.message ?? response.statusText ?? \"API request failed\";\n const code = body.error;\n\n switch (response.status) {\n case 401:\n case 403:\n throw new AuthenticationError(message, response.status, code);\n case 404:\n throw new NotFoundError(message, code);\n case 429: {\n // Same clamp the retry loop uses, so a caller running its own backoff off\n // `error.retryAfter` gets a number it can pass to setTimeout, or nothing at all.\n const retryAfter = clampRetryAfter(\n response.headers.get(\"Retry-After\"),\n MAX_RATE_LIMIT_WAIT_S,\n );\n throw new RateLimitError(message, code, retryAfter);\n }\n default:\n throw new APIError(message, response.status, code);\n }\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/index.ts","../src/errors.ts","../src/resources/analyst.ts","../src/resources/calendar.ts","../src/resources/documents.ts","../src/resources/earnings.ts","../src/resources/entityMetrics.ts","../src/resources/etfs.ts","../src/resources/insider.ts","../src/resources/politicians.ts","../src/resources/insights.ts","../src/resources/institutional.ts","../src/resources/kb.ts","../src/resources/marketMood.ts","../src/resources/marketSummary.ts","../src/resources/screener.ts","../src/resources/stocks.ts","../src/resources/indexes.ts","../src/resources/trackers.ts","../src/version.ts","../src/client.ts"],"sourcesContent":["export { SentiSense } from \"./client.js\";\nexport { SentiSense as default } from \"./client.js\";\n\nexport type {\n AnalystConsensus,\n AnalystAction,\n AnalystEstimate,\n AnalystEarningsSurprise,\n AnalystEstimatesResponse,\n GetAnalystActionsOptions,\n GetAnalystMarketActivityOptions,\n} from \"./resources/analyst.js\";\n\n// Screener types\nexport type {\n EtfScreenerExecuteResponse,\n EtfScreenerRow,\n FeaturedScreen,\n ScreenerExecuteOptions,\n ScreenerExecuteResponse,\n ScreenerFieldCatalog,\n ScreenerFieldDescriptor,\n ScreenerFieldOption,\n ScreenerFilter,\n ScreenerPlan,\n ScreenerRow,\n ScreenerScreensResponse,\n ScreenerSort,\n} from \"./resources/screener.js\";\n\nexport type {\n GetStockInsightsRangeOptions,\n GetLatestInsightsOptions,\n GetUserInsightsOptions,\n} from \"./resources/insights.js\";\n\n// ETF aggregate types\nexport type {\n EtfInfo,\n EtfHolding,\n EtfHoldings,\n EtfAggregateCoverage,\n WeightedConsensus,\n EtfAnalystContributor,\n EtfAnalystAggregate,\n WeightedNetFlow,\n EtfInsiderContributor,\n EtfInsiderAggregate,\n EtfSentimentReading,\n EtfSentimentAggregate,\n GetEtfInsiderAggregateOptions,\n} from \"./resources/etfs.js\";\n\n// KPI types\nexport type {\n KpiDataPoint,\n KpiSeries,\n CompanyKpisData,\n KpiCoverageEntry,\n KpiCoverageResponse,\n KpiTypeEntry,\n} from \"./types.js\";\n\nexport {\n SentiSenseError,\n AuthenticationError,\n NotFoundError,\n DeepHistoryUnavailableError,\n RateLimitError,\n APIError,\n} from \"./errors.js\";\n\nexport type {\n SentiSenseOptions,\n Insight,\n InsightPreviewResponse,\n LockedInsight,\n GetInsightsOptions,\n InsiderActivitySummary,\n InsiderActivityResponse,\n InsiderTrade,\n ClusterBuy,\n GetInsiderOptions,\n AssetMetadata,\n CongressTrade,\n PoliticianSummary,\n PoliticianDetail,\n PoliticianDirectoryEntry,\n PoliticianDirectory,\n PoliticianDirectoryResponse,\n GetPoliticianActivityOptions,\n GetPoliticianMemberOptions,\n GetPoliticiansOptions,\n GetPoliticianDirectoryOptions,\n EarningsEvent,\n CalendarMeta,\n EarningsCalendarResponse,\n GetEarningsCalendarOptions,\n EarningsKpiHighlight,\n EarningsSource,\n EarningsQuarter,\n RecentEarningsEntry,\n GetEarningsSummariesOptions,\n GetRecentEarningsOptions,\n PreviewResponse,\n StockPrice,\n StockQuote,\n StockDetail,\n SimilarStock,\n StockImage,\n StockProfile,\n StockEntity,\n ChartData,\n ChartDataPoint,\n MarketStatus,\n OptionsSummary,\n OptionsAggregate,\n OptionsContext,\n OptionsOiWalls,\n OptionsWall,\n OptionsUnusualContract,\n Fundamentals,\n TtmFundamentals,\n FundamentalsPeriod,\n FundamentalsPeriodsResponse,\n ShortInterest,\n FloatInfo,\n ShortVolume,\n AISummary,\n MetricsBreakdown,\n Document,\n DocumentSearchResponse,\n DocumentSource,\n SentimentEntry,\n Story,\n StoryCluster,\n Quarter,\n InstitutionalFlow,\n InstitutionalFlows,\n InstitutionalFlowsResponse,\n Holder,\n HolderNotableChanges,\n TickerHolders,\n GetHoldersOptions,\n InstitutionSummary,\n InstitutionList,\n InstitutionListResponse,\n ListInstitutionsOptions,\n MetricType,\n MetricsOptions,\n MetricDistributionOptions,\n ServingMetric,\n MetricDistribution,\n MarketMood,\n MarketSummary,\n KBEntity,\n IndexListing,\n IndexListResponse,\n IndexConstituent,\n IndexSnapshot,\n IndexHistoryPoint,\n IndexHistoryResponse,\n TrackerListing,\n TrackerListResponse,\n TrackerSnapshot,\n TrackerSnapshotResponse,\n TrackerTableRow,\n TrackerMetricValue,\n TrackerHeadlineMetric,\n TrackerGeoEntry,\n TrackerTimeSeriesPoint,\n TrackerEvent,\n TrackerSignal,\n TrackerSourceRef,\n} from \"./types.js\";\n\nexport { VERSION } from \"./version.js\";\n","export class SentiSenseError extends Error {\n status?: number;\n code?: string;\n\n constructor(message: string, status?: number, code?: string) {\n super(message);\n this.name = \"SentiSenseError\";\n this.status = status;\n this.code = code;\n }\n}\n\nexport class AuthenticationError extends SentiSenseError {\n constructor(message: string, status: number, code?: string) {\n super(message, status, code);\n this.name = \"AuthenticationError\";\n }\n}\n\nexport class NotFoundError extends SentiSenseError {\n constructor(message: string, code?: string) {\n super(message, 404, code);\n this.name = \"NotFoundError\";\n }\n}\n\n/**\n * Thrown when a deep chart range is still being assembled.\n *\n * The API answers 202 for \"10Y\" and \"MAX\" the first time a rarely-requested stock is asked\n * for. It deliberately does not substitute a shorter range, so a successful response always\n * carries the timeframe you asked for. Retry after a few seconds.\n */\nexport class DeepHistoryUnavailableError extends SentiSenseError {\n retryAfter?: number;\n\n constructor(message: string, retryAfter?: number) {\n super(message, 202);\n this.name = \"DeepHistoryUnavailableError\";\n this.retryAfter = retryAfter;\n }\n}\n\nexport class RateLimitError extends SentiSenseError {\n /**\n * Seconds to wait before retrying, from the server's `Retry-After` header, clamped to\n * `[0.5, 120]`. Always either a finite number or `undefined`: an absent header, or one\n * carrying an HTTP-date instead of a number of seconds, leaves it undefined rather than\n * `NaN`, so `setTimeout(fn, err.retryAfter * 1000)` can never fire immediately.\n */\n retryAfter?: number;\n\n constructor(message: string, code?: string, retryAfter?: number) {\n super(message, 429, code);\n this.name = \"RateLimitError\";\n this.retryAfter = retryAfter;\n }\n}\n\nexport class APIError extends SentiSenseError {\n constructor(message: string, status: number, code?: string) {\n super(message, status, code);\n this.name = \"APIError\";\n }\n}\n","import type { APIClient } from \"../client.js\";\nimport type { PreviewResponse } from \"../types.js\";\n\nexport interface AnalystConsensus {\n ticker: string;\n currentPrice: number | null;\n targetLow: number | null;\n targetMean: number | null;\n targetHigh: number | null;\n targetMedian: number | null;\n numberOfAnalysts: number;\n upsidePercent: number | null;\n consensusLabel: string | null;\n recommendationMean: number | null;\n /** PRO-only; zero in the free preview. */\n strongBuy: number;\n /** PRO-only; zero in the free preview. */\n buy: number;\n /** PRO-only; zero in the free preview. */\n hold: number;\n /** PRO-only; zero in the free preview. */\n sell: number;\n /** PRO-only; zero in the free preview. */\n strongSell: number;\n updatedAt: string | null;\n}\n\nexport interface AnalystAction {\n ticker: string;\n actionDate: string;\n firm: string;\n /** UPGRADE, DOWNGRADE, INITIATE, REITERATE, OTHER */\n actionType: string;\n fromGrade: string | null;\n toGrade: string | null;\n}\n\nexport interface AnalystEstimate {\n /** Fiscal period descriptor (provider-specific shape). */\n [key: string]: unknown;\n}\n\nexport interface AnalystEarningsSurprise {\n /** Past report descriptor (provider-specific shape). */\n [key: string]: unknown;\n}\n\nexport interface AnalystEstimatesResponse {\n estimates: AnalystEstimate[];\n surprises: AnalystEarningsSurprise[];\n}\n\nexport interface GetAnalystActionsOptions {\n /** Days of history to return. Default 90. */\n lookbackDays?: number;\n}\n\nexport interface GetAnalystMarketActivityOptions {\n /** Days of history to return. Default 30. */\n lookbackDays?: number;\n}\n\n/**\n * Wall Street analyst coverage: aggregate price targets, recommendation distribution,\n * recent upgrade/downgrade actions, and forward EPS estimates with earnings surprise history.\n *\n * Free users receive the price target band (low/mean/high + analyst count + consensus label)\n * in full -- it powers the public projection cone. The buy/hold/sell distribution counts\n * and full action/estimate history are PRO-only.\n */\nexport class Analyst {\n constructor(private client: APIClient) {}\n\n /**\n * Get the aggregate Wall Street consensus for a ticker. Returns 404 if no\n * coverage exists.\n */\n async consensus(\n ticker: string,\n ): Promise<PreviewResponse<AnalystConsensus>> {\n return this.client.get(\n `/api/v1/analyst/${encodeURIComponent(ticker.toUpperCase())}/consensus`,\n );\n }\n\n /**\n * Get recent analyst upgrade/downgrade actions for a ticker, newest first.\n * Free users receive the 3 most recent.\n */\n async actions(\n ticker: string,\n options?: GetAnalystActionsOptions,\n ): Promise<PreviewResponse<AnalystAction[]>> {\n return this.client.get(\n `/api/v1/analyst/${encodeURIComponent(ticker.toUpperCase())}/actions`,\n options,\n );\n }\n\n /**\n * Get forward EPS estimates and earnings surprise history for a ticker.\n * Free users receive 1 estimate (current quarter) plus the 2 most recent surprises.\n */\n async estimates(\n ticker: string,\n ): Promise<PreviewResponse<AnalystEstimatesResponse>> {\n return this.client.get(\n `/api/v1/analyst/${encodeURIComponent(ticker.toUpperCase())}/estimates`,\n );\n }\n\n /**\n * Get market-wide recent analyst actions across all covered tickers, newest first.\n * Free users receive the 5 most recent.\n */\n async marketActivity(\n options?: GetAnalystMarketActivityOptions,\n ): Promise<PreviewResponse<AnalystAction[]>> {\n return this.client.get(\"/api/v1/analyst/activity\", options);\n }\n}\n","import type { APIClient } from \"../client.js\";\nimport type {\n EarningsCalendarResponse,\n GetEarningsCalendarOptions,\n PreviewResponse,\n} from \"../types.js\";\n\nexport class Calendar {\n constructor(private client: APIClient) {}\n\n /**\n * Upcoming company earnings, sorted by date.\n *\n * Key-required. A FREE key returns the current week (`isPreview: true`); a PRO\n * key returns the full forward window (about 30 days). Field richness is\n * identical across tiers: the gate is how far ahead you can see, not which\n * columns you get. On a preview, `totalCount` is the full-window event count.\n */\n async getEarnings(\n options?: GetEarningsCalendarOptions,\n ): Promise<PreviewResponse<EarningsCalendarResponse>> {\n return this.client.get(\"/api/v1/calendar/earnings\", options);\n }\n}\n","import type { APIClient } from \"../client.js\";\nimport type {\n DocumentSearchResponse,\n DocumentSource,\n GetByEntityOptions,\n GetBySourceOptions,\n GetByTickerOptions,\n GetByTickerRangeOptions,\n GetStoriesByTickerOptions,\n GetStoriesOptions,\n SearchDocumentsOptions,\n Story,\n} from \"../types.js\";\n\nexport class Documents {\n constructor(private client: APIClient) {}\n\n /** Get document metrics for a stock. The rows are in `documents`. */\n async getByTicker(ticker: string, options?: GetByTickerOptions): Promise<DocumentSearchResponse> {\n return this.client.get(`/api/v1/documents/ticker/${encodeURIComponent(ticker)}`, options);\n }\n\n /** Get document metrics for a stock within a date range. The rows are in `documents`. */\n async getByTickerRange(ticker: string, options: GetByTickerRangeOptions): Promise<DocumentSearchResponse> {\n return this.client.get(\n `/api/v1/documents/ticker/${encodeURIComponent(ticker)}/range`,\n options,\n );\n }\n\n /** Get document metrics for a KB entity. The rows are in `documents`. */\n async getByEntity(entityId: string, options?: GetByEntityOptions): Promise<DocumentSearchResponse> {\n return this.client.get(\n `/api/v1/documents/entity/${encodeURIComponent(entityId)}`,\n options,\n );\n }\n\n /** Smart search with natural language query parsing. The rows are in `documents`. */\n async search(query: string, options?: SearchDocumentsOptions): Promise<DocumentSearchResponse> {\n return this.client.get(\"/api/v1/documents/search\", { query, ...options });\n }\n\n /** Get latest document metrics from a source type. The rows are in `documents`. */\n async getBySource(source: DocumentSource, options?: GetBySourceOptions): Promise<DocumentSearchResponse> {\n return this.client.get(\n `/api/v1/documents/source/${encodeURIComponent(source)}`,\n options,\n );\n }\n\n /** Get AI-curated news story clusters. */\n async getStories(options?: GetStoriesOptions): Promise<Story[]> {\n return this.client.get(\"/api/v1/documents/stories\", options);\n }\n\n /** Get full story detail by cluster ID. */\n async getStoryDetail(clusterId: string): Promise<unknown> {\n return this.client.get(`/api/v1/documents/stories/${encodeURIComponent(clusterId)}`);\n }\n\n /** Get stories for a specific stock. */\n async getStoriesByTicker(\n ticker: string,\n options?: GetStoriesByTickerOptions,\n ): Promise<Story[]> {\n return this.client.get(\n `/api/v1/documents/stories/ticker/${encodeURIComponent(ticker)}`,\n options,\n );\n }\n\n}\n","import type { APIClient } from \"../client.js\";\nimport type {\n EarningsQuarter,\n GetEarningsSummariesOptions,\n GetRecentEarningsOptions,\n PreviewResponse,\n RecentEarningsEntry,\n} from \"../types.js\";\n\n/**\n * Earnings: what a company actually reported, after the fact.\n *\n * A quarter's results arrive as a press release, a filing, and a call, none of\n * which is a data structure. {@link getSummaries} is the assembled version, one\n * object per fiscal quarter, and {@link getRecent} is the cross-ticker view of\n * who reported lately. Pair them to drive a post-earnings sweep: list the\n * window, then pull each ticker's analysis report.\n *\n * The forward-looking half of the family lives on `client.calendar.getEarnings()`,\n * which covers scheduled dates and consensus EPS rather than results.\n *\n * @see EarningsQuarter\n */\nexport class Earnings {\n constructor(private client: APIClient) {}\n\n /**\n * Per-quarter earnings analysis report for one ticker, newest first.\n *\n * Each quarter carries the editorial headline, the KPI cards that matter for\n * that company with year-over-year deltas, the guidance language as\n * management phrased it, and a summary of the earnings call.\n *\n * Branch on `isPreview`: a PRO key receives every hydrated quarter in full, a\n * FREE key receives the latest quarter shaped rather than truncated, plus\n * `totalCount`. {@link EarningsQuarter} documents which fields each tier\n * carries.\n *\n * A quarter typically appears within 48 hours of the company reporting, and\n * the call summary can arrive after the press-release content for the same\n * quarter, so read `generatedAt` and `transcriptGeneratedAt` rather than\n * assuming a fixed lag. A ticker with no stored quarter answers with an empty\n * `data` array, not a 404.\n *\n * Use canonical ticker symbols: `GOOGL` (not `GOOG`), `BRK.B` (not `BRK-B`).\n */\n async getSummaries(\n ticker: string,\n options?: GetEarningsSummariesOptions,\n ): Promise<PreviewResponse<EarningsQuarter[]>> {\n return this.client.get(\n `/api/v1/stocks/${encodeURIComponent(ticker.toUpperCase())}/earnings-summaries`,\n options,\n );\n }\n\n /**\n * Which covered companies reported on or after `today - days`, newest first.\n *\n * Every API key receives the full window it asks for, so `isPreview` is\n * always `false` here. The window is bounded by `reportDate`, so a quarter\n * reported inside it appears even when its call summary lands later, and an\n * empty `data` array means nobody in the covered set reported in that window.\n *\n * This is the backward-looking feed; `client.calendar.getEarnings()` is the\n * forward-looking one.\n */\n async getRecent(\n options?: GetRecentEarningsOptions,\n ): Promise<PreviewResponse<RecentEarningsEntry[]>> {\n return this.client.get(\"/api/v1/earnings/recent\", options);\n }\n}\n","import type { APIClient } from \"../client.js\";\nimport type {\n MetricType,\n MetricsOptions,\n MetricDistributionOptions,\n ServingMetric,\n MetricDistribution,\n} from \"../types.js\";\n\nexport class EntityMetrics {\n constructor(private client: APIClient) {}\n\n /**\n * Get time-series metric data for an entity using the v2 Serving Metrics API.\n *\n * @param symbol Ticker symbol (e.g. \"AAPL\") or entity urlSlug (e.g. \"Nancy-Pelosi\",\n * case-insensitive; discover slugs via stocks.getEntities()).\n * @param options Metric type and optional time range / resolution.\n */\n async getMetrics(\n symbol: string,\n options: MetricsOptions = {},\n ): Promise<ServingMetric[]> {\n const { metricType = \"sentiment\", startTime, endTime, maxDataPoints } = options;\n return this.client.get(\n `/api/v2/metrics/entity/${encodeURIComponent(symbol)}/metric/${encodeURIComponent(metricType)}`,\n {\n ...(startTime !== undefined && { startTime }),\n ...(endTime !== undefined && { endTime }),\n ...(maxDataPoints !== undefined && { maxDataPoints }),\n },\n );\n }\n\n /**\n * Get distribution data for a metric, broken down by a dimension (default: source).\n *\n * @param symbol Ticker symbol (e.g. \"AAPL\") or entity urlSlug.\n * @param metricType The metric to break down (e.g. \"mentions\", \"sentiment\").\n * @param options Optional dimension parameter.\n */\n async getDistribution(\n symbol: string,\n metricType: MetricType,\n options: MetricDistributionOptions = {},\n ): Promise<MetricDistribution> {\n const { dimension = \"source\" } = options;\n return this.client.get(\n `/api/v2/metrics/entity/${encodeURIComponent(symbol)}/distribution/${encodeURIComponent(metricType)}`,\n { dimension },\n );\n }\n}\n","import type { APIClient } from \"../client.js\";\nimport type { PreviewResponse } from \"../types.js\";\n\nexport interface EtfInfo {\n ticker: string;\n name: string;\n kbEntityId: string | null;\n urlSlug: string | null;\n issuer: string | null;\n trackedIndex: string | null;\n assetClass: string | null;\n}\n\nexport interface EtfHolding {\n ticker: string;\n name: string | null;\n /** Weight in the fund as a percentage (0-100). */\n weightPct: number;\n /** ISO date \"YYYY-MM-DD\". First date this holding appeared in the composition. */\n firstSeen: string | null;\n}\n\nexport interface EtfHoldings {\n ticker: string;\n issuer: string;\n issuerEndpoint: string | null;\n /** ISO date \"YYYY-MM-DD\". Composition snapshot date from the issuer. */\n asOfDate: string;\n /** Epoch seconds when SentiSense refreshed the composition. */\n fetchedAt: number | null;\n /** ISO date \"YYYY-MM-DD\". When the composition is scheduled to be refreshed next. */\n nextRefreshDue: string;\n totalHoldings: number;\n holdings: EtfHolding[];\n /** True when this is a top-N view rather than the full fund. */\n partial?: boolean | null;\n /** Issuer's reported total holdings when `partial=true`. */\n totalKnownHoldings?: number | null;\n}\n\nexport interface EtfAggregateCoverage {\n holdingsCount: number;\n holdingsCovered: number;\n /** Sum of weights (0-100) for the covered holdings. */\n weightCovered: number;\n partial?: boolean | null;\n totalKnownHoldings?: number | null;\n}\n\nexport interface WeightedConsensus {\n upsidePercent: number | null;\n consensusLabel: string | null;\n /** Fractions of covered AUM in each bucket. Sums to ~1.0. */\n distribution: Record<string, number>;\n totalAnalysts: number;\n}\n\nexport interface EtfAnalystContributor {\n ticker: string;\n weightPct: number;\n upsidePercent: number | null;\n consensusLabel: string | null;\n /** Signed contribution to the fund's weighted upside in percentage points. */\n contributionPp: number;\n}\n\nexport interface EtfAnalystAggregate {\n ticker: string;\n /** ISO date \"YYYY-MM-DD\". Composition snapshot date. */\n asOfDate: string | null;\n /** Epoch seconds when this rollup was computed. */\n computedAt: number;\n coverage: EtfAggregateCoverage;\n weightedConsensus: WeightedConsensus;\n /** Top contributors (up to 10) by absolute contribution to the weighted upside. */\n topContributors: EtfAnalystContributor[];\n}\n\nexport interface WeightedNetFlow {\n /** Weighted net dollar flow (buys - sells). Negative = net selling. */\n netDollars: number;\n buyDollars: number;\n sellDollars: number;\n /** Unweighted; for context. */\n buyTradeCount: number;\n /** Unweighted; for context. */\n sellTradeCount: number;\n distinctInsiderCount: number;\n}\n\nexport interface EtfInsiderContributor {\n ticker: string;\n weightPct: number;\n /** Per-stock net flow over the window (signed). */\n netDollars: number;\n /** Signed contribution to the weighted headline. */\n weightedNetDollars: number;\n tradeCount: number;\n}\n\nexport interface EtfInsiderAggregate {\n ticker: string;\n /** ISO date \"YYYY-MM-DD\". Composition snapshot date. */\n asOfDate: string | null;\n /** Epoch seconds when this rollup was computed. */\n computedAt: number;\n lookbackDays: number;\n coverage: EtfAggregateCoverage;\n weightedNetFlow: WeightedNetFlow;\n /** Top contributors (up to 10) by absolute weighted-net-dollar contribution. */\n topContributors: EtfInsiderContributor[];\n}\n\nexport interface EtfSentimentReading {\n sentiSenseScore: number | null;\n /** BULLISH / NEUTRAL / BEARISH. */\n scoreLabel: string;\n /** Epoch seconds when the underlying metric was produced. */\n asOfTimestamp: number | null;\n}\n\nexport interface EtfSentimentAggregate {\n ticker: string;\n /** ISO date \"YYYY-MM-DD\". Composition snapshot date. */\n asOfDate: string | null;\n /** Epoch seconds when this aggregate was assembled. */\n computedAt: number;\n coverage: EtfAggregateCoverage;\n /** Holdings-weighted SentiSense across the fund's constituents. */\n constituentsWeighted: EtfSentimentReading;\n /** Direct reading from mentions of the fund's own ticker. Null for low-mention funds. */\n direct: EtfSentimentReading | null;\n}\n\nexport interface GetEtfInsiderAggregateOptions {\n /** Trailing window for the trade aggregation. Typical values: 30, 90. Default 30. */\n lookbackDays?: number;\n}\n\n/**\n * ETF discovery, composition (holdings), and holdings-weighted aggregate views.\n *\n * Funds aren't rated by analysts directly, don't have insiders of their own, and\n * may not get many direct news mentions -- but the companies inside them do. The\n * aggregate endpoints synthesize fund-level views from each constituent's per-stock\n * data, weighted by allocation, with a coverage block so consumers see how much of\n * the fund's AUM the underlying data covered.\n *\n * Beta as of 2026-05-15: starting with a limited set of widely-traded funds.\n */\nexport class Etfs {\n constructor(private client: APIClient) {}\n\n /**\n * List every ETF tracked by SentiSense, sorted by ticker.\n */\n async list(): Promise<EtfInfo[]> {\n return this.client.get(\"/api/v1/etfs\");\n }\n\n /**\n * Get the full holdings composition for an ETF, including per-holding weights\n * and freshness metadata. Returns 404 for unknown ETFs or commodity-only funds.\n */\n async holdings(ticker: string): Promise<EtfHoldings> {\n return this.client.get(\n `/api/v1/etfs/${encodeURIComponent(ticker.toUpperCase())}/holdings`,\n );\n }\n\n /**\n * Get the holdings-weighted analyst consensus for an ETF, including the\n * top per-holding contributors that drive the weighted upside.\n */\n async analystAggregate(\n ticker: string,\n ): Promise<PreviewResponse<EtfAnalystAggregate>> {\n return this.client.get(\n `/api/v1/etfs/${encodeURIComponent(ticker.toUpperCase())}/aggregates/analyst`,\n );\n }\n\n /**\n * Get the holdings-weighted SEC Form 4 insider aggregate for an ETF over a\n * configurable trailing window, including per-holding `topContributors` with\n * signed contribution to the weighted headline.\n */\n async insiderAggregate(\n ticker: string,\n options?: GetEtfInsiderAggregateOptions,\n ): Promise<PreviewResponse<EtfInsiderAggregate>> {\n return this.client.get(\n `/api/v1/etfs/${encodeURIComponent(ticker.toUpperCase())}/aggregates/insider`,\n options,\n );\n }\n\n /**\n * Get two SentiSense Score readings side-by-side: `constituentsWeighted`\n * (precomputed daily weighted average across the fund's holdings) and `direct`\n * (score from mentions of the fund's own ticker). The two can diverge, and the\n * gap is itself information.\n */\n async sentimentAggregate(\n ticker: string,\n ): Promise<PreviewResponse<EtfSentimentAggregate>> {\n return this.client.get(\n `/api/v1/etfs/${encodeURIComponent(ticker.toUpperCase())}/aggregates/sentiment`,\n );\n }\n}\n","import type { APIClient } from \"../client.js\";\nimport type {\n InsiderActivityResponse,\n InsiderTrade,\n ClusterBuy,\n GetInsiderOptions,\n PreviewResponse,\n} from \"../types.js\";\n\nexport class Insider {\n constructor(private client: APIClient) {}\n\n /**\n * Get market-wide insider activity: top buys and sells aggregated by ticker.\n *\n * PRO-gated. Free-tier users receive a preview (top 5 per direction)\n * with `isPreview: true` in the response.\n */\n async getActivity(options?: GetInsiderOptions): Promise<PreviewResponse<InsiderActivityResponse>> {\n return this.client.get(\"/api/v1/insider/activity\", options);\n }\n\n /**\n * Get individual insider transactions for a specific stock.\n *\n * PRO-gated. Free users receive a preview of the top 5 transactions.\n */\n async getTrades(ticker: string, options?: GetInsiderOptions): Promise<PreviewResponse<InsiderTrade[]>> {\n return this.client.get(\n `/api/v1/insider/trades/${encodeURIComponent(ticker.toUpperCase())}`,\n options,\n );\n }\n\n /**\n * Get cluster buy signals: stocks where 3+ distinct insiders bought recently.\n *\n * PRO-gated. Free users receive a preview of the top 3 signals.\n */\n async getClusterBuys(options?: GetInsiderOptions): Promise<PreviewResponse<ClusterBuy[]>> {\n return this.client.get(\"/api/v1/insider/cluster-buys\", options);\n }\n}\n","import type { APIClient } from \"../client.js\";\nimport type {\n CongressTrade,\n PoliticianSummary,\n PoliticianDetail,\n GetPoliticianActivityOptions,\n GetPoliticiansOptions,\n GetPoliticianDirectoryOptions,\n GetPoliticianMemberOptions,\n PoliticianDirectory,\n PoliticianDirectoryResponse,\n PreviewResponse,\n} from \"../types.js\";\n\nexport class Politicians {\n constructor(private client: APIClient) {}\n\n /**\n * Get recent congressional STOCK Act trading activity across all politicians.\n *\n * PRO-gated. Free-tier users receive a preview (top 5 trades)\n * with `isPreview: true` in the response.\n *\n * The feed is longer than one response: a default 90-day window is routinely well over a\n * thousand disclosures, and without `limit` the server sends the first 200 with no marker\n * that it stopped. `totalCount` on the envelope is the real size on every tier, so page\n * with `limit` and `offset` rather than reading `data.length` as the total.\n *\n * ```typescript\n * const first = await client.politicians.getActivity({ limit: 100 });\n * for (let offset = 100; offset < first.totalCount!; offset += 100) {\n * const page = await client.politicians.getActivity({ limit: 100, offset });\n * // ... page.data\n * }\n * ```\n */\n async getActivity(\n options?: GetPoliticianActivityOptions,\n ): Promise<PreviewResponse<CongressTrade[]>> {\n return this.client.get(\"/api/v1/politicians/activity\", options);\n }\n\n /**\n * Get congressional trades for a specific stock.\n *\n * PRO-gated. Free users receive a preview of the top 3 trades.\n */\n async getFilings(\n ticker: string,\n options?: GetPoliticiansOptions,\n ): Promise<PreviewResponse<CongressTrade[]>> {\n return this.client.get(\n `/api/v1/politicians/filings/${encodeURIComponent(ticker.toUpperCase())}`,\n options,\n );\n }\n\n /**\n * Discover tracked members of Congress and the page slug identifying each, so you\n * can find who to query without knowing slugs upfront.\n *\n * Summary only, no trade data; use `getMember` for a member's filings.\n *\n * Unlike `getMembers`, this includes members who have **left Congress**, carrying\n * `former` and `servedUntil`. That roster lists who currently holds office, so a\n * former member is otherwise reachable only if you already know their slug.\n *\n * Requires an API key but does not consume monthly quota (per-minute rate limits\n * still apply), and is not tier-gated. Returns the unwrapped list payload.\n */\n async getDirectory(\n options?: GetPoliticianDirectoryOptions,\n ): Promise<PoliticianDirectory> {\n const resp = await this.client.get<PoliticianDirectoryResponse>(\n \"/api/v1/politicians/directory\",\n { ...options },\n );\n return resp.data;\n }\n\n /**\n * Get all tracked politicians with trading summary statistics.\n *\n * PRO-gated. Free users receive a preview of the top 5 members.\n *\n * Serves only members currently in office. Use `getDirectory` to enumerate\n * everyone tracked, former members included.\n */\n async getMembers(): Promise<PreviewResponse<PoliticianSummary[]>> {\n return this.client.get(\"/api/v1/politicians/members\");\n }\n\n /**\n * Get detailed profile for a single politician: summary, recent trades, top tickers.\n *\n * PRO-gated. Free users receive a preview-wrapped response.\n *\n * `data.recentTrades` is one page of the member's history, not all of it. Most members\n * have a few dozen disclosures and arrive complete in the default page; a handful have\n * thousands. `totalCount` on the envelope is the size of the whole history on every\n * tier, so page with `limit` and `offset` rather than reading `recentTrades.length` as\n * the total. `data.profile` and `data.topTickers` describe the whole history whatever\n * page you ask for, so `profile.totalTrades` does not shrink with a small `limit`.\n *\n * ```typescript\n * const first = await client.politicians.getMember(\"Ro-Khanna\", { limit: 500 });\n * for (let offset = 500; offset < first.totalCount!; offset += 500) {\n * const page = await client.politicians.getMember(\"Ro-Khanna\", { limit: 500, offset });\n * // ... page.data.recentTrades\n * }\n * ```\n */\n async getMember(\n slug: string,\n options?: GetPoliticianMemberOptions,\n ): Promise<PreviewResponse<PoliticianDetail>> {\n return this.client.get(\n `/api/v1/politicians/member/${encodeURIComponent(slug)}`,\n options,\n );\n }\n}\n","import type { APIClient } from \"../client.js\";\nimport type {\n Insight,\n GetInsightsOptions,\n PreviewResponse,\n} from \"../types.js\";\n\nexport interface GetStockInsightsRangeOptions {\n startDate: string;\n endDate: string;\n urgency?: \"low\" | \"medium\" | \"high\";\n insightType?: string;\n}\n\nexport interface GetLatestInsightsOptions {\n limit?: number;\n urgency?: \"low\" | \"medium\" | \"high\";\n}\n\nexport interface GetUserInsightsOptions {\n limit?: number;\n category?: string;\n}\n\nexport class Insights {\n constructor(private client: APIClient) {}\n\n /**\n * Get AI-generated insights for a specific stock, sorted by urgency then confidence.\n *\n * Returns the preview envelope: read the insights as `.data`. PRO callers get the\n * full list with `isPreview: false`; free callers get the top 3 with `isPreview: true`\n * and `totalCount` carrying the untruncated size.\n */\n async stock(\n ticker: string,\n options?: GetInsightsOptions,\n ): Promise<PreviewResponse<Insight[]>> {\n return this.client.get(\n `/api/v1/insights/stock/${encodeURIComponent(ticker.toUpperCase())}`,\n options,\n );\n }\n\n /**\n * Get AI insights for a stock within a date range.\n *\n * Returns the preview envelope: read the insights as `.data`. Free callers receive\n * the top 3, PRO callers the full list. The server returns 400 if `startDate` is\n * after `endDate`.\n */\n async stockRange(\n ticker: string,\n options: GetStockInsightsRangeOptions,\n ): Promise<PreviewResponse<Insight[]>> {\n return this.client.get(\n `/api/v1/insights/stock/${encodeURIComponent(ticker.toUpperCase())}/range`,\n options,\n );\n }\n\n /**\n * Get AI-generated market-level insights, sorted by urgency then confidence.\n *\n * Returns the preview envelope: read the insights as `.data`. PRO callers get the\n * full list with `isPreview: false`; free callers get the top 5 with `isPreview: true`\n * and `totalCount` carrying the untruncated size.\n */\n async market(): Promise<PreviewResponse<Insight[]>> {\n return this.client.get(\"/api/v1/insights/market\");\n }\n\n /**\n * Get the latest AI insights across all tracked stocks, newest first.\n *\n * Returns the preview envelope: read the insights as `.data`. Free callers receive\n * the top 5, PRO callers up to `limit` (clamped to 1-200).\n */\n async latest(\n options?: GetLatestInsightsOptions,\n ): Promise<PreviewResponse<Insight[]>> {\n return this.client.get(\"/api/v1/insights/latest\", options);\n }\n\n /**\n * Get personalized insights for the authenticated user.\n *\n * Biased toward the user's watchlist and portfolio when available; falls back\n * to market-level insights otherwise. API key authentication required.\n * Returns the preview envelope: read the insights as `.data`.\n */\n async user(\n options?: GetUserInsightsOptions,\n ): Promise<PreviewResponse<Insight[]>> {\n return this.client.get(\"/api/v1/insights/user\", options);\n }\n\n /**\n * Get available insight types for a specific stock.\n * API key required.\n *\n * Returns an array of insight type strings (e.g., `[\"sentiment_shift\", \"options_activity\"]`).\n */\n async types(ticker: string): Promise<string[]> {\n return this.client.get(\n `/api/v1/insights/stock/${encodeURIComponent(ticker.toUpperCase())}/types`,\n );\n }\n}\n","import type { APIClient } from \"../client.js\";\nimport type {\n GetFlowsOptions,\n GetHoldersOptions,\n Holder,\n InstitutionList,\n InstitutionListResponse,\n InstitutionalFlows,\n ListInstitutionsOptions,\n PreviewResponse,\n Quarter,\n TickerHolders,\n} from \"../types.js\";\n\nexport class Institutional {\n constructor(private client: APIClient) {}\n\n /** Get available 13F reporting quarters. */\n async getQuarters(): Promise<Quarter[]> {\n return this.client.get(\"/api/v1/institutional/quarters\");\n }\n\n /**\n * Get aggregate institutional activity per ticker for a quarter.\n *\n * `reportDate` is optional: omit it to get the latest available quarter, which may be\n * a still-open one holding only early filers. The response then carries `reportDate`\n * plus `isPending` and filer coverage counts so a partial quarter is clearly labeled.\n *\n * Returns the preview envelope, so the flows are one level down:\n * `const { data } = await client.institutional.getFlows(); data.inflows`.\n */\n async getFlows(\n reportDate?: string,\n options?: GetFlowsOptions,\n ): Promise<PreviewResponse<InstitutionalFlows>> {\n return this.client.get(\"/api/v1/institutional/flows\", {\n reportDate,\n ...options,\n });\n }\n\n /**\n * Get institutional holders for a specific stock.\n *\n * Returns the preview envelope wrapping a {@link TickerHolders} object, so the rows\n * are two levels down: `(await getHolders(t, d)).data.holders`, alongside ticker-level\n * totals like `holderCount`. Free callers get a truncated `holders` array with\n * `isPreview: true`.\n *\n * A widely held ticker returns thousands of rows: a megacap quarter is about\n * 6,000 holders and 1.5 MB. Pass `limit` unless you really want all of them.\n * Omitting `options` sends the original unbounded request.\n *\n * `limit` is the switch for the whole option set. With it, the response also carries\n * `returnedCount`, `offset`, and a `notableChanges` summary, so you can walk the list\n * without re-counting it. Without it, `offset` / `sortBy` / `sortDir` are ignored by the\n * server and you get the full unsorted list back with a 200.\n */\n async getHolders(\n ticker: string,\n reportDate: string,\n options?: GetHoldersOptions,\n ): Promise<PreviewResponse<TickerHolders>> {\n return this.client.get(\n `/api/v1/institutional/holders/${encodeURIComponent(ticker)}`,\n { reportDate, ...options },\n );\n }\n\n /**\n * Get activist investor positions (NEW or INCREASED).\n *\n * Returns the preview envelope, so read the rows as `.data`.\n */\n async getActivists(reportDate: string): Promise<PreviewResponse<Holder[]>> {\n return this.client.get(\"/api/v1/institutional/activist\", { reportDate });\n }\n\n /**\n * Discover institutions: a paginated, AUM-ranked list of filers (slug + metadata)\n * so you can find what to query without knowing slugs upfront.\n *\n * Each institution is rolled up by parent filer, so a multi-filer manager\n * (e.g. Vanguard) appears once with combined AUM. Summary only; use\n * `getInstitutionDetail` for a filer's full holdings.\n *\n * Requires an API key but does not consume monthly quota (per-minute rate\n * limits still apply). Returns the unwrapped list payload.\n */\n async listInstitutions(options?: ListInstitutionsOptions): Promise<InstitutionList> {\n const resp = await this.client.get<InstitutionListResponse>(\n \"/api/v1/institutional/institutions\",\n { ...options },\n );\n return resp.data;\n }\n\n /**\n * Get the full profile, summary stats, and current-quarter holdings for a\n * specific institutional filer.\n *\n * Resolved by URL slug (e.g. `Berkshire-Hathaway`) or numeric SEC CIK.\n * Free users receive the profile and top 10 holdings; PRO users receive the\n * full holdings array. Returns 404 if the slug or CIK is unknown.\n */\n async getInstitutionDetail(slugOrCik: string): Promise<unknown> {\n return this.client.get(\n `/api/v1/institutional/institution/${encodeURIComponent(slugOrCik)}`,\n );\n }\n}\n","import type { APIClient } from \"../client.js\";\nimport type { KBEntity } from \"../types.js\";\n\nexport class KB {\n constructor(private client: APIClient) {}\n\n /** Get popular entities for search suggestions. */\n async getPopularEntities(): Promise<KBEntity[]> {\n return this.client.get(\"/api/v1/kb/entities/popular\");\n }\n}\n","import type { APIClient } from \"../client.js\";\nimport type { MarketMood } from \"../types.js\";\n\nexport class MarketMoodResource {\n constructor(private client: APIClient) {}\n\n /** Get market mood data (scores, history, sectors). */\n async get(): Promise<MarketMood> {\n return this.client.get(\"/api/v2/market-mood\");\n }\n\n // TODO: accept a `days` param to control history length (the endpoint supports ?days=N).\n //\n // Market Mood is also reachable through `client.indexes`, which serves it in the shared\n // index envelope alongside fed-sentiment and ai-sentiment. Use this resource when you want\n // the phase band, weekly change, per-signal breakdown and per-sector map; use `indexes`\n // when you want every index to answer the same shape. Both report the same headline number.\n}\n","import type { APIClient } from \"../client.js\";\nimport type { MarketSummary } from \"../types.js\";\n\nexport class MarketSummaryResource {\n constructor(private client: APIClient) {}\n\n /** Get the AI-generated market summary with headline and analysis. */\n async get(): Promise<MarketSummary> {\n return this.client.get(\"/api/v1/market-summary\");\n }\n}\n","import type { APIClient } from \"../client.js\";\nimport type {\n EtfScreenerExecuteResponse,\n EtfScreenerRow,\n FeaturedScreen,\n ScreenerExecuteOptions,\n ScreenerExecuteResponse,\n ScreenerFieldCatalog,\n ScreenerFieldDescriptor,\n ScreenerFieldOption,\n ScreenerFilter,\n ScreenerPlan,\n ScreenerRow,\n ScreenerScreensResponse,\n ScreenerSort,\n} from \"../types.js\";\n\n/**\n * Screener: filter the tracked universe on the SentiSense Score, attention,\n * analyst consensus, technicals and price in a single query. It is the one\n * surface where our own signals sit in the same `WHERE` clause as the market\n * data, which is the point: screening on analyst ratings alone is something a\n * dozen free tools do, screening on analyst ratings *where the Score disagrees*\n * is not.\n *\n * Every screen is a {@link ScreenerPlan}. Take one from {@link screens} or\n * build your own, then hand it to {@link run} or {@link runEtfs}.\n *\n * Three field semantics are worth knowing before you write a filter, because\n * guessing them wrong produces a screen that looks fine and means nothing:\n *\n * - **`ANALYST_RATING_MEAN` is inverted.** It is the vendor's 1-to-5 scale\n * where `1.0` is strong buy, so bullish is `LTE 2.5`, not `GTE`. Prefer\n * `ANALYST_BUY_RATIO_PCT`, which runs the intuitive direction.\n * - **`MA_CROSS_STATE` is ordinal**, not a percentage: `1` golden cross (50-day\n * above 200-day), `-1` death cross, `0` neither. Use `EQ`.\n * - **`SENTIMENT_DIRECTION` is the sign of the 7-day SentiSense Score**\n * (`1` / `0` / `-1`) with a neutral band of plus-or-minus 5. Despite the name\n * it is not sentiment polarity, and `0` matches only an exact zero, so it\n * returns almost nothing.\n *\n * The Score fields (`SENTI_SCORE_7D`, `SENTI_SCORE_1M`, `SCORE_CHANGE_7D`) are\n * the SentiSense Score, not polarity: unbounded, banded at 5 / 13 / 23 either\n * side of zero. Filter on those band edges, not on values like `0.5`, which\n * behave as \"any positive score\".\n *\n * Nulls never match, in either direction: `RETURN_1Y >= 0` and `RETURN_1Y < 0`\n * do not partition the universe, because a stock listed four months ago is in\n * neither result. If a screen returns fewer rows than you expect, check\n * coverage before you check your thresholds.\n *\n * Screens read a snapshot that refreshes every 20 minutes, so this is not a\n * quote feed. Use `client.stocks.getQuote()` for live prices.\n */\nexport class Screener {\n constructor(private client: APIClient) {}\n\n /**\n * Every filterable field, with its unit, operators and description, for both\n * universes.\n *\n * Build a filter UI from this rather than hardcoding the list and you inherit\n * new fields as they ship. The ETF `STRING` fields (`ISSUER`, `ASSET_CLASS`,\n * `TRACKED_INDEX`) come back with their `values` populated from the live\n * universe, so pickers stay current without a redeploy.\n */\n async fields(): Promise<ScreenerFieldCatalog> {\n return this.client.get(\"/api/v1/screener/fields\");\n }\n\n /**\n * The curated screens shipped in the product, each with a runnable plan.\n *\n * Each `plan` round-trips straight into {@link run} (or {@link runEtfs} when\n * `plan.universe === \"ETF\"`) with nothing to rebuild.\n *\n * Their filters identify the field with `field` rather than `fieldName`.\n * Both keys are accepted on the way in, so read either when inspecting a plan\n * you did not build yourself.\n */\n async screens(): Promise<ScreenerScreensResponse> {\n return this.client.get(\"/api/v1/screener/screens\");\n }\n\n /**\n * Run a screen against the stock universe.\n *\n * `tickers` is optional: omit it to screen the whole tracked universe, pass a\n * list to screen a watchlist. `limit` sits next to the plan rather than\n * inside it, because a plan is a stored object and paging is a transport\n * concern; it defaults to 100 and caps at 500.\n *\n * Read `matched` before you read `results`: it is the count before `limit`\n * was applied, so a `matched` above your `limit` means you are holding the\n * top slice under the plan's sort, not the whole answer.\n *\n * @example\n * ```ts\n * const res = await client.screener.run({\n * plan: {\n * filters: [\n * { fieldName: \"SENTI_SCORE_7D\", op: \"GTE\", value: 13 },\n * { fieldName: \"ANALYST_BUY_RATIO_PCT\", op: \"LTE\", value: 30 },\n * { fieldName: \"ANALYST_COUNT\", op: \"GTE\", value: 5 },\n * ],\n * sort: { fieldName: \"SENTI_SCORE_7D\", dir: \"DESC\" },\n * },\n * limit: 25,\n * });\n * ```\n */\n async run(options: ScreenerExecuteOptions): Promise<ScreenerExecuteResponse> {\n return this.client.post(\"/api/v1/screener/execute\", options);\n }\n\n /**\n * Run a screen against the ETF universe.\n *\n * Same request shape as {@link run}, against a different field vocabulary:\n * take the ETF names from `fields().etf`. `IN` / `NOT_IN` take a `values`\n * array instead of `value` and are the operators for the string fields\n * (`ISSUER`, `ASSET_CLASS`, `TRACKED_INDEX`).\n *\n * `CONSTITUENTS_WEIGHTED_SENTISENSE` is the holdings-weighted SentiSense\n * Score across what the fund owns and is usually the one you want;\n * `DIRECT_SENTISENSE` is the Score from chatter about the fund ticker itself,\n * which on a broad index fund is mostly macro noise. `WEIGHT_COVERED_PCT`\n * tells you how much of the fund's weight had constituent data behind the\n * weighted number.\n */\n async runEtfs(options: ScreenerExecuteOptions): Promise<EtfScreenerExecuteResponse> {\n return this.client.post(\"/api/v1/screener/etfs/execute\", options);\n }\n}\n\n// Re-export for convenience so callers can `import type { ScreenerPlan }`\n// from the resource module instead of `../types`.\nexport type {\n EtfScreenerExecuteResponse,\n EtfScreenerRow,\n FeaturedScreen,\n ScreenerExecuteOptions,\n ScreenerExecuteResponse,\n ScreenerFieldCatalog,\n ScreenerFieldDescriptor,\n ScreenerFieldOption,\n ScreenerFilter,\n ScreenerPlan,\n ScreenerRow,\n ScreenerScreensResponse,\n ScreenerSort,\n};\n","import type { APIClient } from \"../client.js\";\nimport type {\n AISummary,\n ChartData,\n ChartDataPoint,\n CompanyKpisData,\n FloatInfo,\n Fundamentals,\n FundamentalsPeriodsResponse,\n TtmFundamentals,\n GetAISummaryOptions,\n GetChartOptions,\n GetDescriptionsOptions,\n GetFundamentalsOptions,\n GetImagesOptions,\n GetMetricsBreakdownOptions,\n GetProfileOptions,\n GetSimilarOptions,\n KpiCoverageResponse,\n KpiTypeEntry,\n MarketStatus,\n MetricsBreakdown,\n OptionsSummary,\n PreviewResponse,\n SimilarStock,\n ShortInterest,\n ShortVolume,\n StockDetail,\n StockEntity,\n StockSentiment,\n StockImage,\n StockPrice,\n StockProfile,\n StockQuote,\n} from \"../types.js\";\n\nexport class Stocks {\n constructor(private client: APIClient) {}\n\n /** List all available ticker symbols. */\n async list(): Promise<string[]> {\n return this.client.get(\"/api/v1/stocks\");\n }\n\n /** List all stocks with name, kbEntityId, urlSlug. */\n async listDetailed(): Promise<StockDetail[]> {\n return this.client.get(\"/api/v1/stocks/detailed\");\n }\n\n /** Get popular ticker symbols. */\n async listPopular(): Promise<string[]> {\n return this.client.get(\"/api/v1/stocks/popular\");\n }\n\n /** Get popular stocks with details. */\n async listPopularDetailed(): Promise<StockDetail[]> {\n return this.client.get(\"/api/v1/stocks/popular/detailed\");\n }\n\n /** Get real-time price for a single ticker. */\n async getPrice(ticker: string): Promise<StockPrice> {\n return this.client.get(\"/api/v1/stocks/price\", { ticker });\n }\n\n /**\n * Get aggregate quote snapshot: live price, today OHLC, 52-week range,\n * market cap, P/E, EPS TTM, and dividend yield in a single call.\n * All fields except `ticker` may be null when upstream data is unavailable.\n */\n async getQuote(ticker: string): Promise<StockQuote> {\n return this.client.get(`/api/v1/stocks/${encodeURIComponent(ticker)}/quote`);\n }\n\n /** Get real-time prices for multiple tickers. */\n async getPrices(tickers: string[]): Promise<StockPrice[]> {\n return this.client.get(\"/api/v1/stocks/prices\", {\n tickers: tickers.join(\",\"),\n });\n }\n\n /** Get batch company logo URLs. */\n async getImages(\n tickers: string[],\n options?: GetImagesOptions,\n ): Promise<Record<string, StockImage>> {\n return this.client.get(\"/api/v1/stocks/images\", {\n tickers: tickers.join(\",\"),\n ...options,\n });\n }\n\n /** Get company profiles with branding, market cap, sector. */\n async getDescriptions(\n tickers: string[],\n options?: GetDescriptionsOptions,\n ): Promise<Record<string, StockProfile>> {\n return this.client.get(\"/api/v1/stocks/descriptions\", {\n tickers: tickers.join(\",\"),\n ...options,\n });\n }\n\n /** Get peer/similar stocks. */\n async getSimilar(ticker: string, options?: GetSimilarOptions): Promise<SimilarStock[]> {\n return this.client.get(`/api/v1/stocks/${encodeURIComponent(ticker)}/similar`, options);\n }\n\n /** Get company profile (CEO, sector, industry, market data). */\n async getProfile(ticker: string, options?: GetProfileOptions): Promise<StockProfile> {\n return this.client.get(`/api/v1/stocks/${encodeURIComponent(ticker)}/profile`, options);\n }\n\n /**\n * Get the headline sentiment picture for a stock in one call.\n *\n * Returns the SentiSense Score with its 30-day regime, mention volume and social\n * dominance, per-source tone in `bySource`, plus related tickers, story drivers, a\n * narrative and an FAQ. Available in full on every API-key tier.\n *\n * Use `entityMetrics.getMetrics(ticker, \"sentiment\", ...)` instead when you need a time\n * series over a specific window rather than the headline read. Returns 404 for tickers\n * with no sentiment coverage.\n */\n async getSentiment(ticker: string): Promise<PreviewResponse<StockSentiment>> {\n return this.client.get(\n `/api/v1/stocks/${encodeURIComponent(ticker)}/sentiment`,\n );\n }\n\n /** Get related KB entities (people, products, partners). */\n async getEntities(ticker: string): Promise<StockEntity[]> {\n return this.client.get(`/api/v1/stocks/${encodeURIComponent(ticker)}/entities`);\n }\n\n /**\n * Get AI-generated stock analysis report. Requires PRO tier.\n *\n * `depth: \"deep\"` returns the full curated report and consumes one report view on\n * metered tiers; the default `\"basic\"` returns the one-paragraph summary.\n *\n * The deprecated `forceRefresh` option is accepted and discarded, not forwarded.\n */\n async getAISummary(ticker: string, options?: GetAISummaryOptions): Promise<AISummary> {\n const { forceRefresh: _forceRefresh, ...params } = options ?? {};\n return this.client.get(`/api/v1/stocks/${encodeURIComponent(ticker)}/ai-summary`, params);\n }\n\n /** Get sentiment/mention metrics breakdown by entity. */\n async getMetricsBreakdown(\n ticker: string,\n metricType: string,\n options?: GetMetricsBreakdownOptions,\n ): Promise<MetricsBreakdown> {\n return this.client.get(\n `/api/v1/stocks/${encodeURIComponent(ticker)}/metrics/${encodeURIComponent(metricType)}/breakdown`,\n options,\n );\n }\n\n /**\n * Get historical OHLCV chart data.\n *\n * The API returns a bare array of points; this normalizes it to\n * `{ ticker, timeframe, data }`. `timeframe` echoes the requested value\n * (defaulting to \"1M\", matching the server default when omitted).\n */\n async getChart(ticker: string, options?: GetChartOptions): Promise<ChartData> {\n const data = await this.client.get<ChartDataPoint[]>(\"/api/v1/stocks/chart\", {\n ticker,\n ...options,\n });\n return { ticker, timeframe: options?.timeframe ?? \"1M\", data };\n }\n\n /** Get current market open/closed/pre-market/after-hours status. */\n async getMarketStatus(): Promise<MarketStatus> {\n return this.client.get(\"/api/v1/stocks/market-status\");\n }\n\n /**\n * Get financial statement data for one reporting period: income statement, balance sheet,\n * and cash flow, including `capitalExpenditure` and `freeCashFlow`.\n *\n * Capital expenditure is signed as filed, so normally negative. See {@link Fundamentals}\n * for the free-cash-flow relationship and when it is `null`.\n */\n async getFundamentals(ticker: string, options?: GetFundamentalsOptions): Promise<Fundamentals> {\n return this.client.get(\"/api/v1/stocks/fundamentals\", { ticker, ...options });\n }\n\n /** Get available fiscal periods. The periods are in `periods`. */\n async getFundamentalsPeriods(ticker: string): Promise<FundamentalsPeriodsResponse> {\n return this.client.get(\"/api/v1/stocks/fundamentals/periods\", { ticker });\n }\n\n /**\n * Get the trailing-twelve-month fundamentals snapshot: TTM ratios, a different\n * shape from the per-period statement data `getFundamentals()` returns.\n */\n async getCurrentFundamentals(ticker: string): Promise<TtmFundamentals> {\n return this.client.get(\"/api/v1/stocks/fundamentals/current\", { ticker });\n }\n\n /** Get historical revenue data. */\n async getHistoricalRevenue(ticker: string): Promise<unknown> {\n return this.client.get(\"/api/v1/stocks/fundamentals/historical/revenue\", { ticker });\n }\n\n /** Get short interest metrics (FINRA). */\n async getShortInterest(ticker: string): Promise<ShortInterest> {\n return this.client.get(\"/api/v1/stocks/short-interest\", { ticker });\n }\n\n /** Get float information. */\n async getFloat(ticker: string): Promise<FloatInfo> {\n return this.client.get(\"/api/v1/stocks/float\", { ticker });\n }\n\n /** Get short volume trading data. */\n async getShortVolume(ticker: string): Promise<ShortVolume> {\n return this.client.get(\"/api/v1/stocks/short-volume\", { ticker });\n }\n\n /**\n * Get company-specific KPI time-series for a ticker. Returns curated GAAP and\n * non-GAAP metrics from earnings filings (e.g. iPhone unit sales, Tesla deliveries,\n * AWS revenue).\n *\n * Free users receive metadata only with an empty `kpis` list; PRO users receive\n * the full series. Returns 404 for tickers that do not yet have curated coverage.\n *\n * Coverage today: near-complete for the S&P 500 plus extended universe\n * (~500 tickers). Use `listKpiCoverage()` to enumerate.\n */\n async getKpis(ticker: string): Promise<PreviewResponse<CompanyKpisData>> {\n return this.client.get(\n `/api/v1/stocks/${encodeURIComponent(ticker.toUpperCase())}/kpis`,\n );\n }\n\n /**\n * List every ticker with curated KPI coverage. Returns `{count, tickers: [...]}`\n * with lightweight metadata (ticker, companyName, lastUpdated, kpiCount).\n * Sorted alphabetically by ticker.\n *\n * Auth: API key required, but the call does NOT consume your monthly quota\n * (rate-limit-per-minute still applies).\n */\n async listKpiCoverage(): Promise<KpiCoverageResponse> {\n return this.client.get(\"/api/v1/stocks/with-kpis\");\n }\n\n /**\n * List the KPI metadata tuples available for a ticker (`id, name, category,\n * chartType`) without paying the cost of the full series payload. Mirrors\n * the `/api/v1/insights/stock/{ticker}/types` precedent.\n *\n * Auth: API key required, no quota cost. 404 if the ticker has no curated KPIs.\n */\n async getKpiTypes(ticker: string): Promise<KpiTypeEntry[]> {\n return this.client.get(\n `/api/v1/stocks/${encodeURIComponent(ticker.toUpperCase())}/kpis/types`,\n );\n }\n\n /**\n * Get the end-of-day options dossier for one stock or ETF: the session's aggregate, its\n * percentile context, the open-interest wall structure with max pain, and the contracts\n * whose volume ran far ahead of their open interest.\n *\n * End of day, not live. `asOf` is the prior trading session and the data refreshes the\n * following morning, so this is positioning, not a quote feed.\n *\n * **`data` is `null` for a ticker outside the covered universe**, which is the most\n * actively optioned US names plus the tracked ETFs, and for a covered ticker with no\n * snapshot yet. An unknown symbol behaves the same way rather than answering 404, so treat\n * a null as \"no coverage\", never as an error. A covered ticker still building its baseline\n * returns its raw readings with the percentiles omitted.\n *\n * Percentiles compare a ticker to its own trailing history, never to another ticker, so an\n * ETF's readings are not comparable with a single stock's.\n *\n * Tiering: a PRO key always receives the full dossier. A FREE key receives it for the first\n * ten calls each calendar month and a headline-only preview after that, with `isPreview`\n * true; calls that return a null `data` never spend that allowance.\n */\n async getOptionsSummary(ticker: string): Promise<PreviewResponse<OptionsSummary | null>> {\n return this.client.get(\n `/api/v1/stocks/${encodeURIComponent(ticker.toUpperCase())}/options/summary`,\n );\n }\n}\n","import type { APIClient } from \"../client.js\";\nimport type {\n IndexConstituent,\n IndexHistoryPoint,\n IndexHistoryResponse,\n IndexListing,\n IndexListResponse,\n IndexSnapshot,\n} from \"../types.js\";\n\n/**\n * Indexes: composite scalars tracked over time, each blending its own inputs\n * into one number on a stated scale. Every index answers on the same envelope,\n * so you write one renderer and get every current and future SentiSense index.\n *\n * Two archetypes share that envelope. A **basket** index weight-averages\n * tracked entities and fills `constituents` / `basketSize` / `coverage` /\n * `totalMentions`; a **composite** index is built from signals instead and\n * returns `null` for all four by construction. See {@link IndexSnapshot}.\n *\n * @see IndexSnapshot\n */\nexport class Indexes {\n constructor(private client: APIClient) {}\n\n /**\n * List every index the platform publishes: id, display name, one-line\n * description, the scale it lives on, its access tier, and where its richest\n * view lives.\n *\n * Iterate this rather than hardcoding ids. Every `indexId` it advertises\n * resolves on {@link get} and {@link history}.\n */\n async list(): Promise<IndexListResponse> {\n return this.client.get(\"/api/v1/indexes\");\n }\n\n /**\n * Latest reading for one index.\n *\n * Check `constituents` for `null` before iterating: it is `null` on a\n * composite index like `market-mood`, which has no constituents by\n * construction. For Market Mood this is the narrowed view; the phase band,\n * weekly change, per-signal breakdown and per-sector map live on\n * `client.marketMood.get()`, and both report the same headline number.\n *\n * @param indexId slug from {@link list}, e.g. `\"fed-sentiment\"`.\n */\n async get(indexId: string): Promise<IndexSnapshot> {\n return this.client.get(`/api/v1/indexes/${indexId}`);\n }\n\n /**\n * Historical scalar series for one index, for charting.\n *\n * Thin or low-coverage buckets are withheld, so the series can be shorter\n * than `days` and can contain gaps. Plot against each point's `date`.\n *\n * @param indexId slug from {@link list}.\n * @param days days of history to return. Defaults to the API's own 180.\n */\n async history(indexId: string, days?: number): Promise<IndexHistoryResponse> {\n return this.client.get(\n `/api/v1/indexes/${indexId}/history`,\n days === undefined ? undefined : { days },\n );\n }\n}\n\n// Re-export for convenience so callers can `import type { IndexListing }`\n// from the resource module instead of `../types`.\nexport type {\n IndexConstituent,\n IndexHistoryPoint,\n IndexHistoryResponse,\n IndexListing,\n IndexListResponse,\n IndexSnapshot,\n};\n","import type { APIClient } from \"../client.js\";\nimport type {\n TrackerListing,\n TrackerListResponse,\n TrackerSnapshot,\n TrackerSnapshotResponse,\n} from \"../types.js\";\n\n/**\n * Trackers: observational data products published as a standardized\n * `TrackerSnapshot` envelope. Every tracker (institution rankings,\n * hedge-fund reported returns, social trackers, surveillance dashboards)\n * returns the same shape, so consumers write one renderer per `viewType` and\n * get every current and future SentiSense tracker for free.\n *\n * @see TrackerSnapshot\n */\nexport class Trackers {\n constructor(private client: APIClient) {}\n\n /**\n * List every publicly-visible tracker: id, display name, category,\n * one-line description, and the methodology anchor to link out to.\n */\n async list(): Promise<TrackerListResponse> {\n return this.client.get(\"/api/v1/trackers\");\n }\n\n /**\n * Standardized snapshot envelope for one tracker.\n *\n * Returns the envelope as-is: `{ isPreview, previewReason, totalCount?, data }`.\n * When `data.viewType === \"table\"` the rows live at `data.rows[]`; when\n * `\"choropleth\"` they live at `data.geo[]`; etc. Dispatch on `viewType`\n * in your renderer.\n *\n * @param trackerId slug from {@link list}, e.g. `\"institution-concentration\"`.\n * @param params provider-specific query params (e.g. `{ scope: \"us\" }` for\n * geographically-scoped trackers like hantavirus). Unknown keys are ignored.\n */\n async get(\n trackerId: string,\n params?: Record<string, string | number | boolean>,\n ): Promise<TrackerSnapshotResponse> {\n return this.client.get(`/api/v1/trackers/${trackerId}`, params);\n }\n}\n\n// Re-export for convenience so callers can `import type { TrackerListing }`\n// from the resource module instead of `../types`.\nexport type {\n TrackerListing,\n TrackerListResponse,\n TrackerSnapshot,\n TrackerSnapshotResponse,\n};\n","export const VERSION = \"0.44.0\";\n","import {\n APIError,\n AuthenticationError,\n DeepHistoryUnavailableError,\n NotFoundError,\n RateLimitError,\n SentiSenseError,\n} from \"./errors.js\";\nimport { Analyst } from \"./resources/analyst.js\";\nimport { Calendar } from \"./resources/calendar.js\";\nimport { Documents } from \"./resources/documents.js\";\nimport { Earnings } from \"./resources/earnings.js\";\nimport { EntityMetrics } from \"./resources/entityMetrics.js\";\nimport { Etfs } from \"./resources/etfs.js\";\nimport { Insider } from \"./resources/insider.js\";\nimport { Politicians } from \"./resources/politicians.js\";\nimport { Insights } from \"./resources/insights.js\";\nimport { Institutional } from \"./resources/institutional.js\";\nimport { KB } from \"./resources/kb.js\";\nimport { MarketMoodResource } from \"./resources/marketMood.js\";\nimport { MarketSummaryResource } from \"./resources/marketSummary.js\";\nimport { Screener } from \"./resources/screener.js\";\nimport { Stocks } from \"./resources/stocks.js\";\nimport { Indexes } from \"./resources/indexes.js\";\nimport { Trackers } from \"./resources/trackers.js\";\nimport type { SentiSenseOptions } from \"./types.js\";\nimport { VERSION } from \"./version.js\";\n\nconst DEFAULT_BASE_URL = \"https://app.sentisense.ai\";\nconst DEFAULT_TIMEOUT = 30_000;\nconst DEFAULT_MAX_RETRIES = 3;\nconst BASE_DELAY_MS = 1_000;\nconst MAX_DELAY_MS = 60_000;\n// Used when a 202 arrives without a usable Retry-After header.\nconst DEEP_HISTORY_FALLBACK_WAIT_S = 3;\n\n// Upper bounds on any server-supplied Retry-After. Rate limiting gets the longer ceiling\n// because a genuine limit window is legitimately minutes, while a deep-history warm-up is\n// seconds. Without a ceiling an oversized header value strands the caller indefinitely.\nconst MAX_DEEP_HISTORY_WAIT_S = 30;\nconst MAX_RATE_LIMIT_WAIT_S = 120;\nconst RATE_LIMIT_FALLBACK_WAIT_S = 60;\n\n/**\n * A `Retry-After` header as a usable number of seconds, clamped to `[0.5, maxWaitS]`, or\n * `undefined` when there is no usable value.\n *\n * `Retry-After` is vendor-controlled and may legally carry an HTTP-date rather than a\n * number of seconds, in which case parsing yields `NaN`. Left unguarded that produced a\n * `NaN` delay which compared false against every threshold and retried instantly in a busy\n * loop, and a `NaN` on the error object that silently broke a caller's own backoff.\n * Anything that is not a finite number is treated as absent.\n */\nfunction clampRetryAfter(\n raw: string | null,\n maxWaitS: number,\n): number | undefined {\n if (!raw) return undefined;\n const parsed = Number(raw);\n if (!Number.isFinite(parsed)) return undefined;\n return Math.min(Math.max(0.5, parsed), maxWaitS);\n}\n\n/** Same clamp, resolved to `defaultS` when the header gives us nothing to go on. */\nfunction retryAfterSeconds(\n raw: string | null,\n defaultS: number,\n maxWaitS: number,\n): number {\n return clampRetryAfter(raw, maxWaitS) ?? defaultS;\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/** @internal HTTP interface exposed to resource classes. */\nexport interface APIClient {\n get<T = unknown>(path: string, params?: object): Promise<T>;\n post<T = unknown>(path: string, body: unknown): Promise<T>;\n}\n\nexport class SentiSense implements APIClient {\n private baseUrl: string;\n private apiKey: string | undefined;\n private timeout: number;\n private maxRetries: number;\n private userAgent: string;\n\n readonly stocks: Stocks;\n readonly documents: Documents;\n readonly etfs: Etfs;\n readonly institutional: Institutional;\n readonly insider: Insider;\n readonly politicians: Politicians;\n readonly insights: Insights;\n readonly analyst: Analyst;\n readonly entityMetrics: EntityMetrics;\n readonly marketMood: MarketMoodResource;\n readonly marketSummary: MarketSummaryResource;\n readonly kb: KB;\n readonly indexes: Indexes;\n readonly trackers: Trackers;\n readonly calendar: Calendar;\n readonly earnings: Earnings;\n readonly screener: Screener;\n\n constructor(options: SentiSenseOptions = {}) {\n this.apiKey = options.apiKey;\n this.baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\\/+$/, \"\");\n this.timeout = options.timeout ?? DEFAULT_TIMEOUT;\n this.maxRetries = options.maxRetries ?? DEFAULT_MAX_RETRIES;\n // A header value cannot carry CR/LF, so collapse them rather than letting a caller's\n // string decide where the header block ends.\n const suffix = options.userAgentSuffix?.replace(/[\\r\\n]+/g, \" \").trim();\n this.userAgent = suffix\n ? `sentisense-node/${VERSION} ${suffix}`\n : `sentisense-node/${VERSION}`;\n\n this.stocks = new Stocks(this);\n this.documents = new Documents(this);\n this.etfs = new Etfs(this);\n this.institutional = new Institutional(this);\n this.insider = new Insider(this);\n this.politicians = new Politicians(this);\n this.insights = new Insights(this);\n this.analyst = new Analyst(this);\n this.entityMetrics = new EntityMetrics(this);\n this.marketMood = new MarketMoodResource(this);\n this.marketSummary = new MarketSummaryResource(this);\n this.kb = new KB(this);\n this.indexes = new Indexes(this);\n this.trackers = new Trackers(this);\n this.calendar = new Calendar(this);\n this.earnings = new Earnings(this);\n this.screener = new Screener(this);\n }\n\n /** @internal */\n async get<T = unknown>(path: string, params?: object): Promise<T> {\n const url = this.buildUrl(path, params);\n const headers: Record<string, string> = {\n \"Accept\": \"application/json\",\n };\n\n if (this.apiKey) {\n headers[\"X-SentiSense-API-Key\"] = this.apiKey;\n }\n\n // User-Agent is only set in Node.js (browsers disallow it)\n if (typeof process !== \"undefined\" && process.versions?.node) {\n headers[\"User-Agent\"] = this.userAgent;\n }\n\n let delayMs = 0;\n\n for (let attempt = 0; attempt <= this.maxRetries; attempt++) {\n if (delayMs > 0) {\n await sleep(delayMs);\n delayMs = 0;\n }\n\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await fetch(url, {\n method: \"GET\",\n headers,\n signal: controller.signal,\n });\n\n // 202 means a deep chart range is still being built server-side. It is a 2xx, so\n // without this it would fall through and return an empty array: the caller would\n // see \"no data\" rather than \"not ready yet\", which is the exact confusion the\n // status code exists to prevent. Retry honouring Retry-After, then surface it.\n if (response.status === 202) {\n const waitSeconds = retryAfterSeconds(\n response.headers.get(\"Retry-After\"),\n DEEP_HISTORY_FALLBACK_WAIT_S,\n MAX_DEEP_HISTORY_WAIT_S,\n );\n try { await response.body?.cancel(); } catch { /* ignore */ }\n if (attempt < this.maxRetries) {\n delayMs = waitSeconds * 1000;\n continue;\n }\n throw new DeepHistoryUnavailableError(\n \"Deep history is still being assembled. Retry in a few seconds.\",\n waitSeconds,\n );\n }\n\n if (!response.ok) {\n const isRetryable = response.status === 429 || response.status >= 500;\n if (isRetryable && attempt < this.maxRetries) {\n if (response.status === 429) {\n delayMs = retryAfterSeconds(\n response.headers.get(\"Retry-After\"),\n RATE_LIMIT_FALLBACK_WAIT_S,\n MAX_RATE_LIMIT_WAIT_S,\n ) * 1000;\n } else {\n delayMs = Math.min(BASE_DELAY_MS * Math.pow(2, attempt), MAX_DELAY_MS) + Math.random() * 1000;\n }\n try { await response.body?.cancel(); } catch { /* ignore */ }\n continue;\n }\n await this.handleErrorResponse(response);\n }\n\n return (await response.json()) as T;\n } catch (error) {\n if (error instanceof SentiSenseError) throw error;\n if (error instanceof Error && error.name === \"AbortError\") {\n throw new SentiSenseError(`Request timed out after ${this.timeout}ms`);\n }\n throw new SentiSenseError(\n error instanceof Error ? error.message : \"Unknown error\",\n );\n } finally {\n clearTimeout(timer);\n }\n }\n\n throw new SentiSenseError(\"All retries exhausted\");\n }\n\n /** @internal */\n async post<T = unknown>(path: string, body: unknown): Promise<T> {\n const url = this.buildUrl(path);\n const headers: Record<string, string> = {\n \"Accept\": \"application/json\",\n \"Content-Type\": \"application/json\",\n };\n\n if (this.apiKey) {\n headers[\"X-SentiSense-API-Key\"] = this.apiKey;\n }\n\n if (typeof process !== \"undefined\" && process.versions?.node) {\n headers[\"User-Agent\"] = this.userAgent;\n }\n\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await fetch(url, {\n method: \"POST\",\n headers,\n body: JSON.stringify(body),\n signal: controller.signal,\n });\n\n if (!response.ok) {\n await this.handleErrorResponse(response);\n }\n\n return (await response.json()) as T;\n } catch (error) {\n if (error instanceof SentiSenseError) throw error;\n if (error instanceof Error && error.name === \"AbortError\") {\n throw new SentiSenseError(`Request timed out after ${this.timeout}ms`);\n }\n throw new SentiSenseError(\n error instanceof Error ? error.message : \"Unknown error\",\n );\n } finally {\n clearTimeout(timer);\n }\n }\n\n private buildUrl(path: string, params?: object): string {\n const url = new URL(path, this.baseUrl);\n if (params) {\n for (const [key, value] of Object.entries(params as Record<string, unknown>)) {\n if (value !== undefined && value !== null) {\n url.searchParams.set(key, String(value));\n }\n }\n }\n return url.toString();\n }\n\n private async handleErrorResponse(response: Response): Promise<never> {\n let body: { error?: string; message?: string } = {};\n try {\n body = await response.json();\n } catch {\n // Response may not be JSON\n }\n\n const message = body.message ?? response.statusText ?? \"API request failed\";\n const code = body.error;\n\n switch (response.status) {\n case 401:\n case 403:\n throw new AuthenticationError(message, response.status, code);\n case 404:\n throw new NotFoundError(message, code);\n case 429: {\n // Same clamp the retry loop uses, so a caller running its own backoff off\n // `error.retryAfter` gets a number it can pass to setTimeout, or nothing at all.\n const retryAfter = clampRetryAfter(\n response.headers.get(\"Retry-After\"),\n MAX_RATE_LIMIT_WAIT_S,\n );\n throw new RateLimitError(message, code, retryAfter);\n }\n default:\n throw new APIError(message, response.status, code);\n }\n }\n}\n"],"mappings":"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","names":[]}
package/dist/index.d.mts CHANGED
@@ -2908,6 +2908,6 @@ declare class APIError extends SentiSenseError {
2908
2908
  constructor(message: string, status: number, code?: string);
2909
2909
  }
2910
2910
 
2911
- declare const VERSION = "0.43.0";
2911
+ declare const VERSION = "0.44.0";
2912
2912
 
2913
2913
  export { type AISummary, APIError, type AnalystAction, type AnalystConsensus, type AnalystEarningsSurprise, type AnalystEstimate, type AnalystEstimatesResponse, type AssetMetadata, AuthenticationError, type CalendarMeta, type ChartData, type ChartDataPoint, type ClusterBuy, type CompanyKpisData, type CongressTrade, DeepHistoryUnavailableError, type Document, type DocumentSearchResponse, type DocumentSource, type EarningsCalendarResponse, type EarningsEvent, type EarningsKpiHighlight, type EarningsQuarter, type EarningsSource, type EtfAggregateCoverage, type EtfAnalystAggregate, type EtfAnalystContributor, type EtfHolding, type EtfHoldings, type EtfInfo, type EtfInsiderAggregate, type EtfInsiderContributor, type EtfScreenerExecuteResponse, type EtfScreenerRow, type EtfSentimentAggregate, type EtfSentimentReading, type FeaturedScreen, type FloatInfo, type Fundamentals, type FundamentalsPeriod, type FundamentalsPeriodsResponse, type GetAnalystActionsOptions, type GetAnalystMarketActivityOptions, type GetEarningsCalendarOptions, type GetEarningsSummariesOptions, type GetEtfInsiderAggregateOptions, type GetHoldersOptions, type GetInsiderOptions, type GetInsightsOptions, type GetLatestInsightsOptions, type GetPoliticianActivityOptions, type GetPoliticianDirectoryOptions, type GetPoliticianMemberOptions, type GetPoliticiansOptions, type GetRecentEarningsOptions, type GetStockInsightsRangeOptions, type GetUserInsightsOptions, type Holder, type HolderNotableChanges, type IndexConstituent, type IndexHistoryPoint, type IndexHistoryResponse, type IndexListResponse, type IndexListing, type IndexSnapshot, type InsiderActivityResponse, type InsiderActivitySummary, type InsiderTrade, type Insight, type InsightPreviewResponse, type InstitutionList, type InstitutionListResponse, type InstitutionSummary, type InstitutionalFlow, type InstitutionalFlows, type InstitutionalFlowsResponse, type KBEntity, type KpiCoverageEntry, type KpiCoverageResponse, type KpiDataPoint, type KpiSeries, type KpiTypeEntry, type ListInstitutionsOptions, type LockedInsight, type MarketMood, type MarketStatus, type MarketSummary, type MetricDistribution, type MetricDistributionOptions, type MetricType, type MetricsBreakdown, type MetricsOptions, NotFoundError, type OptionsAggregate, type OptionsContext, type OptionsOiWalls, type OptionsSummary, type OptionsUnusualContract, type OptionsWall, type PoliticianDetail, type PoliticianDirectory, type PoliticianDirectoryEntry, type PoliticianDirectoryResponse, type PoliticianSummary, type PreviewResponse, type Quarter, RateLimitError, type RecentEarningsEntry, type ScreenerExecuteOptions, type ScreenerExecuteResponse, type ScreenerFieldCatalog, type ScreenerFieldDescriptor, type ScreenerFieldOption, type ScreenerFilter, type ScreenerPlan, type ScreenerRow, type ScreenerScreensResponse, type ScreenerSort, SentiSense, SentiSenseError, type SentiSenseOptions, type SentimentEntry, type ServingMetric, type ShortInterest, type ShortVolume, type SimilarStock, type StockDetail, type StockEntity, type StockImage, type StockPrice, type StockProfile, type StockQuote, type Story, type StoryCluster, type TickerHolders, type TrackerEvent, type TrackerGeoEntry, type TrackerHeadlineMetric, type TrackerListResponse, type TrackerListing, type TrackerMetricValue, type TrackerSignal, type TrackerSnapshot, type TrackerSnapshotResponse, type TrackerSourceRef, type TrackerTableRow, type TrackerTimeSeriesPoint, type TtmFundamentals, VERSION, type WeightedConsensus, type WeightedNetFlow, SentiSense as default };
package/dist/index.d.ts CHANGED
@@ -2908,6 +2908,6 @@ declare class APIError extends SentiSenseError {
2908
2908
  constructor(message: string, status: number, code?: string);
2909
2909
  }
2910
2910
 
2911
- declare const VERSION = "0.43.0";
2911
+ declare const VERSION = "0.44.0";
2912
2912
 
2913
2913
  export { type AISummary, APIError, type AnalystAction, type AnalystConsensus, type AnalystEarningsSurprise, type AnalystEstimate, type AnalystEstimatesResponse, type AssetMetadata, AuthenticationError, type CalendarMeta, type ChartData, type ChartDataPoint, type ClusterBuy, type CompanyKpisData, type CongressTrade, DeepHistoryUnavailableError, type Document, type DocumentSearchResponse, type DocumentSource, type EarningsCalendarResponse, type EarningsEvent, type EarningsKpiHighlight, type EarningsQuarter, type EarningsSource, type EtfAggregateCoverage, type EtfAnalystAggregate, type EtfAnalystContributor, type EtfHolding, type EtfHoldings, type EtfInfo, type EtfInsiderAggregate, type EtfInsiderContributor, type EtfScreenerExecuteResponse, type EtfScreenerRow, type EtfSentimentAggregate, type EtfSentimentReading, type FeaturedScreen, type FloatInfo, type Fundamentals, type FundamentalsPeriod, type FundamentalsPeriodsResponse, type GetAnalystActionsOptions, type GetAnalystMarketActivityOptions, type GetEarningsCalendarOptions, type GetEarningsSummariesOptions, type GetEtfInsiderAggregateOptions, type GetHoldersOptions, type GetInsiderOptions, type GetInsightsOptions, type GetLatestInsightsOptions, type GetPoliticianActivityOptions, type GetPoliticianDirectoryOptions, type GetPoliticianMemberOptions, type GetPoliticiansOptions, type GetRecentEarningsOptions, type GetStockInsightsRangeOptions, type GetUserInsightsOptions, type Holder, type HolderNotableChanges, type IndexConstituent, type IndexHistoryPoint, type IndexHistoryResponse, type IndexListResponse, type IndexListing, type IndexSnapshot, type InsiderActivityResponse, type InsiderActivitySummary, type InsiderTrade, type Insight, type InsightPreviewResponse, type InstitutionList, type InstitutionListResponse, type InstitutionSummary, type InstitutionalFlow, type InstitutionalFlows, type InstitutionalFlowsResponse, type KBEntity, type KpiCoverageEntry, type KpiCoverageResponse, type KpiDataPoint, type KpiSeries, type KpiTypeEntry, type ListInstitutionsOptions, type LockedInsight, type MarketMood, type MarketStatus, type MarketSummary, type MetricDistribution, type MetricDistributionOptions, type MetricType, type MetricsBreakdown, type MetricsOptions, NotFoundError, type OptionsAggregate, type OptionsContext, type OptionsOiWalls, type OptionsSummary, type OptionsUnusualContract, type OptionsWall, type PoliticianDetail, type PoliticianDirectory, type PoliticianDirectoryEntry, type PoliticianDirectoryResponse, type PoliticianSummary, type PreviewResponse, type Quarter, RateLimitError, type RecentEarningsEntry, type ScreenerExecuteOptions, type ScreenerExecuteResponse, type ScreenerFieldCatalog, type ScreenerFieldDescriptor, type ScreenerFieldOption, type ScreenerFilter, type ScreenerPlan, type ScreenerRow, type ScreenerScreensResponse, type ScreenerSort, SentiSense, SentiSenseError, type SentiSenseOptions, type SentimentEntry, type ServingMetric, type ShortInterest, type ShortVolume, type SimilarStock, type StockDetail, type StockEntity, type StockImage, type StockPrice, type StockProfile, type StockQuote, type Story, type StoryCluster, type TickerHolders, type TrackerEvent, type TrackerGeoEntry, type TrackerHeadlineMetric, type TrackerListResponse, type TrackerListing, type TrackerMetricValue, type TrackerSignal, type TrackerSnapshot, type TrackerSnapshotResponse, type TrackerSourceRef, type TrackerTableRow, type TrackerTimeSeriesPoint, type TtmFundamentals, VERSION, type WeightedConsensus, type WeightedNetFlow, SentiSense as default };
package/dist/index.mjs CHANGED
@@ -1002,7 +1002,7 @@ var Trackers = class {
1002
1002
  };
1003
1003
 
1004
1004
  // src/version.ts
1005
- var VERSION = "0.43.0";
1005
+ var VERSION = "0.44.0";
1006
1006
 
1007
1007
  // src/client.ts
1008
1008
  var DEFAULT_BASE_URL = "https://app.sentisense.ai";
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/errors.ts","../src/resources/analyst.ts","../src/resources/calendar.ts","../src/resources/documents.ts","../src/resources/earnings.ts","../src/resources/entityMetrics.ts","../src/resources/etfs.ts","../src/resources/insider.ts","../src/resources/politicians.ts","../src/resources/insights.ts","../src/resources/institutional.ts","../src/resources/kb.ts","../src/resources/marketMood.ts","../src/resources/marketSummary.ts","../src/resources/screener.ts","../src/resources/stocks.ts","../src/resources/indexes.ts","../src/resources/trackers.ts","../src/version.ts","../src/client.ts"],"sourcesContent":["export class SentiSenseError extends Error {\n status?: number;\n code?: string;\n\n constructor(message: string, status?: number, code?: string) {\n super(message);\n this.name = \"SentiSenseError\";\n this.status = status;\n this.code = code;\n }\n}\n\nexport class AuthenticationError extends SentiSenseError {\n constructor(message: string, status: number, code?: string) {\n super(message, status, code);\n this.name = \"AuthenticationError\";\n }\n}\n\nexport class NotFoundError extends SentiSenseError {\n constructor(message: string, code?: string) {\n super(message, 404, code);\n this.name = \"NotFoundError\";\n }\n}\n\n/**\n * Thrown when a deep chart range is still being assembled.\n *\n * The API answers 202 for \"10Y\" and \"MAX\" the first time a rarely-requested stock is asked\n * for. It deliberately does not substitute a shorter range, so a successful response always\n * carries the timeframe you asked for. Retry after a few seconds.\n */\nexport class DeepHistoryUnavailableError extends SentiSenseError {\n retryAfter?: number;\n\n constructor(message: string, retryAfter?: number) {\n super(message, 202);\n this.name = \"DeepHistoryUnavailableError\";\n this.retryAfter = retryAfter;\n }\n}\n\nexport class RateLimitError extends SentiSenseError {\n /**\n * Seconds to wait before retrying, from the server's `Retry-After` header, clamped to\n * `[0.5, 120]`. Always either a finite number or `undefined`: an absent header, or one\n * carrying an HTTP-date instead of a number of seconds, leaves it undefined rather than\n * `NaN`, so `setTimeout(fn, err.retryAfter * 1000)` can never fire immediately.\n */\n retryAfter?: number;\n\n constructor(message: string, code?: string, retryAfter?: number) {\n super(message, 429, code);\n this.name = \"RateLimitError\";\n this.retryAfter = retryAfter;\n }\n}\n\nexport class APIError extends SentiSenseError {\n constructor(message: string, status: number, code?: string) {\n super(message, status, code);\n this.name = \"APIError\";\n }\n}\n","import type { APIClient } from \"../client.js\";\nimport type { PreviewResponse } from \"../types.js\";\n\nexport interface AnalystConsensus {\n ticker: string;\n currentPrice: number | null;\n targetLow: number | null;\n targetMean: number | null;\n targetHigh: number | null;\n targetMedian: number | null;\n numberOfAnalysts: number;\n upsidePercent: number | null;\n consensusLabel: string | null;\n recommendationMean: number | null;\n /** PRO-only; zero in the free preview. */\n strongBuy: number;\n /** PRO-only; zero in the free preview. */\n buy: number;\n /** PRO-only; zero in the free preview. */\n hold: number;\n /** PRO-only; zero in the free preview. */\n sell: number;\n /** PRO-only; zero in the free preview. */\n strongSell: number;\n updatedAt: string | null;\n}\n\nexport interface AnalystAction {\n ticker: string;\n actionDate: string;\n firm: string;\n /** UPGRADE, DOWNGRADE, INITIATE, REITERATE, OTHER */\n actionType: string;\n fromGrade: string | null;\n toGrade: string | null;\n}\n\nexport interface AnalystEstimate {\n /** Fiscal period descriptor (provider-specific shape). */\n [key: string]: unknown;\n}\n\nexport interface AnalystEarningsSurprise {\n /** Past report descriptor (provider-specific shape). */\n [key: string]: unknown;\n}\n\nexport interface AnalystEstimatesResponse {\n estimates: AnalystEstimate[];\n surprises: AnalystEarningsSurprise[];\n}\n\nexport interface GetAnalystActionsOptions {\n /** Days of history to return. Default 90. */\n lookbackDays?: number;\n}\n\nexport interface GetAnalystMarketActivityOptions {\n /** Days of history to return. Default 30. */\n lookbackDays?: number;\n}\n\n/**\n * Wall Street analyst coverage: aggregate price targets, recommendation distribution,\n * recent upgrade/downgrade actions, and forward EPS estimates with earnings surprise history.\n *\n * Free users receive the price target band (low/mean/high + analyst count + consensus label)\n * in full -- it powers the public projection cone. The buy/hold/sell distribution counts\n * and full action/estimate history are PRO-only.\n */\nexport class Analyst {\n constructor(private client: APIClient) {}\n\n /**\n * Get the aggregate Wall Street consensus for a ticker. Returns 404 if no\n * coverage exists.\n */\n async consensus(\n ticker: string,\n ): Promise<PreviewResponse<AnalystConsensus>> {\n return this.client.get(\n `/api/v1/analyst/${encodeURIComponent(ticker.toUpperCase())}/consensus`,\n );\n }\n\n /**\n * Get recent analyst upgrade/downgrade actions for a ticker, newest first.\n * Free users receive the 3 most recent.\n */\n async actions(\n ticker: string,\n options?: GetAnalystActionsOptions,\n ): Promise<PreviewResponse<AnalystAction[]>> {\n return this.client.get(\n `/api/v1/analyst/${encodeURIComponent(ticker.toUpperCase())}/actions`,\n options,\n );\n }\n\n /**\n * Get forward EPS estimates and earnings surprise history for a ticker.\n * Free users receive 1 estimate (current quarter) plus the 2 most recent surprises.\n */\n async estimates(\n ticker: string,\n ): Promise<PreviewResponse<AnalystEstimatesResponse>> {\n return this.client.get(\n `/api/v1/analyst/${encodeURIComponent(ticker.toUpperCase())}/estimates`,\n );\n }\n\n /**\n * Get market-wide recent analyst actions across all covered tickers, newest first.\n * Free users receive the 5 most recent.\n */\n async marketActivity(\n options?: GetAnalystMarketActivityOptions,\n ): Promise<PreviewResponse<AnalystAction[]>> {\n return this.client.get(\"/api/v1/analyst/activity\", options);\n }\n}\n","import type { APIClient } from \"../client.js\";\nimport type {\n EarningsCalendarResponse,\n GetEarningsCalendarOptions,\n PreviewResponse,\n} from \"../types.js\";\n\nexport class Calendar {\n constructor(private client: APIClient) {}\n\n /**\n * Upcoming company earnings, sorted by date.\n *\n * Key-required. A FREE key returns the current week (`isPreview: true`); a PRO\n * key returns the full forward window (about 30 days). Field richness is\n * identical across tiers: the gate is how far ahead you can see, not which\n * columns you get. On a preview, `totalCount` is the full-window event count.\n */\n async getEarnings(\n options?: GetEarningsCalendarOptions,\n ): Promise<PreviewResponse<EarningsCalendarResponse>> {\n return this.client.get(\"/api/v1/calendar/earnings\", options);\n }\n}\n","import type { APIClient } from \"../client.js\";\nimport type {\n DocumentSearchResponse,\n DocumentSource,\n GetByEntityOptions,\n GetBySourceOptions,\n GetByTickerOptions,\n GetByTickerRangeOptions,\n GetStoriesByTickerOptions,\n GetStoriesOptions,\n SearchDocumentsOptions,\n Story,\n} from \"../types.js\";\n\nexport class Documents {\n constructor(private client: APIClient) {}\n\n /** Get document metrics for a stock. The rows are in `documents`. */\n async getByTicker(ticker: string, options?: GetByTickerOptions): Promise<DocumentSearchResponse> {\n return this.client.get(`/api/v1/documents/ticker/${encodeURIComponent(ticker)}`, options);\n }\n\n /** Get document metrics for a stock within a date range. The rows are in `documents`. */\n async getByTickerRange(ticker: string, options: GetByTickerRangeOptions): Promise<DocumentSearchResponse> {\n return this.client.get(\n `/api/v1/documents/ticker/${encodeURIComponent(ticker)}/range`,\n options,\n );\n }\n\n /** Get document metrics for a KB entity. The rows are in `documents`. */\n async getByEntity(entityId: string, options?: GetByEntityOptions): Promise<DocumentSearchResponse> {\n return this.client.get(\n `/api/v1/documents/entity/${encodeURIComponent(entityId)}`,\n options,\n );\n }\n\n /** Smart search with natural language query parsing. The rows are in `documents`. */\n async search(query: string, options?: SearchDocumentsOptions): Promise<DocumentSearchResponse> {\n return this.client.get(\"/api/v1/documents/search\", { query, ...options });\n }\n\n /** Get latest document metrics from a source type. The rows are in `documents`. */\n async getBySource(source: DocumentSource, options?: GetBySourceOptions): Promise<DocumentSearchResponse> {\n return this.client.get(\n `/api/v1/documents/source/${encodeURIComponent(source)}`,\n options,\n );\n }\n\n /** Get AI-curated news story clusters. */\n async getStories(options?: GetStoriesOptions): Promise<Story[]> {\n return this.client.get(\"/api/v1/documents/stories\", options);\n }\n\n /** Get full story detail by cluster ID. */\n async getStoryDetail(clusterId: string): Promise<unknown> {\n return this.client.get(`/api/v1/documents/stories/${encodeURIComponent(clusterId)}`);\n }\n\n /** Get stories for a specific stock. */\n async getStoriesByTicker(\n ticker: string,\n options?: GetStoriesByTickerOptions,\n ): Promise<Story[]> {\n return this.client.get(\n `/api/v1/documents/stories/ticker/${encodeURIComponent(ticker)}`,\n options,\n );\n }\n\n}\n","import type { APIClient } from \"../client.js\";\nimport type {\n EarningsQuarter,\n GetEarningsSummariesOptions,\n GetRecentEarningsOptions,\n PreviewResponse,\n RecentEarningsEntry,\n} from \"../types.js\";\n\n/**\n * Earnings: what a company actually reported, after the fact.\n *\n * A quarter's results arrive as a press release, a filing, and a call, none of\n * which is a data structure. {@link getSummaries} is the assembled version, one\n * object per fiscal quarter, and {@link getRecent} is the cross-ticker view of\n * who reported lately. Pair them to drive a post-earnings sweep: list the\n * window, then pull each ticker's analysis report.\n *\n * The forward-looking half of the family lives on `client.calendar.getEarnings()`,\n * which covers scheduled dates and consensus EPS rather than results.\n *\n * @see EarningsQuarter\n */\nexport class Earnings {\n constructor(private client: APIClient) {}\n\n /**\n * Per-quarter earnings analysis report for one ticker, newest first.\n *\n * Each quarter carries the editorial headline, the KPI cards that matter for\n * that company with year-over-year deltas, the guidance language as\n * management phrased it, and a summary of the earnings call.\n *\n * Branch on `isPreview`: a PRO key receives every hydrated quarter in full, a\n * FREE key receives the latest quarter shaped rather than truncated, plus\n * `totalCount`. {@link EarningsQuarter} documents which fields each tier\n * carries.\n *\n * A quarter typically appears within 48 hours of the company reporting, and\n * the call summary can arrive after the press-release content for the same\n * quarter, so read `generatedAt` and `transcriptGeneratedAt` rather than\n * assuming a fixed lag. A ticker with no stored quarter answers with an empty\n * `data` array, not a 404.\n *\n * Use canonical ticker symbols: `GOOGL` (not `GOOG`), `BRK.B` (not `BRK-B`).\n */\n async getSummaries(\n ticker: string,\n options?: GetEarningsSummariesOptions,\n ): Promise<PreviewResponse<EarningsQuarter[]>> {\n return this.client.get(\n `/api/v1/stocks/${encodeURIComponent(ticker.toUpperCase())}/earnings-summaries`,\n options,\n );\n }\n\n /**\n * Which covered companies reported on or after `today - days`, newest first.\n *\n * Every API key receives the full window it asks for, so `isPreview` is\n * always `false` here. The window is bounded by `reportDate`, so a quarter\n * reported inside it appears even when its call summary lands later, and an\n * empty `data` array means nobody in the covered set reported in that window.\n *\n * This is the backward-looking feed; `client.calendar.getEarnings()` is the\n * forward-looking one.\n */\n async getRecent(\n options?: GetRecentEarningsOptions,\n ): Promise<PreviewResponse<RecentEarningsEntry[]>> {\n return this.client.get(\"/api/v1/earnings/recent\", options);\n }\n}\n","import type { APIClient } from \"../client.js\";\nimport type {\n MetricType,\n MetricsOptions,\n MetricDistributionOptions,\n ServingMetric,\n MetricDistribution,\n} from \"../types.js\";\n\nexport class EntityMetrics {\n constructor(private client: APIClient) {}\n\n /**\n * Get time-series metric data for an entity using the v2 Serving Metrics API.\n *\n * @param symbol Ticker symbol (e.g. \"AAPL\") or entity urlSlug (e.g. \"Nancy-Pelosi\",\n * case-insensitive; discover slugs via stocks.getEntities()).\n * @param options Metric type and optional time range / resolution.\n */\n async getMetrics(\n symbol: string,\n options: MetricsOptions = {},\n ): Promise<ServingMetric[]> {\n const { metricType = \"sentiment\", startTime, endTime, maxDataPoints } = options;\n return this.client.get(\n `/api/v2/metrics/entity/${encodeURIComponent(symbol)}/metric/${encodeURIComponent(metricType)}`,\n {\n ...(startTime !== undefined && { startTime }),\n ...(endTime !== undefined && { endTime }),\n ...(maxDataPoints !== undefined && { maxDataPoints }),\n },\n );\n }\n\n /**\n * Get distribution data for a metric, broken down by a dimension (default: source).\n *\n * @param symbol Ticker symbol (e.g. \"AAPL\") or entity urlSlug.\n * @param metricType The metric to break down (e.g. \"mentions\", \"sentiment\").\n * @param options Optional dimension parameter.\n */\n async getDistribution(\n symbol: string,\n metricType: MetricType,\n options: MetricDistributionOptions = {},\n ): Promise<MetricDistribution> {\n const { dimension = \"source\" } = options;\n return this.client.get(\n `/api/v2/metrics/entity/${encodeURIComponent(symbol)}/distribution/${encodeURIComponent(metricType)}`,\n { dimension },\n );\n }\n}\n","import type { APIClient } from \"../client.js\";\nimport type { PreviewResponse } from \"../types.js\";\n\nexport interface EtfInfo {\n ticker: string;\n name: string;\n kbEntityId: string | null;\n urlSlug: string | null;\n issuer: string | null;\n trackedIndex: string | null;\n assetClass: string | null;\n}\n\nexport interface EtfHolding {\n ticker: string;\n name: string | null;\n /** Weight in the fund as a percentage (0-100). */\n weightPct: number;\n /** ISO date \"YYYY-MM-DD\". First date this holding appeared in the composition. */\n firstSeen: string | null;\n}\n\nexport interface EtfHoldings {\n ticker: string;\n issuer: string;\n issuerEndpoint: string | null;\n /** ISO date \"YYYY-MM-DD\". Composition snapshot date from the issuer. */\n asOfDate: string;\n /** Epoch seconds when SentiSense refreshed the composition. */\n fetchedAt: number | null;\n /** ISO date \"YYYY-MM-DD\". When the composition is scheduled to be refreshed next. */\n nextRefreshDue: string;\n totalHoldings: number;\n holdings: EtfHolding[];\n /** True when this is a top-N view rather than the full fund. */\n partial?: boolean | null;\n /** Issuer's reported total holdings when `partial=true`. */\n totalKnownHoldings?: number | null;\n}\n\nexport interface EtfAggregateCoverage {\n holdingsCount: number;\n holdingsCovered: number;\n /** Sum of weights (0-100) for the covered holdings. */\n weightCovered: number;\n partial?: boolean | null;\n totalKnownHoldings?: number | null;\n}\n\nexport interface WeightedConsensus {\n upsidePercent: number | null;\n consensusLabel: string | null;\n /** Fractions of covered AUM in each bucket. Sums to ~1.0. */\n distribution: Record<string, number>;\n totalAnalysts: number;\n}\n\nexport interface EtfAnalystContributor {\n ticker: string;\n weightPct: number;\n upsidePercent: number | null;\n consensusLabel: string | null;\n /** Signed contribution to the fund's weighted upside in percentage points. */\n contributionPp: number;\n}\n\nexport interface EtfAnalystAggregate {\n ticker: string;\n /** ISO date \"YYYY-MM-DD\". Composition snapshot date. */\n asOfDate: string | null;\n /** Epoch seconds when this rollup was computed. */\n computedAt: number;\n coverage: EtfAggregateCoverage;\n weightedConsensus: WeightedConsensus;\n /** Top contributors (up to 10) by absolute contribution to the weighted upside. */\n topContributors: EtfAnalystContributor[];\n}\n\nexport interface WeightedNetFlow {\n /** Weighted net dollar flow (buys - sells). Negative = net selling. */\n netDollars: number;\n buyDollars: number;\n sellDollars: number;\n /** Unweighted; for context. */\n buyTradeCount: number;\n /** Unweighted; for context. */\n sellTradeCount: number;\n distinctInsiderCount: number;\n}\n\nexport interface EtfInsiderContributor {\n ticker: string;\n weightPct: number;\n /** Per-stock net flow over the window (signed). */\n netDollars: number;\n /** Signed contribution to the weighted headline. */\n weightedNetDollars: number;\n tradeCount: number;\n}\n\nexport interface EtfInsiderAggregate {\n ticker: string;\n /** ISO date \"YYYY-MM-DD\". Composition snapshot date. */\n asOfDate: string | null;\n /** Epoch seconds when this rollup was computed. */\n computedAt: number;\n lookbackDays: number;\n coverage: EtfAggregateCoverage;\n weightedNetFlow: WeightedNetFlow;\n /** Top contributors (up to 10) by absolute weighted-net-dollar contribution. */\n topContributors: EtfInsiderContributor[];\n}\n\nexport interface EtfSentimentReading {\n sentiSenseScore: number | null;\n /** BULLISH / NEUTRAL / BEARISH. */\n scoreLabel: string;\n /** Epoch seconds when the underlying metric was produced. */\n asOfTimestamp: number | null;\n}\n\nexport interface EtfSentimentAggregate {\n ticker: string;\n /** ISO date \"YYYY-MM-DD\". Composition snapshot date. */\n asOfDate: string | null;\n /** Epoch seconds when this aggregate was assembled. */\n computedAt: number;\n coverage: EtfAggregateCoverage;\n /** Holdings-weighted SentiSense across the fund's constituents. */\n constituentsWeighted: EtfSentimentReading;\n /** Direct reading from mentions of the fund's own ticker. Null for low-mention funds. */\n direct: EtfSentimentReading | null;\n}\n\nexport interface GetEtfInsiderAggregateOptions {\n /** Trailing window for the trade aggregation. Typical values: 30, 90. Default 30. */\n lookbackDays?: number;\n}\n\n/**\n * ETF discovery, composition (holdings), and holdings-weighted aggregate views.\n *\n * Funds aren't rated by analysts directly, don't have insiders of their own, and\n * may not get many direct news mentions -- but the companies inside them do. The\n * aggregate endpoints synthesize fund-level views from each constituent's per-stock\n * data, weighted by allocation, with a coverage block so consumers see how much of\n * the fund's AUM the underlying data covered.\n *\n * Beta as of 2026-05-15: starting with a limited set of widely-traded funds.\n */\nexport class Etfs {\n constructor(private client: APIClient) {}\n\n /**\n * List every ETF tracked by SentiSense, sorted by ticker.\n */\n async list(): Promise<EtfInfo[]> {\n return this.client.get(\"/api/v1/etfs\");\n }\n\n /**\n * Get the full holdings composition for an ETF, including per-holding weights\n * and freshness metadata. Returns 404 for unknown ETFs or commodity-only funds.\n */\n async holdings(ticker: string): Promise<EtfHoldings> {\n return this.client.get(\n `/api/v1/etfs/${encodeURIComponent(ticker.toUpperCase())}/holdings`,\n );\n }\n\n /**\n * Get the holdings-weighted analyst consensus for an ETF, including the\n * top per-holding contributors that drive the weighted upside.\n */\n async analystAggregate(\n ticker: string,\n ): Promise<PreviewResponse<EtfAnalystAggregate>> {\n return this.client.get(\n `/api/v1/etfs/${encodeURIComponent(ticker.toUpperCase())}/aggregates/analyst`,\n );\n }\n\n /**\n * Get the holdings-weighted SEC Form 4 insider aggregate for an ETF over a\n * configurable trailing window, including per-holding `topContributors` with\n * signed contribution to the weighted headline.\n */\n async insiderAggregate(\n ticker: string,\n options?: GetEtfInsiderAggregateOptions,\n ): Promise<PreviewResponse<EtfInsiderAggregate>> {\n return this.client.get(\n `/api/v1/etfs/${encodeURIComponent(ticker.toUpperCase())}/aggregates/insider`,\n options,\n );\n }\n\n /**\n * Get two SentiSense Score readings side-by-side: `constituentsWeighted`\n * (precomputed daily weighted average across the fund's holdings) and `direct`\n * (score from mentions of the fund's own ticker). The two can diverge, and the\n * gap is itself information.\n */\n async sentimentAggregate(\n ticker: string,\n ): Promise<PreviewResponse<EtfSentimentAggregate>> {\n return this.client.get(\n `/api/v1/etfs/${encodeURIComponent(ticker.toUpperCase())}/aggregates/sentiment`,\n );\n }\n}\n","import type { APIClient } from \"../client.js\";\nimport type {\n InsiderActivityResponse,\n InsiderTrade,\n ClusterBuy,\n GetInsiderOptions,\n PreviewResponse,\n} from \"../types.js\";\n\nexport class Insider {\n constructor(private client: APIClient) {}\n\n /**\n * Get market-wide insider activity: top buys and sells aggregated by ticker.\n *\n * PRO-gated. Free-tier users receive a preview (top 5 per direction)\n * with `isPreview: true` in the response.\n */\n async getActivity(options?: GetInsiderOptions): Promise<PreviewResponse<InsiderActivityResponse>> {\n return this.client.get(\"/api/v1/insider/activity\", options);\n }\n\n /**\n * Get individual insider transactions for a specific stock.\n *\n * PRO-gated. Free users receive a preview of the top 5 transactions.\n */\n async getTrades(ticker: string, options?: GetInsiderOptions): Promise<PreviewResponse<InsiderTrade[]>> {\n return this.client.get(\n `/api/v1/insider/trades/${encodeURIComponent(ticker.toUpperCase())}`,\n options,\n );\n }\n\n /**\n * Get cluster buy signals: stocks where 3+ distinct insiders bought recently.\n *\n * PRO-gated. Free users receive a preview of the top 3 signals.\n */\n async getClusterBuys(options?: GetInsiderOptions): Promise<PreviewResponse<ClusterBuy[]>> {\n return this.client.get(\"/api/v1/insider/cluster-buys\", options);\n }\n}\n","import type { APIClient } from \"../client.js\";\nimport type {\n CongressTrade,\n PoliticianSummary,\n PoliticianDetail,\n GetPoliticianActivityOptions,\n GetPoliticiansOptions,\n GetPoliticianDirectoryOptions,\n GetPoliticianMemberOptions,\n PoliticianDirectory,\n PoliticianDirectoryResponse,\n PreviewResponse,\n} from \"../types.js\";\n\nexport class Politicians {\n constructor(private client: APIClient) {}\n\n /**\n * Get recent congressional STOCK Act trading activity across all politicians.\n *\n * PRO-gated. Free-tier users receive a preview (top 5 trades)\n * with `isPreview: true` in the response.\n *\n * The feed is longer than one response: a default 90-day window is routinely well over a\n * thousand disclosures, and without `limit` the server sends the first 200 with no marker\n * that it stopped. `totalCount` on the envelope is the real size on every tier, so page\n * with `limit` and `offset` rather than reading `data.length` as the total.\n *\n * ```typescript\n * const first = await client.politicians.getActivity({ limit: 100 });\n * for (let offset = 100; offset < first.totalCount!; offset += 100) {\n * const page = await client.politicians.getActivity({ limit: 100, offset });\n * // ... page.data\n * }\n * ```\n */\n async getActivity(\n options?: GetPoliticianActivityOptions,\n ): Promise<PreviewResponse<CongressTrade[]>> {\n return this.client.get(\"/api/v1/politicians/activity\", options);\n }\n\n /**\n * Get congressional trades for a specific stock.\n *\n * PRO-gated. Free users receive a preview of the top 3 trades.\n */\n async getFilings(\n ticker: string,\n options?: GetPoliticiansOptions,\n ): Promise<PreviewResponse<CongressTrade[]>> {\n return this.client.get(\n `/api/v1/politicians/filings/${encodeURIComponent(ticker.toUpperCase())}`,\n options,\n );\n }\n\n /**\n * Discover tracked members of Congress and the page slug identifying each, so you\n * can find who to query without knowing slugs upfront.\n *\n * Summary only, no trade data; use `getMember` for a member's filings.\n *\n * Unlike `getMembers`, this includes members who have **left Congress**, carrying\n * `former` and `servedUntil`. That roster lists who currently holds office, so a\n * former member is otherwise reachable only if you already know their slug.\n *\n * Requires an API key but does not consume monthly quota (per-minute rate limits\n * still apply), and is not tier-gated. Returns the unwrapped list payload.\n */\n async getDirectory(\n options?: GetPoliticianDirectoryOptions,\n ): Promise<PoliticianDirectory> {\n const resp = await this.client.get<PoliticianDirectoryResponse>(\n \"/api/v1/politicians/directory\",\n { ...options },\n );\n return resp.data;\n }\n\n /**\n * Get all tracked politicians with trading summary statistics.\n *\n * PRO-gated. Free users receive a preview of the top 5 members.\n *\n * Serves only members currently in office. Use `getDirectory` to enumerate\n * everyone tracked, former members included.\n */\n async getMembers(): Promise<PreviewResponse<PoliticianSummary[]>> {\n return this.client.get(\"/api/v1/politicians/members\");\n }\n\n /**\n * Get detailed profile for a single politician: summary, recent trades, top tickers.\n *\n * PRO-gated. Free users receive a preview-wrapped response.\n *\n * `data.recentTrades` is one page of the member's history, not all of it. Most members\n * have a few dozen disclosures and arrive complete in the default page; a handful have\n * thousands. `totalCount` on the envelope is the size of the whole history on every\n * tier, so page with `limit` and `offset` rather than reading `recentTrades.length` as\n * the total. `data.profile` and `data.topTickers` describe the whole history whatever\n * page you ask for, so `profile.totalTrades` does not shrink with a small `limit`.\n *\n * ```typescript\n * const first = await client.politicians.getMember(\"Ro-Khanna\", { limit: 500 });\n * for (let offset = 500; offset < first.totalCount!; offset += 500) {\n * const page = await client.politicians.getMember(\"Ro-Khanna\", { limit: 500, offset });\n * // ... page.data.recentTrades\n * }\n * ```\n */\n async getMember(\n slug: string,\n options?: GetPoliticianMemberOptions,\n ): Promise<PreviewResponse<PoliticianDetail>> {\n return this.client.get(\n `/api/v1/politicians/member/${encodeURIComponent(slug)}`,\n options,\n );\n }\n}\n","import type { APIClient } from \"../client.js\";\nimport type {\n Insight,\n GetInsightsOptions,\n PreviewResponse,\n} from \"../types.js\";\n\nexport interface GetStockInsightsRangeOptions {\n startDate: string;\n endDate: string;\n urgency?: \"low\" | \"medium\" | \"high\";\n insightType?: string;\n}\n\nexport interface GetLatestInsightsOptions {\n limit?: number;\n urgency?: \"low\" | \"medium\" | \"high\";\n}\n\nexport interface GetUserInsightsOptions {\n limit?: number;\n category?: string;\n}\n\nexport class Insights {\n constructor(private client: APIClient) {}\n\n /**\n * Get AI-generated insights for a specific stock, sorted by urgency then confidence.\n *\n * Returns the preview envelope: read the insights as `.data`. PRO callers get the\n * full list with `isPreview: false`; free callers get the top 3 with `isPreview: true`\n * and `totalCount` carrying the untruncated size.\n */\n async stock(\n ticker: string,\n options?: GetInsightsOptions,\n ): Promise<PreviewResponse<Insight[]>> {\n return this.client.get(\n `/api/v1/insights/stock/${encodeURIComponent(ticker.toUpperCase())}`,\n options,\n );\n }\n\n /**\n * Get AI insights for a stock within a date range.\n *\n * Returns the preview envelope: read the insights as `.data`. Free callers receive\n * the top 3, PRO callers the full list. The server returns 400 if `startDate` is\n * after `endDate`.\n */\n async stockRange(\n ticker: string,\n options: GetStockInsightsRangeOptions,\n ): Promise<PreviewResponse<Insight[]>> {\n return this.client.get(\n `/api/v1/insights/stock/${encodeURIComponent(ticker.toUpperCase())}/range`,\n options,\n );\n }\n\n /**\n * Get AI-generated market-level insights, sorted by urgency then confidence.\n *\n * Returns the preview envelope: read the insights as `.data`. PRO callers get the\n * full list with `isPreview: false`; free callers get the top 5 with `isPreview: true`\n * and `totalCount` carrying the untruncated size.\n */\n async market(): Promise<PreviewResponse<Insight[]>> {\n return this.client.get(\"/api/v1/insights/market\");\n }\n\n /**\n * Get the latest AI insights across all tracked stocks, newest first.\n *\n * Returns the preview envelope: read the insights as `.data`. Free callers receive\n * the top 5, PRO callers up to `limit` (clamped to 1-200).\n */\n async latest(\n options?: GetLatestInsightsOptions,\n ): Promise<PreviewResponse<Insight[]>> {\n return this.client.get(\"/api/v1/insights/latest\", options);\n }\n\n /**\n * Get personalized insights for the authenticated user.\n *\n * Biased toward the user's watchlist and portfolio when available; falls back\n * to market-level insights otherwise. API key authentication required.\n * Returns the preview envelope: read the insights as `.data`.\n */\n async user(\n options?: GetUserInsightsOptions,\n ): Promise<PreviewResponse<Insight[]>> {\n return this.client.get(\"/api/v1/insights/user\", options);\n }\n\n /**\n * Get available insight types for a specific stock.\n * API key required.\n *\n * Returns an array of insight type strings (e.g., `[\"sentiment_shift\", \"options_activity\"]`).\n */\n async types(ticker: string): Promise<string[]> {\n return this.client.get(\n `/api/v1/insights/stock/${encodeURIComponent(ticker.toUpperCase())}/types`,\n );\n }\n}\n","import type { APIClient } from \"../client.js\";\nimport type {\n GetFlowsOptions,\n GetHoldersOptions,\n Holder,\n InstitutionList,\n InstitutionListResponse,\n InstitutionalFlows,\n ListInstitutionsOptions,\n PreviewResponse,\n Quarter,\n TickerHolders,\n} from \"../types.js\";\n\nexport class Institutional {\n constructor(private client: APIClient) {}\n\n /** Get available 13F reporting quarters. */\n async getQuarters(): Promise<Quarter[]> {\n return this.client.get(\"/api/v1/institutional/quarters\");\n }\n\n /**\n * Get aggregate institutional activity per ticker for a quarter.\n *\n * `reportDate` is optional: omit it to get the latest available quarter, which may be\n * a still-open one holding only early filers. The response then carries `reportDate`\n * plus `isPending` and filer coverage counts so a partial quarter is clearly labeled.\n *\n * Returns the preview envelope, so the flows are one level down:\n * `const { data } = await client.institutional.getFlows(); data.inflows`.\n */\n async getFlows(\n reportDate?: string,\n options?: GetFlowsOptions,\n ): Promise<PreviewResponse<InstitutionalFlows>> {\n return this.client.get(\"/api/v1/institutional/flows\", {\n reportDate,\n ...options,\n });\n }\n\n /**\n * Get institutional holders for a specific stock.\n *\n * Returns the preview envelope wrapping a {@link TickerHolders} object, so the rows\n * are two levels down: `(await getHolders(t, d)).data.holders`, alongside ticker-level\n * totals like `holderCount`. Free callers get a truncated `holders` array with\n * `isPreview: true`.\n *\n * A widely held ticker returns thousands of rows: a megacap quarter is about\n * 6,000 holders and 1.5 MB. Pass `limit` unless you really want all of them.\n * Omitting `options` sends the original unbounded request.\n *\n * `limit` is the switch for the whole option set. With it, the response also carries\n * `returnedCount`, `offset`, and a `notableChanges` summary, so you can walk the list\n * without re-counting it. Without it, `offset` / `sortBy` / `sortDir` are ignored by the\n * server and you get the full unsorted list back with a 200.\n */\n async getHolders(\n ticker: string,\n reportDate: string,\n options?: GetHoldersOptions,\n ): Promise<PreviewResponse<TickerHolders>> {\n return this.client.get(\n `/api/v1/institutional/holders/${encodeURIComponent(ticker)}`,\n { reportDate, ...options },\n );\n }\n\n /**\n * Get activist investor positions (NEW or INCREASED).\n *\n * Returns the preview envelope, so read the rows as `.data`.\n */\n async getActivists(reportDate: string): Promise<PreviewResponse<Holder[]>> {\n return this.client.get(\"/api/v1/institutional/activist\", { reportDate });\n }\n\n /**\n * Discover institutions: a paginated, AUM-ranked list of filers (slug + metadata)\n * so you can find what to query without knowing slugs upfront.\n *\n * Each institution is rolled up by parent filer, so a multi-filer manager\n * (e.g. Vanguard) appears once with combined AUM. Summary only; use\n * `getInstitutionDetail` for a filer's full holdings.\n *\n * Requires an API key but does not consume monthly quota (per-minute rate\n * limits still apply). Returns the unwrapped list payload.\n */\n async listInstitutions(options?: ListInstitutionsOptions): Promise<InstitutionList> {\n const resp = await this.client.get<InstitutionListResponse>(\n \"/api/v1/institutional/institutions\",\n { ...options },\n );\n return resp.data;\n }\n\n /**\n * Get the full profile, summary stats, and current-quarter holdings for a\n * specific institutional filer.\n *\n * Resolved by URL slug (e.g. `Berkshire-Hathaway`) or numeric SEC CIK.\n * Free users receive the profile and top 10 holdings; PRO users receive the\n * full holdings array. Returns 404 if the slug or CIK is unknown.\n */\n async getInstitutionDetail(slugOrCik: string): Promise<unknown> {\n return this.client.get(\n `/api/v1/institutional/institution/${encodeURIComponent(slugOrCik)}`,\n );\n }\n}\n","import type { APIClient } from \"../client.js\";\nimport type { KBEntity } from \"../types.js\";\n\nexport class KB {\n constructor(private client: APIClient) {}\n\n /** Get popular entities for search suggestions. */\n async getPopularEntities(): Promise<KBEntity[]> {\n return this.client.get(\"/api/v1/kb/entities/popular\");\n }\n}\n","import type { APIClient } from \"../client.js\";\nimport type { MarketMood } from \"../types.js\";\n\nexport class MarketMoodResource {\n constructor(private client: APIClient) {}\n\n /** Get market mood data (scores, history, sectors). */\n async get(): Promise<MarketMood> {\n return this.client.get(\"/api/v2/market-mood\");\n }\n\n // TODO: accept a `days` param to control history length (the endpoint supports ?days=N).\n //\n // Market Mood is also reachable through `client.indexes`, which serves it in the shared\n // index envelope alongside fed-sentiment and ai-sentiment. Use this resource when you want\n // the phase band, weekly change, per-signal breakdown and per-sector map; use `indexes`\n // when you want every index to answer the same shape. Both report the same headline number.\n}\n","import type { APIClient } from \"../client.js\";\nimport type { MarketSummary } from \"../types.js\";\n\nexport class MarketSummaryResource {\n constructor(private client: APIClient) {}\n\n /** Get the AI-generated market summary with headline and analysis. */\n async get(): Promise<MarketSummary> {\n return this.client.get(\"/api/v1/market-summary\");\n }\n}\n","import type { APIClient } from \"../client.js\";\nimport type {\n EtfScreenerExecuteResponse,\n EtfScreenerRow,\n FeaturedScreen,\n ScreenerExecuteOptions,\n ScreenerExecuteResponse,\n ScreenerFieldCatalog,\n ScreenerFieldDescriptor,\n ScreenerFieldOption,\n ScreenerFilter,\n ScreenerPlan,\n ScreenerRow,\n ScreenerScreensResponse,\n ScreenerSort,\n} from \"../types.js\";\n\n/**\n * Screener: filter the tracked universe on the SentiSense Score, attention,\n * analyst consensus, technicals and price in a single query. It is the one\n * surface where our own signals sit in the same `WHERE` clause as the market\n * data, which is the point: screening on analyst ratings alone is something a\n * dozen free tools do, screening on analyst ratings *where the Score disagrees*\n * is not.\n *\n * Every screen is a {@link ScreenerPlan}. Take one from {@link screens} or\n * build your own, then hand it to {@link run} or {@link runEtfs}.\n *\n * Three field semantics are worth knowing before you write a filter, because\n * guessing them wrong produces a screen that looks fine and means nothing:\n *\n * - **`ANALYST_RATING_MEAN` is inverted.** It is the vendor's 1-to-5 scale\n * where `1.0` is strong buy, so bullish is `LTE 2.5`, not `GTE`. Prefer\n * `ANALYST_BUY_RATIO_PCT`, which runs the intuitive direction.\n * - **`MA_CROSS_STATE` is ordinal**, not a percentage: `1` golden cross (50-day\n * above 200-day), `-1` death cross, `0` neither. Use `EQ`.\n * - **`SENTIMENT_DIRECTION` is the sign of the 7-day SentiSense Score**\n * (`1` / `0` / `-1`) with a neutral band of plus-or-minus 5. Despite the name\n * it is not sentiment polarity, and `0` matches only an exact zero, so it\n * returns almost nothing.\n *\n * The Score fields (`SENTI_SCORE_7D`, `SENTI_SCORE_1M`, `SCORE_CHANGE_7D`) are\n * the SentiSense Score, not polarity: unbounded, banded at 5 / 13 / 23 either\n * side of zero. Filter on those band edges, not on values like `0.5`, which\n * behave as \"any positive score\".\n *\n * Nulls never match, in either direction: `RETURN_1Y >= 0` and `RETURN_1Y < 0`\n * do not partition the universe, because a stock listed four months ago is in\n * neither result. If a screen returns fewer rows than you expect, check\n * coverage before you check your thresholds.\n *\n * Screens read a snapshot that refreshes every 20 minutes, so this is not a\n * quote feed. Use `client.stocks.getQuote()` for live prices.\n */\nexport class Screener {\n constructor(private client: APIClient) {}\n\n /**\n * Every filterable field, with its unit, operators and description, for both\n * universes.\n *\n * Build a filter UI from this rather than hardcoding the list and you inherit\n * new fields as they ship. The ETF `STRING` fields (`ISSUER`, `ASSET_CLASS`,\n * `TRACKED_INDEX`) come back with their `values` populated from the live\n * universe, so pickers stay current without a redeploy.\n */\n async fields(): Promise<ScreenerFieldCatalog> {\n return this.client.get(\"/api/v1/screener/fields\");\n }\n\n /**\n * The curated screens shipped in the product, each with a runnable plan.\n *\n * Each `plan` round-trips straight into {@link run} (or {@link runEtfs} when\n * `plan.universe === \"ETF\"`) with nothing to rebuild.\n *\n * Their filters identify the field with `field` rather than `fieldName`.\n * Both keys are accepted on the way in, so read either when inspecting a plan\n * you did not build yourself.\n */\n async screens(): Promise<ScreenerScreensResponse> {\n return this.client.get(\"/api/v1/screener/screens\");\n }\n\n /**\n * Run a screen against the stock universe.\n *\n * `tickers` is optional: omit it to screen the whole tracked universe, pass a\n * list to screen a watchlist. `limit` sits next to the plan rather than\n * inside it, because a plan is a stored object and paging is a transport\n * concern; it defaults to 100 and caps at 500.\n *\n * Read `matched` before you read `results`: it is the count before `limit`\n * was applied, so a `matched` above your `limit` means you are holding the\n * top slice under the plan's sort, not the whole answer.\n *\n * @example\n * ```ts\n * const res = await client.screener.run({\n * plan: {\n * filters: [\n * { fieldName: \"SENTI_SCORE_7D\", op: \"GTE\", value: 13 },\n * { fieldName: \"ANALYST_BUY_RATIO_PCT\", op: \"LTE\", value: 30 },\n * { fieldName: \"ANALYST_COUNT\", op: \"GTE\", value: 5 },\n * ],\n * sort: { fieldName: \"SENTI_SCORE_7D\", dir: \"DESC\" },\n * },\n * limit: 25,\n * });\n * ```\n */\n async run(options: ScreenerExecuteOptions): Promise<ScreenerExecuteResponse> {\n return this.client.post(\"/api/v1/screener/execute\", options);\n }\n\n /**\n * Run a screen against the ETF universe.\n *\n * Same request shape as {@link run}, against a different field vocabulary:\n * take the ETF names from `fields().etf`. `IN` / `NOT_IN` take a `values`\n * array instead of `value` and are the operators for the string fields\n * (`ISSUER`, `ASSET_CLASS`, `TRACKED_INDEX`).\n *\n * `CONSTITUENTS_WEIGHTED_SENTISENSE` is the holdings-weighted SentiSense\n * Score across what the fund owns and is usually the one you want;\n * `DIRECT_SENTISENSE` is the Score from chatter about the fund ticker itself,\n * which on a broad index fund is mostly macro noise. `WEIGHT_COVERED_PCT`\n * tells you how much of the fund's weight had constituent data behind the\n * weighted number.\n */\n async runEtfs(options: ScreenerExecuteOptions): Promise<EtfScreenerExecuteResponse> {\n return this.client.post(\"/api/v1/screener/etfs/execute\", options);\n }\n}\n\n// Re-export for convenience so callers can `import type { ScreenerPlan }`\n// from the resource module instead of `../types`.\nexport type {\n EtfScreenerExecuteResponse,\n EtfScreenerRow,\n FeaturedScreen,\n ScreenerExecuteOptions,\n ScreenerExecuteResponse,\n ScreenerFieldCatalog,\n ScreenerFieldDescriptor,\n ScreenerFieldOption,\n ScreenerFilter,\n ScreenerPlan,\n ScreenerRow,\n ScreenerScreensResponse,\n ScreenerSort,\n};\n","import type { APIClient } from \"../client.js\";\nimport type {\n AISummary,\n ChartData,\n ChartDataPoint,\n CompanyKpisData,\n FloatInfo,\n Fundamentals,\n FundamentalsPeriodsResponse,\n TtmFundamentals,\n GetAISummaryOptions,\n GetChartOptions,\n GetDescriptionsOptions,\n GetFundamentalsOptions,\n GetImagesOptions,\n GetMetricsBreakdownOptions,\n GetProfileOptions,\n GetSimilarOptions,\n KpiCoverageResponse,\n KpiTypeEntry,\n MarketStatus,\n MetricsBreakdown,\n OptionsSummary,\n PreviewResponse,\n SimilarStock,\n ShortInterest,\n ShortVolume,\n StockDetail,\n StockEntity,\n StockSentiment,\n StockImage,\n StockPrice,\n StockProfile,\n StockQuote,\n} from \"../types.js\";\n\nexport class Stocks {\n constructor(private client: APIClient) {}\n\n /** List all available ticker symbols. */\n async list(): Promise<string[]> {\n return this.client.get(\"/api/v1/stocks\");\n }\n\n /** List all stocks with name, kbEntityId, urlSlug. */\n async listDetailed(): Promise<StockDetail[]> {\n return this.client.get(\"/api/v1/stocks/detailed\");\n }\n\n /** Get popular ticker symbols. */\n async listPopular(): Promise<string[]> {\n return this.client.get(\"/api/v1/stocks/popular\");\n }\n\n /** Get popular stocks with details. */\n async listPopularDetailed(): Promise<StockDetail[]> {\n return this.client.get(\"/api/v1/stocks/popular/detailed\");\n }\n\n /** Get real-time price for a single ticker. */\n async getPrice(ticker: string): Promise<StockPrice> {\n return this.client.get(\"/api/v1/stocks/price\", { ticker });\n }\n\n /**\n * Get aggregate quote snapshot: live price, today OHLC, 52-week range,\n * market cap, P/E, EPS TTM, and dividend yield in a single call.\n * All fields except `ticker` may be null when upstream data is unavailable.\n */\n async getQuote(ticker: string): Promise<StockQuote> {\n return this.client.get(`/api/v1/stocks/${encodeURIComponent(ticker)}/quote`);\n }\n\n /** Get real-time prices for multiple tickers. */\n async getPrices(tickers: string[]): Promise<StockPrice[]> {\n return this.client.get(\"/api/v1/stocks/prices\", {\n tickers: tickers.join(\",\"),\n });\n }\n\n /** Get batch company logo URLs. */\n async getImages(\n tickers: string[],\n options?: GetImagesOptions,\n ): Promise<Record<string, StockImage>> {\n return this.client.get(\"/api/v1/stocks/images\", {\n tickers: tickers.join(\",\"),\n ...options,\n });\n }\n\n /** Get company profiles with branding, market cap, sector. */\n async getDescriptions(\n tickers: string[],\n options?: GetDescriptionsOptions,\n ): Promise<Record<string, StockProfile>> {\n return this.client.get(\"/api/v1/stocks/descriptions\", {\n tickers: tickers.join(\",\"),\n ...options,\n });\n }\n\n /** Get peer/similar stocks. */\n async getSimilar(ticker: string, options?: GetSimilarOptions): Promise<SimilarStock[]> {\n return this.client.get(`/api/v1/stocks/${encodeURIComponent(ticker)}/similar`, options);\n }\n\n /** Get company profile (CEO, sector, industry, market data). */\n async getProfile(ticker: string, options?: GetProfileOptions): Promise<StockProfile> {\n return this.client.get(`/api/v1/stocks/${encodeURIComponent(ticker)}/profile`, options);\n }\n\n /**\n * Get the headline sentiment picture for a stock in one call.\n *\n * Returns the SentiSense Score with its 30-day regime, mention volume and social\n * dominance, per-source tone in `bySource`, plus related tickers, story drivers, a\n * narrative and an FAQ. Available in full on every API-key tier.\n *\n * Use `entityMetrics.getMetrics(ticker, \"sentiment\", ...)` instead when you need a time\n * series over a specific window rather than the headline read. Returns 404 for tickers\n * with no sentiment coverage.\n */\n async getSentiment(ticker: string): Promise<PreviewResponse<StockSentiment>> {\n return this.client.get(\n `/api/v1/stocks/${encodeURIComponent(ticker)}/sentiment`,\n );\n }\n\n /** Get related KB entities (people, products, partners). */\n async getEntities(ticker: string): Promise<StockEntity[]> {\n return this.client.get(`/api/v1/stocks/${encodeURIComponent(ticker)}/entities`);\n }\n\n /**\n * Get AI-generated stock analysis report. Requires PRO tier.\n *\n * `depth: \"deep\"` returns the full curated report and consumes one report view on\n * metered tiers; the default `\"basic\"` returns the one-paragraph summary.\n *\n * The deprecated `forceRefresh` option is accepted and discarded, not forwarded.\n */\n async getAISummary(ticker: string, options?: GetAISummaryOptions): Promise<AISummary> {\n const { forceRefresh: _forceRefresh, ...params } = options ?? {};\n return this.client.get(`/api/v1/stocks/${encodeURIComponent(ticker)}/ai-summary`, params);\n }\n\n /** Get sentiment/mention metrics breakdown by entity. */\n async getMetricsBreakdown(\n ticker: string,\n metricType: string,\n options?: GetMetricsBreakdownOptions,\n ): Promise<MetricsBreakdown> {\n return this.client.get(\n `/api/v1/stocks/${encodeURIComponent(ticker)}/metrics/${encodeURIComponent(metricType)}/breakdown`,\n options,\n );\n }\n\n /**\n * Get historical OHLCV chart data.\n *\n * The API returns a bare array of points; this normalizes it to\n * `{ ticker, timeframe, data }`. `timeframe` echoes the requested value\n * (defaulting to \"1M\", matching the server default when omitted).\n */\n async getChart(ticker: string, options?: GetChartOptions): Promise<ChartData> {\n const data = await this.client.get<ChartDataPoint[]>(\"/api/v1/stocks/chart\", {\n ticker,\n ...options,\n });\n return { ticker, timeframe: options?.timeframe ?? \"1M\", data };\n }\n\n /** Get current market open/closed/pre-market/after-hours status. */\n async getMarketStatus(): Promise<MarketStatus> {\n return this.client.get(\"/api/v1/stocks/market-status\");\n }\n\n /**\n * Get financial statement data for one reporting period: income statement, balance sheet,\n * and cash flow, including `capitalExpenditure` and `freeCashFlow`.\n *\n * Capital expenditure is signed as filed, so normally negative. See {@link Fundamentals}\n * for the free-cash-flow relationship and when it is `null`.\n */\n async getFundamentals(ticker: string, options?: GetFundamentalsOptions): Promise<Fundamentals> {\n return this.client.get(\"/api/v1/stocks/fundamentals\", { ticker, ...options });\n }\n\n /** Get available fiscal periods. The periods are in `periods`. */\n async getFundamentalsPeriods(ticker: string): Promise<FundamentalsPeriodsResponse> {\n return this.client.get(\"/api/v1/stocks/fundamentals/periods\", { ticker });\n }\n\n /**\n * Get the trailing-twelve-month fundamentals snapshot: TTM ratios, a different\n * shape from the per-period statement data `getFundamentals()` returns.\n */\n async getCurrentFundamentals(ticker: string): Promise<TtmFundamentals> {\n return this.client.get(\"/api/v1/stocks/fundamentals/current\", { ticker });\n }\n\n /** Get historical revenue data. */\n async getHistoricalRevenue(ticker: string): Promise<unknown> {\n return this.client.get(\"/api/v1/stocks/fundamentals/historical/revenue\", { ticker });\n }\n\n /** Get short interest metrics (FINRA). */\n async getShortInterest(ticker: string): Promise<ShortInterest> {\n return this.client.get(\"/api/v1/stocks/short-interest\", { ticker });\n }\n\n /** Get float information. */\n async getFloat(ticker: string): Promise<FloatInfo> {\n return this.client.get(\"/api/v1/stocks/float\", { ticker });\n }\n\n /** Get short volume trading data. */\n async getShortVolume(ticker: string): Promise<ShortVolume> {\n return this.client.get(\"/api/v1/stocks/short-volume\", { ticker });\n }\n\n /**\n * Get company-specific KPI time-series for a ticker. Returns curated GAAP and\n * non-GAAP metrics from earnings filings (e.g. iPhone unit sales, Tesla deliveries,\n * AWS revenue).\n *\n * Free users receive metadata only with an empty `kpis` list; PRO users receive\n * the full series. Returns 404 for tickers that do not yet have curated coverage.\n *\n * Coverage today: near-complete for the S&P 500 plus extended universe\n * (~500 tickers). Use `listKpiCoverage()` to enumerate.\n */\n async getKpis(ticker: string): Promise<PreviewResponse<CompanyKpisData>> {\n return this.client.get(\n `/api/v1/stocks/${encodeURIComponent(ticker.toUpperCase())}/kpis`,\n );\n }\n\n /**\n * List every ticker with curated KPI coverage. Returns `{count, tickers: [...]}`\n * with lightweight metadata (ticker, companyName, lastUpdated, kpiCount).\n * Sorted alphabetically by ticker.\n *\n * Auth: API key required, but the call does NOT consume your monthly quota\n * (rate-limit-per-minute still applies).\n */\n async listKpiCoverage(): Promise<KpiCoverageResponse> {\n return this.client.get(\"/api/v1/stocks/with-kpis\");\n }\n\n /**\n * List the KPI metadata tuples available for a ticker (`id, name, category,\n * chartType`) without paying the cost of the full series payload. Mirrors\n * the `/api/v1/insights/stock/{ticker}/types` precedent.\n *\n * Auth: API key required, no quota cost. 404 if the ticker has no curated KPIs.\n */\n async getKpiTypes(ticker: string): Promise<KpiTypeEntry[]> {\n return this.client.get(\n `/api/v1/stocks/${encodeURIComponent(ticker.toUpperCase())}/kpis/types`,\n );\n }\n\n /**\n * Get the end-of-day options dossier for one stock or ETF: the session's aggregate, its\n * percentile context, the open-interest wall structure with max pain, and the contracts\n * whose volume ran far ahead of their open interest.\n *\n * End of day, not live. `asOf` is the prior trading session and the data refreshes the\n * following morning, so this is positioning, not a quote feed.\n *\n * **`data` is `null` for a ticker outside the covered universe**, which is the most\n * actively optioned US names plus the tracked ETFs, and for a covered ticker with no\n * snapshot yet. An unknown symbol behaves the same way rather than answering 404, so treat\n * a null as \"no coverage\", never as an error. A covered ticker still building its baseline\n * returns its raw readings with the percentiles omitted.\n *\n * Percentiles compare a ticker to its own trailing history, never to another ticker, so an\n * ETF's readings are not comparable with a single stock's.\n *\n * Tiering: a PRO key always receives the full dossier. A FREE key receives it for the first\n * ten calls each calendar month and a headline-only preview after that, with `isPreview`\n * true; calls that return a null `data` never spend that allowance.\n */\n async getOptionsSummary(ticker: string): Promise<PreviewResponse<OptionsSummary | null>> {\n return this.client.get(\n `/api/v1/stocks/${encodeURIComponent(ticker.toUpperCase())}/options/summary`,\n );\n }\n}\n","import type { APIClient } from \"../client.js\";\nimport type {\n IndexConstituent,\n IndexHistoryPoint,\n IndexHistoryResponse,\n IndexListing,\n IndexListResponse,\n IndexSnapshot,\n} from \"../types.js\";\n\n/**\n * Indexes: composite scalars tracked over time, each blending its own inputs\n * into one number on a stated scale. Every index answers on the same envelope,\n * so you write one renderer and get every current and future SentiSense index.\n *\n * Two archetypes share that envelope. A **basket** index weight-averages\n * tracked entities and fills `constituents` / `basketSize` / `coverage` /\n * `totalMentions`; a **composite** index is built from signals instead and\n * returns `null` for all four by construction. See {@link IndexSnapshot}.\n *\n * @see IndexSnapshot\n */\nexport class Indexes {\n constructor(private client: APIClient) {}\n\n /**\n * List every index the platform publishes: id, display name, one-line\n * description, the scale it lives on, its access tier, and where its richest\n * view lives.\n *\n * Iterate this rather than hardcoding ids. Every `indexId` it advertises\n * resolves on {@link get} and {@link history}.\n */\n async list(): Promise<IndexListResponse> {\n return this.client.get(\"/api/v1/indexes\");\n }\n\n /**\n * Latest reading for one index.\n *\n * Check `constituents` for `null` before iterating: it is `null` on a\n * composite index like `market-mood`, which has no constituents by\n * construction. For Market Mood this is the narrowed view; the phase band,\n * weekly change, per-signal breakdown and per-sector map live on\n * `client.marketMood.get()`, and both report the same headline number.\n *\n * @param indexId slug from {@link list}, e.g. `\"fed-sentiment\"`.\n */\n async get(indexId: string): Promise<IndexSnapshot> {\n return this.client.get(`/api/v1/indexes/${indexId}`);\n }\n\n /**\n * Historical scalar series for one index, for charting.\n *\n * Thin or low-coverage buckets are withheld, so the series can be shorter\n * than `days` and can contain gaps. Plot against each point's `date`.\n *\n * @param indexId slug from {@link list}.\n * @param days days of history to return. Defaults to the API's own 180.\n */\n async history(indexId: string, days?: number): Promise<IndexHistoryResponse> {\n return this.client.get(\n `/api/v1/indexes/${indexId}/history`,\n days === undefined ? undefined : { days },\n );\n }\n}\n\n// Re-export for convenience so callers can `import type { IndexListing }`\n// from the resource module instead of `../types`.\nexport type {\n IndexConstituent,\n IndexHistoryPoint,\n IndexHistoryResponse,\n IndexListing,\n IndexListResponse,\n IndexSnapshot,\n};\n","import type { APIClient } from \"../client.js\";\nimport type {\n TrackerListing,\n TrackerListResponse,\n TrackerSnapshot,\n TrackerSnapshotResponse,\n} from \"../types.js\";\n\n/**\n * Trackers: observational data products published as a standardized\n * `TrackerSnapshot` envelope. Every tracker (institution rankings,\n * hedge-fund reported returns, social trackers, surveillance dashboards)\n * returns the same shape, so consumers write one renderer per `viewType` and\n * get every current and future SentiSense tracker for free.\n *\n * @see TrackerSnapshot\n */\nexport class Trackers {\n constructor(private client: APIClient) {}\n\n /**\n * List every publicly-visible tracker: id, display name, category,\n * one-line description, and the methodology anchor to link out to.\n */\n async list(): Promise<TrackerListResponse> {\n return this.client.get(\"/api/v1/trackers\");\n }\n\n /**\n * Standardized snapshot envelope for one tracker.\n *\n * Returns the envelope as-is: `{ isPreview, previewReason, totalCount?, data }`.\n * When `data.viewType === \"table\"` the rows live at `data.rows[]`; when\n * `\"choropleth\"` they live at `data.geo[]`; etc. Dispatch on `viewType`\n * in your renderer.\n *\n * @param trackerId slug from {@link list}, e.g. `\"institution-concentration\"`.\n * @param params provider-specific query params (e.g. `{ scope: \"us\" }` for\n * geographically-scoped trackers like hantavirus). Unknown keys are ignored.\n */\n async get(\n trackerId: string,\n params?: Record<string, string | number | boolean>,\n ): Promise<TrackerSnapshotResponse> {\n return this.client.get(`/api/v1/trackers/${trackerId}`, params);\n }\n}\n\n// Re-export for convenience so callers can `import type { TrackerListing }`\n// from the resource module instead of `../types`.\nexport type {\n TrackerListing,\n TrackerListResponse,\n TrackerSnapshot,\n TrackerSnapshotResponse,\n};\n","export const VERSION = \"0.43.0\";\n","import {\n APIError,\n AuthenticationError,\n DeepHistoryUnavailableError,\n NotFoundError,\n RateLimitError,\n SentiSenseError,\n} from \"./errors.js\";\nimport { Analyst } from \"./resources/analyst.js\";\nimport { Calendar } from \"./resources/calendar.js\";\nimport { Documents } from \"./resources/documents.js\";\nimport { Earnings } from \"./resources/earnings.js\";\nimport { EntityMetrics } from \"./resources/entityMetrics.js\";\nimport { Etfs } from \"./resources/etfs.js\";\nimport { Insider } from \"./resources/insider.js\";\nimport { Politicians } from \"./resources/politicians.js\";\nimport { Insights } from \"./resources/insights.js\";\nimport { Institutional } from \"./resources/institutional.js\";\nimport { KB } from \"./resources/kb.js\";\nimport { MarketMoodResource } from \"./resources/marketMood.js\";\nimport { MarketSummaryResource } from \"./resources/marketSummary.js\";\nimport { Screener } from \"./resources/screener.js\";\nimport { Stocks } from \"./resources/stocks.js\";\nimport { Indexes } from \"./resources/indexes.js\";\nimport { Trackers } from \"./resources/trackers.js\";\nimport type { SentiSenseOptions } from \"./types.js\";\nimport { VERSION } from \"./version.js\";\n\nconst DEFAULT_BASE_URL = \"https://app.sentisense.ai\";\nconst DEFAULT_TIMEOUT = 30_000;\nconst DEFAULT_MAX_RETRIES = 3;\nconst BASE_DELAY_MS = 1_000;\nconst MAX_DELAY_MS = 60_000;\n// Used when a 202 arrives without a usable Retry-After header.\nconst DEEP_HISTORY_FALLBACK_WAIT_S = 3;\n\n// Upper bounds on any server-supplied Retry-After. Rate limiting gets the longer ceiling\n// because a genuine limit window is legitimately minutes, while a deep-history warm-up is\n// seconds. Without a ceiling an oversized header value strands the caller indefinitely.\nconst MAX_DEEP_HISTORY_WAIT_S = 30;\nconst MAX_RATE_LIMIT_WAIT_S = 120;\nconst RATE_LIMIT_FALLBACK_WAIT_S = 60;\n\n/**\n * A `Retry-After` header as a usable number of seconds, clamped to `[0.5, maxWaitS]`, or\n * `undefined` when there is no usable value.\n *\n * `Retry-After` is vendor-controlled and may legally carry an HTTP-date rather than a\n * number of seconds, in which case parsing yields `NaN`. Left unguarded that produced a\n * `NaN` delay which compared false against every threshold and retried instantly in a busy\n * loop, and a `NaN` on the error object that silently broke a caller's own backoff.\n * Anything that is not a finite number is treated as absent.\n */\nfunction clampRetryAfter(\n raw: string | null,\n maxWaitS: number,\n): number | undefined {\n if (!raw) return undefined;\n const parsed = Number(raw);\n if (!Number.isFinite(parsed)) return undefined;\n return Math.min(Math.max(0.5, parsed), maxWaitS);\n}\n\n/** Same clamp, resolved to `defaultS` when the header gives us nothing to go on. */\nfunction retryAfterSeconds(\n raw: string | null,\n defaultS: number,\n maxWaitS: number,\n): number {\n return clampRetryAfter(raw, maxWaitS) ?? defaultS;\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/** @internal HTTP interface exposed to resource classes. */\nexport interface APIClient {\n get<T = unknown>(path: string, params?: object): Promise<T>;\n post<T = unknown>(path: string, body: unknown): Promise<T>;\n}\n\nexport class SentiSense implements APIClient {\n private baseUrl: string;\n private apiKey: string | undefined;\n private timeout: number;\n private maxRetries: number;\n private userAgent: string;\n\n readonly stocks: Stocks;\n readonly documents: Documents;\n readonly etfs: Etfs;\n readonly institutional: Institutional;\n readonly insider: Insider;\n readonly politicians: Politicians;\n readonly insights: Insights;\n readonly analyst: Analyst;\n readonly entityMetrics: EntityMetrics;\n readonly marketMood: MarketMoodResource;\n readonly marketSummary: MarketSummaryResource;\n readonly kb: KB;\n readonly indexes: Indexes;\n readonly trackers: Trackers;\n readonly calendar: Calendar;\n readonly earnings: Earnings;\n readonly screener: Screener;\n\n constructor(options: SentiSenseOptions = {}) {\n this.apiKey = options.apiKey;\n this.baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\\/+$/, \"\");\n this.timeout = options.timeout ?? DEFAULT_TIMEOUT;\n this.maxRetries = options.maxRetries ?? DEFAULT_MAX_RETRIES;\n // A header value cannot carry CR/LF, so collapse them rather than letting a caller's\n // string decide where the header block ends.\n const suffix = options.userAgentSuffix?.replace(/[\\r\\n]+/g, \" \").trim();\n this.userAgent = suffix\n ? `sentisense-node/${VERSION} ${suffix}`\n : `sentisense-node/${VERSION}`;\n\n this.stocks = new Stocks(this);\n this.documents = new Documents(this);\n this.etfs = new Etfs(this);\n this.institutional = new Institutional(this);\n this.insider = new Insider(this);\n this.politicians = new Politicians(this);\n this.insights = new Insights(this);\n this.analyst = new Analyst(this);\n this.entityMetrics = new EntityMetrics(this);\n this.marketMood = new MarketMoodResource(this);\n this.marketSummary = new MarketSummaryResource(this);\n this.kb = new KB(this);\n this.indexes = new Indexes(this);\n this.trackers = new Trackers(this);\n this.calendar = new Calendar(this);\n this.earnings = new Earnings(this);\n this.screener = new Screener(this);\n }\n\n /** @internal */\n async get<T = unknown>(path: string, params?: object): Promise<T> {\n const url = this.buildUrl(path, params);\n const headers: Record<string, string> = {\n \"Accept\": \"application/json\",\n };\n\n if (this.apiKey) {\n headers[\"X-SentiSense-API-Key\"] = this.apiKey;\n }\n\n // User-Agent is only set in Node.js (browsers disallow it)\n if (typeof process !== \"undefined\" && process.versions?.node) {\n headers[\"User-Agent\"] = this.userAgent;\n }\n\n let delayMs = 0;\n\n for (let attempt = 0; attempt <= this.maxRetries; attempt++) {\n if (delayMs > 0) {\n await sleep(delayMs);\n delayMs = 0;\n }\n\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await fetch(url, {\n method: \"GET\",\n headers,\n signal: controller.signal,\n });\n\n // 202 means a deep chart range is still being built server-side. It is a 2xx, so\n // without this it would fall through and return an empty array: the caller would\n // see \"no data\" rather than \"not ready yet\", which is the exact confusion the\n // status code exists to prevent. Retry honouring Retry-After, then surface it.\n if (response.status === 202) {\n const waitSeconds = retryAfterSeconds(\n response.headers.get(\"Retry-After\"),\n DEEP_HISTORY_FALLBACK_WAIT_S,\n MAX_DEEP_HISTORY_WAIT_S,\n );\n try { await response.body?.cancel(); } catch { /* ignore */ }\n if (attempt < this.maxRetries) {\n delayMs = waitSeconds * 1000;\n continue;\n }\n throw new DeepHistoryUnavailableError(\n \"Deep history is still being assembled. Retry in a few seconds.\",\n waitSeconds,\n );\n }\n\n if (!response.ok) {\n const isRetryable = response.status === 429 || response.status >= 500;\n if (isRetryable && attempt < this.maxRetries) {\n if (response.status === 429) {\n delayMs = retryAfterSeconds(\n response.headers.get(\"Retry-After\"),\n RATE_LIMIT_FALLBACK_WAIT_S,\n MAX_RATE_LIMIT_WAIT_S,\n ) * 1000;\n } else {\n delayMs = Math.min(BASE_DELAY_MS * Math.pow(2, attempt), MAX_DELAY_MS) + Math.random() * 1000;\n }\n try { await response.body?.cancel(); } catch { /* ignore */ }\n continue;\n }\n await this.handleErrorResponse(response);\n }\n\n return (await response.json()) as T;\n } catch (error) {\n if (error instanceof SentiSenseError) throw error;\n if (error instanceof Error && error.name === \"AbortError\") {\n throw new SentiSenseError(`Request timed out after ${this.timeout}ms`);\n }\n throw new SentiSenseError(\n error instanceof Error ? error.message : \"Unknown error\",\n );\n } finally {\n clearTimeout(timer);\n }\n }\n\n throw new SentiSenseError(\"All retries exhausted\");\n }\n\n /** @internal */\n async post<T = unknown>(path: string, body: unknown): Promise<T> {\n const url = this.buildUrl(path);\n const headers: Record<string, string> = {\n \"Accept\": \"application/json\",\n \"Content-Type\": \"application/json\",\n };\n\n if (this.apiKey) {\n headers[\"X-SentiSense-API-Key\"] = this.apiKey;\n }\n\n if (typeof process !== \"undefined\" && process.versions?.node) {\n headers[\"User-Agent\"] = this.userAgent;\n }\n\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await fetch(url, {\n method: \"POST\",\n headers,\n body: JSON.stringify(body),\n signal: controller.signal,\n });\n\n if (!response.ok) {\n await this.handleErrorResponse(response);\n }\n\n return (await response.json()) as T;\n } catch (error) {\n if (error instanceof SentiSenseError) throw error;\n if (error instanceof Error && error.name === \"AbortError\") {\n throw new SentiSenseError(`Request timed out after ${this.timeout}ms`);\n }\n throw new SentiSenseError(\n error instanceof Error ? error.message : \"Unknown error\",\n );\n } finally {\n clearTimeout(timer);\n }\n }\n\n private buildUrl(path: string, params?: object): string {\n const url = new URL(path, this.baseUrl);\n if (params) {\n for (const [key, value] of Object.entries(params as Record<string, unknown>)) {\n if (value !== undefined && value !== null) {\n url.searchParams.set(key, String(value));\n }\n }\n }\n return url.toString();\n }\n\n private async handleErrorResponse(response: Response): Promise<never> {\n let body: { error?: string; message?: string } = {};\n try {\n body = await response.json();\n } catch {\n // Response may not be JSON\n }\n\n const message = body.message ?? response.statusText ?? \"API request failed\";\n const code = body.error;\n\n switch (response.status) {\n case 401:\n case 403:\n throw new AuthenticationError(message, response.status, code);\n case 404:\n throw new NotFoundError(message, code);\n case 429: {\n // Same clamp the retry loop uses, so a caller running its own backoff off\n // `error.retryAfter` gets a number it can pass to setTimeout, or nothing at all.\n const retryAfter = clampRetryAfter(\n response.headers.get(\"Retry-After\"),\n MAX_RATE_LIMIT_WAIT_S,\n );\n throw new RateLimitError(message, code, retryAfter);\n }\n default:\n throw new APIError(message, response.status, code);\n }\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/errors.ts","../src/resources/analyst.ts","../src/resources/calendar.ts","../src/resources/documents.ts","../src/resources/earnings.ts","../src/resources/entityMetrics.ts","../src/resources/etfs.ts","../src/resources/insider.ts","../src/resources/politicians.ts","../src/resources/insights.ts","../src/resources/institutional.ts","../src/resources/kb.ts","../src/resources/marketMood.ts","../src/resources/marketSummary.ts","../src/resources/screener.ts","../src/resources/stocks.ts","../src/resources/indexes.ts","../src/resources/trackers.ts","../src/version.ts","../src/client.ts"],"sourcesContent":["export class SentiSenseError extends Error {\n status?: number;\n code?: string;\n\n constructor(message: string, status?: number, code?: string) {\n super(message);\n this.name = \"SentiSenseError\";\n this.status = status;\n this.code = code;\n }\n}\n\nexport class AuthenticationError extends SentiSenseError {\n constructor(message: string, status: number, code?: string) {\n super(message, status, code);\n this.name = \"AuthenticationError\";\n }\n}\n\nexport class NotFoundError extends SentiSenseError {\n constructor(message: string, code?: string) {\n super(message, 404, code);\n this.name = \"NotFoundError\";\n }\n}\n\n/**\n * Thrown when a deep chart range is still being assembled.\n *\n * The API answers 202 for \"10Y\" and \"MAX\" the first time a rarely-requested stock is asked\n * for. It deliberately does not substitute a shorter range, so a successful response always\n * carries the timeframe you asked for. Retry after a few seconds.\n */\nexport class DeepHistoryUnavailableError extends SentiSenseError {\n retryAfter?: number;\n\n constructor(message: string, retryAfter?: number) {\n super(message, 202);\n this.name = \"DeepHistoryUnavailableError\";\n this.retryAfter = retryAfter;\n }\n}\n\nexport class RateLimitError extends SentiSenseError {\n /**\n * Seconds to wait before retrying, from the server's `Retry-After` header, clamped to\n * `[0.5, 120]`. Always either a finite number or `undefined`: an absent header, or one\n * carrying an HTTP-date instead of a number of seconds, leaves it undefined rather than\n * `NaN`, so `setTimeout(fn, err.retryAfter * 1000)` can never fire immediately.\n */\n retryAfter?: number;\n\n constructor(message: string, code?: string, retryAfter?: number) {\n super(message, 429, code);\n this.name = \"RateLimitError\";\n this.retryAfter = retryAfter;\n }\n}\n\nexport class APIError extends SentiSenseError {\n constructor(message: string, status: number, code?: string) {\n super(message, status, code);\n this.name = \"APIError\";\n }\n}\n","import type { APIClient } from \"../client.js\";\nimport type { PreviewResponse } from \"../types.js\";\n\nexport interface AnalystConsensus {\n ticker: string;\n currentPrice: number | null;\n targetLow: number | null;\n targetMean: number | null;\n targetHigh: number | null;\n targetMedian: number | null;\n numberOfAnalysts: number;\n upsidePercent: number | null;\n consensusLabel: string | null;\n recommendationMean: number | null;\n /** PRO-only; zero in the free preview. */\n strongBuy: number;\n /** PRO-only; zero in the free preview. */\n buy: number;\n /** PRO-only; zero in the free preview. */\n hold: number;\n /** PRO-only; zero in the free preview. */\n sell: number;\n /** PRO-only; zero in the free preview. */\n strongSell: number;\n updatedAt: string | null;\n}\n\nexport interface AnalystAction {\n ticker: string;\n actionDate: string;\n firm: string;\n /** UPGRADE, DOWNGRADE, INITIATE, REITERATE, OTHER */\n actionType: string;\n fromGrade: string | null;\n toGrade: string | null;\n}\n\nexport interface AnalystEstimate {\n /** Fiscal period descriptor (provider-specific shape). */\n [key: string]: unknown;\n}\n\nexport interface AnalystEarningsSurprise {\n /** Past report descriptor (provider-specific shape). */\n [key: string]: unknown;\n}\n\nexport interface AnalystEstimatesResponse {\n estimates: AnalystEstimate[];\n surprises: AnalystEarningsSurprise[];\n}\n\nexport interface GetAnalystActionsOptions {\n /** Days of history to return. Default 90. */\n lookbackDays?: number;\n}\n\nexport interface GetAnalystMarketActivityOptions {\n /** Days of history to return. Default 30. */\n lookbackDays?: number;\n}\n\n/**\n * Wall Street analyst coverage: aggregate price targets, recommendation distribution,\n * recent upgrade/downgrade actions, and forward EPS estimates with earnings surprise history.\n *\n * Free users receive the price target band (low/mean/high + analyst count + consensus label)\n * in full -- it powers the public projection cone. The buy/hold/sell distribution counts\n * and full action/estimate history are PRO-only.\n */\nexport class Analyst {\n constructor(private client: APIClient) {}\n\n /**\n * Get the aggregate Wall Street consensus for a ticker. Returns 404 if no\n * coverage exists.\n */\n async consensus(\n ticker: string,\n ): Promise<PreviewResponse<AnalystConsensus>> {\n return this.client.get(\n `/api/v1/analyst/${encodeURIComponent(ticker.toUpperCase())}/consensus`,\n );\n }\n\n /**\n * Get recent analyst upgrade/downgrade actions for a ticker, newest first.\n * Free users receive the 3 most recent.\n */\n async actions(\n ticker: string,\n options?: GetAnalystActionsOptions,\n ): Promise<PreviewResponse<AnalystAction[]>> {\n return this.client.get(\n `/api/v1/analyst/${encodeURIComponent(ticker.toUpperCase())}/actions`,\n options,\n );\n }\n\n /**\n * Get forward EPS estimates and earnings surprise history for a ticker.\n * Free users receive 1 estimate (current quarter) plus the 2 most recent surprises.\n */\n async estimates(\n ticker: string,\n ): Promise<PreviewResponse<AnalystEstimatesResponse>> {\n return this.client.get(\n `/api/v1/analyst/${encodeURIComponent(ticker.toUpperCase())}/estimates`,\n );\n }\n\n /**\n * Get market-wide recent analyst actions across all covered tickers, newest first.\n * Free users receive the 5 most recent.\n */\n async marketActivity(\n options?: GetAnalystMarketActivityOptions,\n ): Promise<PreviewResponse<AnalystAction[]>> {\n return this.client.get(\"/api/v1/analyst/activity\", options);\n }\n}\n","import type { APIClient } from \"../client.js\";\nimport type {\n EarningsCalendarResponse,\n GetEarningsCalendarOptions,\n PreviewResponse,\n} from \"../types.js\";\n\nexport class Calendar {\n constructor(private client: APIClient) {}\n\n /**\n * Upcoming company earnings, sorted by date.\n *\n * Key-required. A FREE key returns the current week (`isPreview: true`); a PRO\n * key returns the full forward window (about 30 days). Field richness is\n * identical across tiers: the gate is how far ahead you can see, not which\n * columns you get. On a preview, `totalCount` is the full-window event count.\n */\n async getEarnings(\n options?: GetEarningsCalendarOptions,\n ): Promise<PreviewResponse<EarningsCalendarResponse>> {\n return this.client.get(\"/api/v1/calendar/earnings\", options);\n }\n}\n","import type { APIClient } from \"../client.js\";\nimport type {\n DocumentSearchResponse,\n DocumentSource,\n GetByEntityOptions,\n GetBySourceOptions,\n GetByTickerOptions,\n GetByTickerRangeOptions,\n GetStoriesByTickerOptions,\n GetStoriesOptions,\n SearchDocumentsOptions,\n Story,\n} from \"../types.js\";\n\nexport class Documents {\n constructor(private client: APIClient) {}\n\n /** Get document metrics for a stock. The rows are in `documents`. */\n async getByTicker(ticker: string, options?: GetByTickerOptions): Promise<DocumentSearchResponse> {\n return this.client.get(`/api/v1/documents/ticker/${encodeURIComponent(ticker)}`, options);\n }\n\n /** Get document metrics for a stock within a date range. The rows are in `documents`. */\n async getByTickerRange(ticker: string, options: GetByTickerRangeOptions): Promise<DocumentSearchResponse> {\n return this.client.get(\n `/api/v1/documents/ticker/${encodeURIComponent(ticker)}/range`,\n options,\n );\n }\n\n /** Get document metrics for a KB entity. The rows are in `documents`. */\n async getByEntity(entityId: string, options?: GetByEntityOptions): Promise<DocumentSearchResponse> {\n return this.client.get(\n `/api/v1/documents/entity/${encodeURIComponent(entityId)}`,\n options,\n );\n }\n\n /** Smart search with natural language query parsing. The rows are in `documents`. */\n async search(query: string, options?: SearchDocumentsOptions): Promise<DocumentSearchResponse> {\n return this.client.get(\"/api/v1/documents/search\", { query, ...options });\n }\n\n /** Get latest document metrics from a source type. The rows are in `documents`. */\n async getBySource(source: DocumentSource, options?: GetBySourceOptions): Promise<DocumentSearchResponse> {\n return this.client.get(\n `/api/v1/documents/source/${encodeURIComponent(source)}`,\n options,\n );\n }\n\n /** Get AI-curated news story clusters. */\n async getStories(options?: GetStoriesOptions): Promise<Story[]> {\n return this.client.get(\"/api/v1/documents/stories\", options);\n }\n\n /** Get full story detail by cluster ID. */\n async getStoryDetail(clusterId: string): Promise<unknown> {\n return this.client.get(`/api/v1/documents/stories/${encodeURIComponent(clusterId)}`);\n }\n\n /** Get stories for a specific stock. */\n async getStoriesByTicker(\n ticker: string,\n options?: GetStoriesByTickerOptions,\n ): Promise<Story[]> {\n return this.client.get(\n `/api/v1/documents/stories/ticker/${encodeURIComponent(ticker)}`,\n options,\n );\n }\n\n}\n","import type { APIClient } from \"../client.js\";\nimport type {\n EarningsQuarter,\n GetEarningsSummariesOptions,\n GetRecentEarningsOptions,\n PreviewResponse,\n RecentEarningsEntry,\n} from \"../types.js\";\n\n/**\n * Earnings: what a company actually reported, after the fact.\n *\n * A quarter's results arrive as a press release, a filing, and a call, none of\n * which is a data structure. {@link getSummaries} is the assembled version, one\n * object per fiscal quarter, and {@link getRecent} is the cross-ticker view of\n * who reported lately. Pair them to drive a post-earnings sweep: list the\n * window, then pull each ticker's analysis report.\n *\n * The forward-looking half of the family lives on `client.calendar.getEarnings()`,\n * which covers scheduled dates and consensus EPS rather than results.\n *\n * @see EarningsQuarter\n */\nexport class Earnings {\n constructor(private client: APIClient) {}\n\n /**\n * Per-quarter earnings analysis report for one ticker, newest first.\n *\n * Each quarter carries the editorial headline, the KPI cards that matter for\n * that company with year-over-year deltas, the guidance language as\n * management phrased it, and a summary of the earnings call.\n *\n * Branch on `isPreview`: a PRO key receives every hydrated quarter in full, a\n * FREE key receives the latest quarter shaped rather than truncated, plus\n * `totalCount`. {@link EarningsQuarter} documents which fields each tier\n * carries.\n *\n * A quarter typically appears within 48 hours of the company reporting, and\n * the call summary can arrive after the press-release content for the same\n * quarter, so read `generatedAt` and `transcriptGeneratedAt` rather than\n * assuming a fixed lag. A ticker with no stored quarter answers with an empty\n * `data` array, not a 404.\n *\n * Use canonical ticker symbols: `GOOGL` (not `GOOG`), `BRK.B` (not `BRK-B`).\n */\n async getSummaries(\n ticker: string,\n options?: GetEarningsSummariesOptions,\n ): Promise<PreviewResponse<EarningsQuarter[]>> {\n return this.client.get(\n `/api/v1/stocks/${encodeURIComponent(ticker.toUpperCase())}/earnings-summaries`,\n options,\n );\n }\n\n /**\n * Which covered companies reported on or after `today - days`, newest first.\n *\n * Every API key receives the full window it asks for, so `isPreview` is\n * always `false` here. The window is bounded by `reportDate`, so a quarter\n * reported inside it appears even when its call summary lands later, and an\n * empty `data` array means nobody in the covered set reported in that window.\n *\n * This is the backward-looking feed; `client.calendar.getEarnings()` is the\n * forward-looking one.\n */\n async getRecent(\n options?: GetRecentEarningsOptions,\n ): Promise<PreviewResponse<RecentEarningsEntry[]>> {\n return this.client.get(\"/api/v1/earnings/recent\", options);\n }\n}\n","import type { APIClient } from \"../client.js\";\nimport type {\n MetricType,\n MetricsOptions,\n MetricDistributionOptions,\n ServingMetric,\n MetricDistribution,\n} from \"../types.js\";\n\nexport class EntityMetrics {\n constructor(private client: APIClient) {}\n\n /**\n * Get time-series metric data for an entity using the v2 Serving Metrics API.\n *\n * @param symbol Ticker symbol (e.g. \"AAPL\") or entity urlSlug (e.g. \"Nancy-Pelosi\",\n * case-insensitive; discover slugs via stocks.getEntities()).\n * @param options Metric type and optional time range / resolution.\n */\n async getMetrics(\n symbol: string,\n options: MetricsOptions = {},\n ): Promise<ServingMetric[]> {\n const { metricType = \"sentiment\", startTime, endTime, maxDataPoints } = options;\n return this.client.get(\n `/api/v2/metrics/entity/${encodeURIComponent(symbol)}/metric/${encodeURIComponent(metricType)}`,\n {\n ...(startTime !== undefined && { startTime }),\n ...(endTime !== undefined && { endTime }),\n ...(maxDataPoints !== undefined && { maxDataPoints }),\n },\n );\n }\n\n /**\n * Get distribution data for a metric, broken down by a dimension (default: source).\n *\n * @param symbol Ticker symbol (e.g. \"AAPL\") or entity urlSlug.\n * @param metricType The metric to break down (e.g. \"mentions\", \"sentiment\").\n * @param options Optional dimension parameter.\n */\n async getDistribution(\n symbol: string,\n metricType: MetricType,\n options: MetricDistributionOptions = {},\n ): Promise<MetricDistribution> {\n const { dimension = \"source\" } = options;\n return this.client.get(\n `/api/v2/metrics/entity/${encodeURIComponent(symbol)}/distribution/${encodeURIComponent(metricType)}`,\n { dimension },\n );\n }\n}\n","import type { APIClient } from \"../client.js\";\nimport type { PreviewResponse } from \"../types.js\";\n\nexport interface EtfInfo {\n ticker: string;\n name: string;\n kbEntityId: string | null;\n urlSlug: string | null;\n issuer: string | null;\n trackedIndex: string | null;\n assetClass: string | null;\n}\n\nexport interface EtfHolding {\n ticker: string;\n name: string | null;\n /** Weight in the fund as a percentage (0-100). */\n weightPct: number;\n /** ISO date \"YYYY-MM-DD\". First date this holding appeared in the composition. */\n firstSeen: string | null;\n}\n\nexport interface EtfHoldings {\n ticker: string;\n issuer: string;\n issuerEndpoint: string | null;\n /** ISO date \"YYYY-MM-DD\". Composition snapshot date from the issuer. */\n asOfDate: string;\n /** Epoch seconds when SentiSense refreshed the composition. */\n fetchedAt: number | null;\n /** ISO date \"YYYY-MM-DD\". When the composition is scheduled to be refreshed next. */\n nextRefreshDue: string;\n totalHoldings: number;\n holdings: EtfHolding[];\n /** True when this is a top-N view rather than the full fund. */\n partial?: boolean | null;\n /** Issuer's reported total holdings when `partial=true`. */\n totalKnownHoldings?: number | null;\n}\n\nexport interface EtfAggregateCoverage {\n holdingsCount: number;\n holdingsCovered: number;\n /** Sum of weights (0-100) for the covered holdings. */\n weightCovered: number;\n partial?: boolean | null;\n totalKnownHoldings?: number | null;\n}\n\nexport interface WeightedConsensus {\n upsidePercent: number | null;\n consensusLabel: string | null;\n /** Fractions of covered AUM in each bucket. Sums to ~1.0. */\n distribution: Record<string, number>;\n totalAnalysts: number;\n}\n\nexport interface EtfAnalystContributor {\n ticker: string;\n weightPct: number;\n upsidePercent: number | null;\n consensusLabel: string | null;\n /** Signed contribution to the fund's weighted upside in percentage points. */\n contributionPp: number;\n}\n\nexport interface EtfAnalystAggregate {\n ticker: string;\n /** ISO date \"YYYY-MM-DD\". Composition snapshot date. */\n asOfDate: string | null;\n /** Epoch seconds when this rollup was computed. */\n computedAt: number;\n coverage: EtfAggregateCoverage;\n weightedConsensus: WeightedConsensus;\n /** Top contributors (up to 10) by absolute contribution to the weighted upside. */\n topContributors: EtfAnalystContributor[];\n}\n\nexport interface WeightedNetFlow {\n /** Weighted net dollar flow (buys - sells). Negative = net selling. */\n netDollars: number;\n buyDollars: number;\n sellDollars: number;\n /** Unweighted; for context. */\n buyTradeCount: number;\n /** Unweighted; for context. */\n sellTradeCount: number;\n distinctInsiderCount: number;\n}\n\nexport interface EtfInsiderContributor {\n ticker: string;\n weightPct: number;\n /** Per-stock net flow over the window (signed). */\n netDollars: number;\n /** Signed contribution to the weighted headline. */\n weightedNetDollars: number;\n tradeCount: number;\n}\n\nexport interface EtfInsiderAggregate {\n ticker: string;\n /** ISO date \"YYYY-MM-DD\". Composition snapshot date. */\n asOfDate: string | null;\n /** Epoch seconds when this rollup was computed. */\n computedAt: number;\n lookbackDays: number;\n coverage: EtfAggregateCoverage;\n weightedNetFlow: WeightedNetFlow;\n /** Top contributors (up to 10) by absolute weighted-net-dollar contribution. */\n topContributors: EtfInsiderContributor[];\n}\n\nexport interface EtfSentimentReading {\n sentiSenseScore: number | null;\n /** BULLISH / NEUTRAL / BEARISH. */\n scoreLabel: string;\n /** Epoch seconds when the underlying metric was produced. */\n asOfTimestamp: number | null;\n}\n\nexport interface EtfSentimentAggregate {\n ticker: string;\n /** ISO date \"YYYY-MM-DD\". Composition snapshot date. */\n asOfDate: string | null;\n /** Epoch seconds when this aggregate was assembled. */\n computedAt: number;\n coverage: EtfAggregateCoverage;\n /** Holdings-weighted SentiSense across the fund's constituents. */\n constituentsWeighted: EtfSentimentReading;\n /** Direct reading from mentions of the fund's own ticker. Null for low-mention funds. */\n direct: EtfSentimentReading | null;\n}\n\nexport interface GetEtfInsiderAggregateOptions {\n /** Trailing window for the trade aggregation. Typical values: 30, 90. Default 30. */\n lookbackDays?: number;\n}\n\n/**\n * ETF discovery, composition (holdings), and holdings-weighted aggregate views.\n *\n * Funds aren't rated by analysts directly, don't have insiders of their own, and\n * may not get many direct news mentions -- but the companies inside them do. The\n * aggregate endpoints synthesize fund-level views from each constituent's per-stock\n * data, weighted by allocation, with a coverage block so consumers see how much of\n * the fund's AUM the underlying data covered.\n *\n * Beta as of 2026-05-15: starting with a limited set of widely-traded funds.\n */\nexport class Etfs {\n constructor(private client: APIClient) {}\n\n /**\n * List every ETF tracked by SentiSense, sorted by ticker.\n */\n async list(): Promise<EtfInfo[]> {\n return this.client.get(\"/api/v1/etfs\");\n }\n\n /**\n * Get the full holdings composition for an ETF, including per-holding weights\n * and freshness metadata. Returns 404 for unknown ETFs or commodity-only funds.\n */\n async holdings(ticker: string): Promise<EtfHoldings> {\n return this.client.get(\n `/api/v1/etfs/${encodeURIComponent(ticker.toUpperCase())}/holdings`,\n );\n }\n\n /**\n * Get the holdings-weighted analyst consensus for an ETF, including the\n * top per-holding contributors that drive the weighted upside.\n */\n async analystAggregate(\n ticker: string,\n ): Promise<PreviewResponse<EtfAnalystAggregate>> {\n return this.client.get(\n `/api/v1/etfs/${encodeURIComponent(ticker.toUpperCase())}/aggregates/analyst`,\n );\n }\n\n /**\n * Get the holdings-weighted SEC Form 4 insider aggregate for an ETF over a\n * configurable trailing window, including per-holding `topContributors` with\n * signed contribution to the weighted headline.\n */\n async insiderAggregate(\n ticker: string,\n options?: GetEtfInsiderAggregateOptions,\n ): Promise<PreviewResponse<EtfInsiderAggregate>> {\n return this.client.get(\n `/api/v1/etfs/${encodeURIComponent(ticker.toUpperCase())}/aggregates/insider`,\n options,\n );\n }\n\n /**\n * Get two SentiSense Score readings side-by-side: `constituentsWeighted`\n * (precomputed daily weighted average across the fund's holdings) and `direct`\n * (score from mentions of the fund's own ticker). The two can diverge, and the\n * gap is itself information.\n */\n async sentimentAggregate(\n ticker: string,\n ): Promise<PreviewResponse<EtfSentimentAggregate>> {\n return this.client.get(\n `/api/v1/etfs/${encodeURIComponent(ticker.toUpperCase())}/aggregates/sentiment`,\n );\n }\n}\n","import type { APIClient } from \"../client.js\";\nimport type {\n InsiderActivityResponse,\n InsiderTrade,\n ClusterBuy,\n GetInsiderOptions,\n PreviewResponse,\n} from \"../types.js\";\n\nexport class Insider {\n constructor(private client: APIClient) {}\n\n /**\n * Get market-wide insider activity: top buys and sells aggregated by ticker.\n *\n * PRO-gated. Free-tier users receive a preview (top 5 per direction)\n * with `isPreview: true` in the response.\n */\n async getActivity(options?: GetInsiderOptions): Promise<PreviewResponse<InsiderActivityResponse>> {\n return this.client.get(\"/api/v1/insider/activity\", options);\n }\n\n /**\n * Get individual insider transactions for a specific stock.\n *\n * PRO-gated. Free users receive a preview of the top 5 transactions.\n */\n async getTrades(ticker: string, options?: GetInsiderOptions): Promise<PreviewResponse<InsiderTrade[]>> {\n return this.client.get(\n `/api/v1/insider/trades/${encodeURIComponent(ticker.toUpperCase())}`,\n options,\n );\n }\n\n /**\n * Get cluster buy signals: stocks where 3+ distinct insiders bought recently.\n *\n * PRO-gated. Free users receive a preview of the top 3 signals.\n */\n async getClusterBuys(options?: GetInsiderOptions): Promise<PreviewResponse<ClusterBuy[]>> {\n return this.client.get(\"/api/v1/insider/cluster-buys\", options);\n }\n}\n","import type { APIClient } from \"../client.js\";\nimport type {\n CongressTrade,\n PoliticianSummary,\n PoliticianDetail,\n GetPoliticianActivityOptions,\n GetPoliticiansOptions,\n GetPoliticianDirectoryOptions,\n GetPoliticianMemberOptions,\n PoliticianDirectory,\n PoliticianDirectoryResponse,\n PreviewResponse,\n} from \"../types.js\";\n\nexport class Politicians {\n constructor(private client: APIClient) {}\n\n /**\n * Get recent congressional STOCK Act trading activity across all politicians.\n *\n * PRO-gated. Free-tier users receive a preview (top 5 trades)\n * with `isPreview: true` in the response.\n *\n * The feed is longer than one response: a default 90-day window is routinely well over a\n * thousand disclosures, and without `limit` the server sends the first 200 with no marker\n * that it stopped. `totalCount` on the envelope is the real size on every tier, so page\n * with `limit` and `offset` rather than reading `data.length` as the total.\n *\n * ```typescript\n * const first = await client.politicians.getActivity({ limit: 100 });\n * for (let offset = 100; offset < first.totalCount!; offset += 100) {\n * const page = await client.politicians.getActivity({ limit: 100, offset });\n * // ... page.data\n * }\n * ```\n */\n async getActivity(\n options?: GetPoliticianActivityOptions,\n ): Promise<PreviewResponse<CongressTrade[]>> {\n return this.client.get(\"/api/v1/politicians/activity\", options);\n }\n\n /**\n * Get congressional trades for a specific stock.\n *\n * PRO-gated. Free users receive a preview of the top 3 trades.\n */\n async getFilings(\n ticker: string,\n options?: GetPoliticiansOptions,\n ): Promise<PreviewResponse<CongressTrade[]>> {\n return this.client.get(\n `/api/v1/politicians/filings/${encodeURIComponent(ticker.toUpperCase())}`,\n options,\n );\n }\n\n /**\n * Discover tracked members of Congress and the page slug identifying each, so you\n * can find who to query without knowing slugs upfront.\n *\n * Summary only, no trade data; use `getMember` for a member's filings.\n *\n * Unlike `getMembers`, this includes members who have **left Congress**, carrying\n * `former` and `servedUntil`. That roster lists who currently holds office, so a\n * former member is otherwise reachable only if you already know their slug.\n *\n * Requires an API key but does not consume monthly quota (per-minute rate limits\n * still apply), and is not tier-gated. Returns the unwrapped list payload.\n */\n async getDirectory(\n options?: GetPoliticianDirectoryOptions,\n ): Promise<PoliticianDirectory> {\n const resp = await this.client.get<PoliticianDirectoryResponse>(\n \"/api/v1/politicians/directory\",\n { ...options },\n );\n return resp.data;\n }\n\n /**\n * Get all tracked politicians with trading summary statistics.\n *\n * PRO-gated. Free users receive a preview of the top 5 members.\n *\n * Serves only members currently in office. Use `getDirectory` to enumerate\n * everyone tracked, former members included.\n */\n async getMembers(): Promise<PreviewResponse<PoliticianSummary[]>> {\n return this.client.get(\"/api/v1/politicians/members\");\n }\n\n /**\n * Get detailed profile for a single politician: summary, recent trades, top tickers.\n *\n * PRO-gated. Free users receive a preview-wrapped response.\n *\n * `data.recentTrades` is one page of the member's history, not all of it. Most members\n * have a few dozen disclosures and arrive complete in the default page; a handful have\n * thousands. `totalCount` on the envelope is the size of the whole history on every\n * tier, so page with `limit` and `offset` rather than reading `recentTrades.length` as\n * the total. `data.profile` and `data.topTickers` describe the whole history whatever\n * page you ask for, so `profile.totalTrades` does not shrink with a small `limit`.\n *\n * ```typescript\n * const first = await client.politicians.getMember(\"Ro-Khanna\", { limit: 500 });\n * for (let offset = 500; offset < first.totalCount!; offset += 500) {\n * const page = await client.politicians.getMember(\"Ro-Khanna\", { limit: 500, offset });\n * // ... page.data.recentTrades\n * }\n * ```\n */\n async getMember(\n slug: string,\n options?: GetPoliticianMemberOptions,\n ): Promise<PreviewResponse<PoliticianDetail>> {\n return this.client.get(\n `/api/v1/politicians/member/${encodeURIComponent(slug)}`,\n options,\n );\n }\n}\n","import type { APIClient } from \"../client.js\";\nimport type {\n Insight,\n GetInsightsOptions,\n PreviewResponse,\n} from \"../types.js\";\n\nexport interface GetStockInsightsRangeOptions {\n startDate: string;\n endDate: string;\n urgency?: \"low\" | \"medium\" | \"high\";\n insightType?: string;\n}\n\nexport interface GetLatestInsightsOptions {\n limit?: number;\n urgency?: \"low\" | \"medium\" | \"high\";\n}\n\nexport interface GetUserInsightsOptions {\n limit?: number;\n category?: string;\n}\n\nexport class Insights {\n constructor(private client: APIClient) {}\n\n /**\n * Get AI-generated insights for a specific stock, sorted by urgency then confidence.\n *\n * Returns the preview envelope: read the insights as `.data`. PRO callers get the\n * full list with `isPreview: false`; free callers get the top 3 with `isPreview: true`\n * and `totalCount` carrying the untruncated size.\n */\n async stock(\n ticker: string,\n options?: GetInsightsOptions,\n ): Promise<PreviewResponse<Insight[]>> {\n return this.client.get(\n `/api/v1/insights/stock/${encodeURIComponent(ticker.toUpperCase())}`,\n options,\n );\n }\n\n /**\n * Get AI insights for a stock within a date range.\n *\n * Returns the preview envelope: read the insights as `.data`. Free callers receive\n * the top 3, PRO callers the full list. The server returns 400 if `startDate` is\n * after `endDate`.\n */\n async stockRange(\n ticker: string,\n options: GetStockInsightsRangeOptions,\n ): Promise<PreviewResponse<Insight[]>> {\n return this.client.get(\n `/api/v1/insights/stock/${encodeURIComponent(ticker.toUpperCase())}/range`,\n options,\n );\n }\n\n /**\n * Get AI-generated market-level insights, sorted by urgency then confidence.\n *\n * Returns the preview envelope: read the insights as `.data`. PRO callers get the\n * full list with `isPreview: false`; free callers get the top 5 with `isPreview: true`\n * and `totalCount` carrying the untruncated size.\n */\n async market(): Promise<PreviewResponse<Insight[]>> {\n return this.client.get(\"/api/v1/insights/market\");\n }\n\n /**\n * Get the latest AI insights across all tracked stocks, newest first.\n *\n * Returns the preview envelope: read the insights as `.data`. Free callers receive\n * the top 5, PRO callers up to `limit` (clamped to 1-200).\n */\n async latest(\n options?: GetLatestInsightsOptions,\n ): Promise<PreviewResponse<Insight[]>> {\n return this.client.get(\"/api/v1/insights/latest\", options);\n }\n\n /**\n * Get personalized insights for the authenticated user.\n *\n * Biased toward the user's watchlist and portfolio when available; falls back\n * to market-level insights otherwise. API key authentication required.\n * Returns the preview envelope: read the insights as `.data`.\n */\n async user(\n options?: GetUserInsightsOptions,\n ): Promise<PreviewResponse<Insight[]>> {\n return this.client.get(\"/api/v1/insights/user\", options);\n }\n\n /**\n * Get available insight types for a specific stock.\n * API key required.\n *\n * Returns an array of insight type strings (e.g., `[\"sentiment_shift\", \"options_activity\"]`).\n */\n async types(ticker: string): Promise<string[]> {\n return this.client.get(\n `/api/v1/insights/stock/${encodeURIComponent(ticker.toUpperCase())}/types`,\n );\n }\n}\n","import type { APIClient } from \"../client.js\";\nimport type {\n GetFlowsOptions,\n GetHoldersOptions,\n Holder,\n InstitutionList,\n InstitutionListResponse,\n InstitutionalFlows,\n ListInstitutionsOptions,\n PreviewResponse,\n Quarter,\n TickerHolders,\n} from \"../types.js\";\n\nexport class Institutional {\n constructor(private client: APIClient) {}\n\n /** Get available 13F reporting quarters. */\n async getQuarters(): Promise<Quarter[]> {\n return this.client.get(\"/api/v1/institutional/quarters\");\n }\n\n /**\n * Get aggregate institutional activity per ticker for a quarter.\n *\n * `reportDate` is optional: omit it to get the latest available quarter, which may be\n * a still-open one holding only early filers. The response then carries `reportDate`\n * plus `isPending` and filer coverage counts so a partial quarter is clearly labeled.\n *\n * Returns the preview envelope, so the flows are one level down:\n * `const { data } = await client.institutional.getFlows(); data.inflows`.\n */\n async getFlows(\n reportDate?: string,\n options?: GetFlowsOptions,\n ): Promise<PreviewResponse<InstitutionalFlows>> {\n return this.client.get(\"/api/v1/institutional/flows\", {\n reportDate,\n ...options,\n });\n }\n\n /**\n * Get institutional holders for a specific stock.\n *\n * Returns the preview envelope wrapping a {@link TickerHolders} object, so the rows\n * are two levels down: `(await getHolders(t, d)).data.holders`, alongside ticker-level\n * totals like `holderCount`. Free callers get a truncated `holders` array with\n * `isPreview: true`.\n *\n * A widely held ticker returns thousands of rows: a megacap quarter is about\n * 6,000 holders and 1.5 MB. Pass `limit` unless you really want all of them.\n * Omitting `options` sends the original unbounded request.\n *\n * `limit` is the switch for the whole option set. With it, the response also carries\n * `returnedCount`, `offset`, and a `notableChanges` summary, so you can walk the list\n * without re-counting it. Without it, `offset` / `sortBy` / `sortDir` are ignored by the\n * server and you get the full unsorted list back with a 200.\n */\n async getHolders(\n ticker: string,\n reportDate: string,\n options?: GetHoldersOptions,\n ): Promise<PreviewResponse<TickerHolders>> {\n return this.client.get(\n `/api/v1/institutional/holders/${encodeURIComponent(ticker)}`,\n { reportDate, ...options },\n );\n }\n\n /**\n * Get activist investor positions (NEW or INCREASED).\n *\n * Returns the preview envelope, so read the rows as `.data`.\n */\n async getActivists(reportDate: string): Promise<PreviewResponse<Holder[]>> {\n return this.client.get(\"/api/v1/institutional/activist\", { reportDate });\n }\n\n /**\n * Discover institutions: a paginated, AUM-ranked list of filers (slug + metadata)\n * so you can find what to query without knowing slugs upfront.\n *\n * Each institution is rolled up by parent filer, so a multi-filer manager\n * (e.g. Vanguard) appears once with combined AUM. Summary only; use\n * `getInstitutionDetail` for a filer's full holdings.\n *\n * Requires an API key but does not consume monthly quota (per-minute rate\n * limits still apply). Returns the unwrapped list payload.\n */\n async listInstitutions(options?: ListInstitutionsOptions): Promise<InstitutionList> {\n const resp = await this.client.get<InstitutionListResponse>(\n \"/api/v1/institutional/institutions\",\n { ...options },\n );\n return resp.data;\n }\n\n /**\n * Get the full profile, summary stats, and current-quarter holdings for a\n * specific institutional filer.\n *\n * Resolved by URL slug (e.g. `Berkshire-Hathaway`) or numeric SEC CIK.\n * Free users receive the profile and top 10 holdings; PRO users receive the\n * full holdings array. Returns 404 if the slug or CIK is unknown.\n */\n async getInstitutionDetail(slugOrCik: string): Promise<unknown> {\n return this.client.get(\n `/api/v1/institutional/institution/${encodeURIComponent(slugOrCik)}`,\n );\n }\n}\n","import type { APIClient } from \"../client.js\";\nimport type { KBEntity } from \"../types.js\";\n\nexport class KB {\n constructor(private client: APIClient) {}\n\n /** Get popular entities for search suggestions. */\n async getPopularEntities(): Promise<KBEntity[]> {\n return this.client.get(\"/api/v1/kb/entities/popular\");\n }\n}\n","import type { APIClient } from \"../client.js\";\nimport type { MarketMood } from \"../types.js\";\n\nexport class MarketMoodResource {\n constructor(private client: APIClient) {}\n\n /** Get market mood data (scores, history, sectors). */\n async get(): Promise<MarketMood> {\n return this.client.get(\"/api/v2/market-mood\");\n }\n\n // TODO: accept a `days` param to control history length (the endpoint supports ?days=N).\n //\n // Market Mood is also reachable through `client.indexes`, which serves it in the shared\n // index envelope alongside fed-sentiment and ai-sentiment. Use this resource when you want\n // the phase band, weekly change, per-signal breakdown and per-sector map; use `indexes`\n // when you want every index to answer the same shape. Both report the same headline number.\n}\n","import type { APIClient } from \"../client.js\";\nimport type { MarketSummary } from \"../types.js\";\n\nexport class MarketSummaryResource {\n constructor(private client: APIClient) {}\n\n /** Get the AI-generated market summary with headline and analysis. */\n async get(): Promise<MarketSummary> {\n return this.client.get(\"/api/v1/market-summary\");\n }\n}\n","import type { APIClient } from \"../client.js\";\nimport type {\n EtfScreenerExecuteResponse,\n EtfScreenerRow,\n FeaturedScreen,\n ScreenerExecuteOptions,\n ScreenerExecuteResponse,\n ScreenerFieldCatalog,\n ScreenerFieldDescriptor,\n ScreenerFieldOption,\n ScreenerFilter,\n ScreenerPlan,\n ScreenerRow,\n ScreenerScreensResponse,\n ScreenerSort,\n} from \"../types.js\";\n\n/**\n * Screener: filter the tracked universe on the SentiSense Score, attention,\n * analyst consensus, technicals and price in a single query. It is the one\n * surface where our own signals sit in the same `WHERE` clause as the market\n * data, which is the point: screening on analyst ratings alone is something a\n * dozen free tools do, screening on analyst ratings *where the Score disagrees*\n * is not.\n *\n * Every screen is a {@link ScreenerPlan}. Take one from {@link screens} or\n * build your own, then hand it to {@link run} or {@link runEtfs}.\n *\n * Three field semantics are worth knowing before you write a filter, because\n * guessing them wrong produces a screen that looks fine and means nothing:\n *\n * - **`ANALYST_RATING_MEAN` is inverted.** It is the vendor's 1-to-5 scale\n * where `1.0` is strong buy, so bullish is `LTE 2.5`, not `GTE`. Prefer\n * `ANALYST_BUY_RATIO_PCT`, which runs the intuitive direction.\n * - **`MA_CROSS_STATE` is ordinal**, not a percentage: `1` golden cross (50-day\n * above 200-day), `-1` death cross, `0` neither. Use `EQ`.\n * - **`SENTIMENT_DIRECTION` is the sign of the 7-day SentiSense Score**\n * (`1` / `0` / `-1`) with a neutral band of plus-or-minus 5. Despite the name\n * it is not sentiment polarity, and `0` matches only an exact zero, so it\n * returns almost nothing.\n *\n * The Score fields (`SENTI_SCORE_7D`, `SENTI_SCORE_1M`, `SCORE_CHANGE_7D`) are\n * the SentiSense Score, not polarity: unbounded, banded at 5 / 13 / 23 either\n * side of zero. Filter on those band edges, not on values like `0.5`, which\n * behave as \"any positive score\".\n *\n * Nulls never match, in either direction: `RETURN_1Y >= 0` and `RETURN_1Y < 0`\n * do not partition the universe, because a stock listed four months ago is in\n * neither result. If a screen returns fewer rows than you expect, check\n * coverage before you check your thresholds.\n *\n * Screens read a snapshot that refreshes every 20 minutes, so this is not a\n * quote feed. Use `client.stocks.getQuote()` for live prices.\n */\nexport class Screener {\n constructor(private client: APIClient) {}\n\n /**\n * Every filterable field, with its unit, operators and description, for both\n * universes.\n *\n * Build a filter UI from this rather than hardcoding the list and you inherit\n * new fields as they ship. The ETF `STRING` fields (`ISSUER`, `ASSET_CLASS`,\n * `TRACKED_INDEX`) come back with their `values` populated from the live\n * universe, so pickers stay current without a redeploy.\n */\n async fields(): Promise<ScreenerFieldCatalog> {\n return this.client.get(\"/api/v1/screener/fields\");\n }\n\n /**\n * The curated screens shipped in the product, each with a runnable plan.\n *\n * Each `plan` round-trips straight into {@link run} (or {@link runEtfs} when\n * `plan.universe === \"ETF\"`) with nothing to rebuild.\n *\n * Their filters identify the field with `field` rather than `fieldName`.\n * Both keys are accepted on the way in, so read either when inspecting a plan\n * you did not build yourself.\n */\n async screens(): Promise<ScreenerScreensResponse> {\n return this.client.get(\"/api/v1/screener/screens\");\n }\n\n /**\n * Run a screen against the stock universe.\n *\n * `tickers` is optional: omit it to screen the whole tracked universe, pass a\n * list to screen a watchlist. `limit` sits next to the plan rather than\n * inside it, because a plan is a stored object and paging is a transport\n * concern; it defaults to 100 and caps at 500.\n *\n * Read `matched` before you read `results`: it is the count before `limit`\n * was applied, so a `matched` above your `limit` means you are holding the\n * top slice under the plan's sort, not the whole answer.\n *\n * @example\n * ```ts\n * const res = await client.screener.run({\n * plan: {\n * filters: [\n * { fieldName: \"SENTI_SCORE_7D\", op: \"GTE\", value: 13 },\n * { fieldName: \"ANALYST_BUY_RATIO_PCT\", op: \"LTE\", value: 30 },\n * { fieldName: \"ANALYST_COUNT\", op: \"GTE\", value: 5 },\n * ],\n * sort: { fieldName: \"SENTI_SCORE_7D\", dir: \"DESC\" },\n * },\n * limit: 25,\n * });\n * ```\n */\n async run(options: ScreenerExecuteOptions): Promise<ScreenerExecuteResponse> {\n return this.client.post(\"/api/v1/screener/execute\", options);\n }\n\n /**\n * Run a screen against the ETF universe.\n *\n * Same request shape as {@link run}, against a different field vocabulary:\n * take the ETF names from `fields().etf`. `IN` / `NOT_IN` take a `values`\n * array instead of `value` and are the operators for the string fields\n * (`ISSUER`, `ASSET_CLASS`, `TRACKED_INDEX`).\n *\n * `CONSTITUENTS_WEIGHTED_SENTISENSE` is the holdings-weighted SentiSense\n * Score across what the fund owns and is usually the one you want;\n * `DIRECT_SENTISENSE` is the Score from chatter about the fund ticker itself,\n * which on a broad index fund is mostly macro noise. `WEIGHT_COVERED_PCT`\n * tells you how much of the fund's weight had constituent data behind the\n * weighted number.\n */\n async runEtfs(options: ScreenerExecuteOptions): Promise<EtfScreenerExecuteResponse> {\n return this.client.post(\"/api/v1/screener/etfs/execute\", options);\n }\n}\n\n// Re-export for convenience so callers can `import type { ScreenerPlan }`\n// from the resource module instead of `../types`.\nexport type {\n EtfScreenerExecuteResponse,\n EtfScreenerRow,\n FeaturedScreen,\n ScreenerExecuteOptions,\n ScreenerExecuteResponse,\n ScreenerFieldCatalog,\n ScreenerFieldDescriptor,\n ScreenerFieldOption,\n ScreenerFilter,\n ScreenerPlan,\n ScreenerRow,\n ScreenerScreensResponse,\n ScreenerSort,\n};\n","import type { APIClient } from \"../client.js\";\nimport type {\n AISummary,\n ChartData,\n ChartDataPoint,\n CompanyKpisData,\n FloatInfo,\n Fundamentals,\n FundamentalsPeriodsResponse,\n TtmFundamentals,\n GetAISummaryOptions,\n GetChartOptions,\n GetDescriptionsOptions,\n GetFundamentalsOptions,\n GetImagesOptions,\n GetMetricsBreakdownOptions,\n GetProfileOptions,\n GetSimilarOptions,\n KpiCoverageResponse,\n KpiTypeEntry,\n MarketStatus,\n MetricsBreakdown,\n OptionsSummary,\n PreviewResponse,\n SimilarStock,\n ShortInterest,\n ShortVolume,\n StockDetail,\n StockEntity,\n StockSentiment,\n StockImage,\n StockPrice,\n StockProfile,\n StockQuote,\n} from \"../types.js\";\n\nexport class Stocks {\n constructor(private client: APIClient) {}\n\n /** List all available ticker symbols. */\n async list(): Promise<string[]> {\n return this.client.get(\"/api/v1/stocks\");\n }\n\n /** List all stocks with name, kbEntityId, urlSlug. */\n async listDetailed(): Promise<StockDetail[]> {\n return this.client.get(\"/api/v1/stocks/detailed\");\n }\n\n /** Get popular ticker symbols. */\n async listPopular(): Promise<string[]> {\n return this.client.get(\"/api/v1/stocks/popular\");\n }\n\n /** Get popular stocks with details. */\n async listPopularDetailed(): Promise<StockDetail[]> {\n return this.client.get(\"/api/v1/stocks/popular/detailed\");\n }\n\n /** Get real-time price for a single ticker. */\n async getPrice(ticker: string): Promise<StockPrice> {\n return this.client.get(\"/api/v1/stocks/price\", { ticker });\n }\n\n /**\n * Get aggregate quote snapshot: live price, today OHLC, 52-week range,\n * market cap, P/E, EPS TTM, and dividend yield in a single call.\n * All fields except `ticker` may be null when upstream data is unavailable.\n */\n async getQuote(ticker: string): Promise<StockQuote> {\n return this.client.get(`/api/v1/stocks/${encodeURIComponent(ticker)}/quote`);\n }\n\n /** Get real-time prices for multiple tickers. */\n async getPrices(tickers: string[]): Promise<StockPrice[]> {\n return this.client.get(\"/api/v1/stocks/prices\", {\n tickers: tickers.join(\",\"),\n });\n }\n\n /** Get batch company logo URLs. */\n async getImages(\n tickers: string[],\n options?: GetImagesOptions,\n ): Promise<Record<string, StockImage>> {\n return this.client.get(\"/api/v1/stocks/images\", {\n tickers: tickers.join(\",\"),\n ...options,\n });\n }\n\n /** Get company profiles with branding, market cap, sector. */\n async getDescriptions(\n tickers: string[],\n options?: GetDescriptionsOptions,\n ): Promise<Record<string, StockProfile>> {\n return this.client.get(\"/api/v1/stocks/descriptions\", {\n tickers: tickers.join(\",\"),\n ...options,\n });\n }\n\n /** Get peer/similar stocks. */\n async getSimilar(ticker: string, options?: GetSimilarOptions): Promise<SimilarStock[]> {\n return this.client.get(`/api/v1/stocks/${encodeURIComponent(ticker)}/similar`, options);\n }\n\n /** Get company profile (CEO, sector, industry, market data). */\n async getProfile(ticker: string, options?: GetProfileOptions): Promise<StockProfile> {\n return this.client.get(`/api/v1/stocks/${encodeURIComponent(ticker)}/profile`, options);\n }\n\n /**\n * Get the headline sentiment picture for a stock in one call.\n *\n * Returns the SentiSense Score with its 30-day regime, mention volume and social\n * dominance, per-source tone in `bySource`, plus related tickers, story drivers, a\n * narrative and an FAQ. Available in full on every API-key tier.\n *\n * Use `entityMetrics.getMetrics(ticker, \"sentiment\", ...)` instead when you need a time\n * series over a specific window rather than the headline read. Returns 404 for tickers\n * with no sentiment coverage.\n */\n async getSentiment(ticker: string): Promise<PreviewResponse<StockSentiment>> {\n return this.client.get(\n `/api/v1/stocks/${encodeURIComponent(ticker)}/sentiment`,\n );\n }\n\n /** Get related KB entities (people, products, partners). */\n async getEntities(ticker: string): Promise<StockEntity[]> {\n return this.client.get(`/api/v1/stocks/${encodeURIComponent(ticker)}/entities`);\n }\n\n /**\n * Get AI-generated stock analysis report. Requires PRO tier.\n *\n * `depth: \"deep\"` returns the full curated report and consumes one report view on\n * metered tiers; the default `\"basic\"` returns the one-paragraph summary.\n *\n * The deprecated `forceRefresh` option is accepted and discarded, not forwarded.\n */\n async getAISummary(ticker: string, options?: GetAISummaryOptions): Promise<AISummary> {\n const { forceRefresh: _forceRefresh, ...params } = options ?? {};\n return this.client.get(`/api/v1/stocks/${encodeURIComponent(ticker)}/ai-summary`, params);\n }\n\n /** Get sentiment/mention metrics breakdown by entity. */\n async getMetricsBreakdown(\n ticker: string,\n metricType: string,\n options?: GetMetricsBreakdownOptions,\n ): Promise<MetricsBreakdown> {\n return this.client.get(\n `/api/v1/stocks/${encodeURIComponent(ticker)}/metrics/${encodeURIComponent(metricType)}/breakdown`,\n options,\n );\n }\n\n /**\n * Get historical OHLCV chart data.\n *\n * The API returns a bare array of points; this normalizes it to\n * `{ ticker, timeframe, data }`. `timeframe` echoes the requested value\n * (defaulting to \"1M\", matching the server default when omitted).\n */\n async getChart(ticker: string, options?: GetChartOptions): Promise<ChartData> {\n const data = await this.client.get<ChartDataPoint[]>(\"/api/v1/stocks/chart\", {\n ticker,\n ...options,\n });\n return { ticker, timeframe: options?.timeframe ?? \"1M\", data };\n }\n\n /** Get current market open/closed/pre-market/after-hours status. */\n async getMarketStatus(): Promise<MarketStatus> {\n return this.client.get(\"/api/v1/stocks/market-status\");\n }\n\n /**\n * Get financial statement data for one reporting period: income statement, balance sheet,\n * and cash flow, including `capitalExpenditure` and `freeCashFlow`.\n *\n * Capital expenditure is signed as filed, so normally negative. See {@link Fundamentals}\n * for the free-cash-flow relationship and when it is `null`.\n */\n async getFundamentals(ticker: string, options?: GetFundamentalsOptions): Promise<Fundamentals> {\n return this.client.get(\"/api/v1/stocks/fundamentals\", { ticker, ...options });\n }\n\n /** Get available fiscal periods. The periods are in `periods`. */\n async getFundamentalsPeriods(ticker: string): Promise<FundamentalsPeriodsResponse> {\n return this.client.get(\"/api/v1/stocks/fundamentals/periods\", { ticker });\n }\n\n /**\n * Get the trailing-twelve-month fundamentals snapshot: TTM ratios, a different\n * shape from the per-period statement data `getFundamentals()` returns.\n */\n async getCurrentFundamentals(ticker: string): Promise<TtmFundamentals> {\n return this.client.get(\"/api/v1/stocks/fundamentals/current\", { ticker });\n }\n\n /** Get historical revenue data. */\n async getHistoricalRevenue(ticker: string): Promise<unknown> {\n return this.client.get(\"/api/v1/stocks/fundamentals/historical/revenue\", { ticker });\n }\n\n /** Get short interest metrics (FINRA). */\n async getShortInterest(ticker: string): Promise<ShortInterest> {\n return this.client.get(\"/api/v1/stocks/short-interest\", { ticker });\n }\n\n /** Get float information. */\n async getFloat(ticker: string): Promise<FloatInfo> {\n return this.client.get(\"/api/v1/stocks/float\", { ticker });\n }\n\n /** Get short volume trading data. */\n async getShortVolume(ticker: string): Promise<ShortVolume> {\n return this.client.get(\"/api/v1/stocks/short-volume\", { ticker });\n }\n\n /**\n * Get company-specific KPI time-series for a ticker. Returns curated GAAP and\n * non-GAAP metrics from earnings filings (e.g. iPhone unit sales, Tesla deliveries,\n * AWS revenue).\n *\n * Free users receive metadata only with an empty `kpis` list; PRO users receive\n * the full series. Returns 404 for tickers that do not yet have curated coverage.\n *\n * Coverage today: near-complete for the S&P 500 plus extended universe\n * (~500 tickers). Use `listKpiCoverage()` to enumerate.\n */\n async getKpis(ticker: string): Promise<PreviewResponse<CompanyKpisData>> {\n return this.client.get(\n `/api/v1/stocks/${encodeURIComponent(ticker.toUpperCase())}/kpis`,\n );\n }\n\n /**\n * List every ticker with curated KPI coverage. Returns `{count, tickers: [...]}`\n * with lightweight metadata (ticker, companyName, lastUpdated, kpiCount).\n * Sorted alphabetically by ticker.\n *\n * Auth: API key required, but the call does NOT consume your monthly quota\n * (rate-limit-per-minute still applies).\n */\n async listKpiCoverage(): Promise<KpiCoverageResponse> {\n return this.client.get(\"/api/v1/stocks/with-kpis\");\n }\n\n /**\n * List the KPI metadata tuples available for a ticker (`id, name, category,\n * chartType`) without paying the cost of the full series payload. Mirrors\n * the `/api/v1/insights/stock/{ticker}/types` precedent.\n *\n * Auth: API key required, no quota cost. 404 if the ticker has no curated KPIs.\n */\n async getKpiTypes(ticker: string): Promise<KpiTypeEntry[]> {\n return this.client.get(\n `/api/v1/stocks/${encodeURIComponent(ticker.toUpperCase())}/kpis/types`,\n );\n }\n\n /**\n * Get the end-of-day options dossier for one stock or ETF: the session's aggregate, its\n * percentile context, the open-interest wall structure with max pain, and the contracts\n * whose volume ran far ahead of their open interest.\n *\n * End of day, not live. `asOf` is the prior trading session and the data refreshes the\n * following morning, so this is positioning, not a quote feed.\n *\n * **`data` is `null` for a ticker outside the covered universe**, which is the most\n * actively optioned US names plus the tracked ETFs, and for a covered ticker with no\n * snapshot yet. An unknown symbol behaves the same way rather than answering 404, so treat\n * a null as \"no coverage\", never as an error. A covered ticker still building its baseline\n * returns its raw readings with the percentiles omitted.\n *\n * Percentiles compare a ticker to its own trailing history, never to another ticker, so an\n * ETF's readings are not comparable with a single stock's.\n *\n * Tiering: a PRO key always receives the full dossier. A FREE key receives it for the first\n * ten calls each calendar month and a headline-only preview after that, with `isPreview`\n * true; calls that return a null `data` never spend that allowance.\n */\n async getOptionsSummary(ticker: string): Promise<PreviewResponse<OptionsSummary | null>> {\n return this.client.get(\n `/api/v1/stocks/${encodeURIComponent(ticker.toUpperCase())}/options/summary`,\n );\n }\n}\n","import type { APIClient } from \"../client.js\";\nimport type {\n IndexConstituent,\n IndexHistoryPoint,\n IndexHistoryResponse,\n IndexListing,\n IndexListResponse,\n IndexSnapshot,\n} from \"../types.js\";\n\n/**\n * Indexes: composite scalars tracked over time, each blending its own inputs\n * into one number on a stated scale. Every index answers on the same envelope,\n * so you write one renderer and get every current and future SentiSense index.\n *\n * Two archetypes share that envelope. A **basket** index weight-averages\n * tracked entities and fills `constituents` / `basketSize` / `coverage` /\n * `totalMentions`; a **composite** index is built from signals instead and\n * returns `null` for all four by construction. See {@link IndexSnapshot}.\n *\n * @see IndexSnapshot\n */\nexport class Indexes {\n constructor(private client: APIClient) {}\n\n /**\n * List every index the platform publishes: id, display name, one-line\n * description, the scale it lives on, its access tier, and where its richest\n * view lives.\n *\n * Iterate this rather than hardcoding ids. Every `indexId` it advertises\n * resolves on {@link get} and {@link history}.\n */\n async list(): Promise<IndexListResponse> {\n return this.client.get(\"/api/v1/indexes\");\n }\n\n /**\n * Latest reading for one index.\n *\n * Check `constituents` for `null` before iterating: it is `null` on a\n * composite index like `market-mood`, which has no constituents by\n * construction. For Market Mood this is the narrowed view; the phase band,\n * weekly change, per-signal breakdown and per-sector map live on\n * `client.marketMood.get()`, and both report the same headline number.\n *\n * @param indexId slug from {@link list}, e.g. `\"fed-sentiment\"`.\n */\n async get(indexId: string): Promise<IndexSnapshot> {\n return this.client.get(`/api/v1/indexes/${indexId}`);\n }\n\n /**\n * Historical scalar series for one index, for charting.\n *\n * Thin or low-coverage buckets are withheld, so the series can be shorter\n * than `days` and can contain gaps. Plot against each point's `date`.\n *\n * @param indexId slug from {@link list}.\n * @param days days of history to return. Defaults to the API's own 180.\n */\n async history(indexId: string, days?: number): Promise<IndexHistoryResponse> {\n return this.client.get(\n `/api/v1/indexes/${indexId}/history`,\n days === undefined ? undefined : { days },\n );\n }\n}\n\n// Re-export for convenience so callers can `import type { IndexListing }`\n// from the resource module instead of `../types`.\nexport type {\n IndexConstituent,\n IndexHistoryPoint,\n IndexHistoryResponse,\n IndexListing,\n IndexListResponse,\n IndexSnapshot,\n};\n","import type { APIClient } from \"../client.js\";\nimport type {\n TrackerListing,\n TrackerListResponse,\n TrackerSnapshot,\n TrackerSnapshotResponse,\n} from \"../types.js\";\n\n/**\n * Trackers: observational data products published as a standardized\n * `TrackerSnapshot` envelope. Every tracker (institution rankings,\n * hedge-fund reported returns, social trackers, surveillance dashboards)\n * returns the same shape, so consumers write one renderer per `viewType` and\n * get every current and future SentiSense tracker for free.\n *\n * @see TrackerSnapshot\n */\nexport class Trackers {\n constructor(private client: APIClient) {}\n\n /**\n * List every publicly-visible tracker: id, display name, category,\n * one-line description, and the methodology anchor to link out to.\n */\n async list(): Promise<TrackerListResponse> {\n return this.client.get(\"/api/v1/trackers\");\n }\n\n /**\n * Standardized snapshot envelope for one tracker.\n *\n * Returns the envelope as-is: `{ isPreview, previewReason, totalCount?, data }`.\n * When `data.viewType === \"table\"` the rows live at `data.rows[]`; when\n * `\"choropleth\"` they live at `data.geo[]`; etc. Dispatch on `viewType`\n * in your renderer.\n *\n * @param trackerId slug from {@link list}, e.g. `\"institution-concentration\"`.\n * @param params provider-specific query params (e.g. `{ scope: \"us\" }` for\n * geographically-scoped trackers like hantavirus). Unknown keys are ignored.\n */\n async get(\n trackerId: string,\n params?: Record<string, string | number | boolean>,\n ): Promise<TrackerSnapshotResponse> {\n return this.client.get(`/api/v1/trackers/${trackerId}`, params);\n }\n}\n\n// Re-export for convenience so callers can `import type { TrackerListing }`\n// from the resource module instead of `../types`.\nexport type {\n TrackerListing,\n TrackerListResponse,\n TrackerSnapshot,\n TrackerSnapshotResponse,\n};\n","export const VERSION = \"0.44.0\";\n","import {\n APIError,\n AuthenticationError,\n DeepHistoryUnavailableError,\n NotFoundError,\n RateLimitError,\n SentiSenseError,\n} from \"./errors.js\";\nimport { Analyst } from \"./resources/analyst.js\";\nimport { Calendar } from \"./resources/calendar.js\";\nimport { Documents } from \"./resources/documents.js\";\nimport { Earnings } from \"./resources/earnings.js\";\nimport { EntityMetrics } from \"./resources/entityMetrics.js\";\nimport { Etfs } from \"./resources/etfs.js\";\nimport { Insider } from \"./resources/insider.js\";\nimport { Politicians } from \"./resources/politicians.js\";\nimport { Insights } from \"./resources/insights.js\";\nimport { Institutional } from \"./resources/institutional.js\";\nimport { KB } from \"./resources/kb.js\";\nimport { MarketMoodResource } from \"./resources/marketMood.js\";\nimport { MarketSummaryResource } from \"./resources/marketSummary.js\";\nimport { Screener } from \"./resources/screener.js\";\nimport { Stocks } from \"./resources/stocks.js\";\nimport { Indexes } from \"./resources/indexes.js\";\nimport { Trackers } from \"./resources/trackers.js\";\nimport type { SentiSenseOptions } from \"./types.js\";\nimport { VERSION } from \"./version.js\";\n\nconst DEFAULT_BASE_URL = \"https://app.sentisense.ai\";\nconst DEFAULT_TIMEOUT = 30_000;\nconst DEFAULT_MAX_RETRIES = 3;\nconst BASE_DELAY_MS = 1_000;\nconst MAX_DELAY_MS = 60_000;\n// Used when a 202 arrives without a usable Retry-After header.\nconst DEEP_HISTORY_FALLBACK_WAIT_S = 3;\n\n// Upper bounds on any server-supplied Retry-After. Rate limiting gets the longer ceiling\n// because a genuine limit window is legitimately minutes, while a deep-history warm-up is\n// seconds. Without a ceiling an oversized header value strands the caller indefinitely.\nconst MAX_DEEP_HISTORY_WAIT_S = 30;\nconst MAX_RATE_LIMIT_WAIT_S = 120;\nconst RATE_LIMIT_FALLBACK_WAIT_S = 60;\n\n/**\n * A `Retry-After` header as a usable number of seconds, clamped to `[0.5, maxWaitS]`, or\n * `undefined` when there is no usable value.\n *\n * `Retry-After` is vendor-controlled and may legally carry an HTTP-date rather than a\n * number of seconds, in which case parsing yields `NaN`. Left unguarded that produced a\n * `NaN` delay which compared false against every threshold and retried instantly in a busy\n * loop, and a `NaN` on the error object that silently broke a caller's own backoff.\n * Anything that is not a finite number is treated as absent.\n */\nfunction clampRetryAfter(\n raw: string | null,\n maxWaitS: number,\n): number | undefined {\n if (!raw) return undefined;\n const parsed = Number(raw);\n if (!Number.isFinite(parsed)) return undefined;\n return Math.min(Math.max(0.5, parsed), maxWaitS);\n}\n\n/** Same clamp, resolved to `defaultS` when the header gives us nothing to go on. */\nfunction retryAfterSeconds(\n raw: string | null,\n defaultS: number,\n maxWaitS: number,\n): number {\n return clampRetryAfter(raw, maxWaitS) ?? defaultS;\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/** @internal HTTP interface exposed to resource classes. */\nexport interface APIClient {\n get<T = unknown>(path: string, params?: object): Promise<T>;\n post<T = unknown>(path: string, body: unknown): Promise<T>;\n}\n\nexport class SentiSense implements APIClient {\n private baseUrl: string;\n private apiKey: string | undefined;\n private timeout: number;\n private maxRetries: number;\n private userAgent: string;\n\n readonly stocks: Stocks;\n readonly documents: Documents;\n readonly etfs: Etfs;\n readonly institutional: Institutional;\n readonly insider: Insider;\n readonly politicians: Politicians;\n readonly insights: Insights;\n readonly analyst: Analyst;\n readonly entityMetrics: EntityMetrics;\n readonly marketMood: MarketMoodResource;\n readonly marketSummary: MarketSummaryResource;\n readonly kb: KB;\n readonly indexes: Indexes;\n readonly trackers: Trackers;\n readonly calendar: Calendar;\n readonly earnings: Earnings;\n readonly screener: Screener;\n\n constructor(options: SentiSenseOptions = {}) {\n this.apiKey = options.apiKey;\n this.baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\\/+$/, \"\");\n this.timeout = options.timeout ?? DEFAULT_TIMEOUT;\n this.maxRetries = options.maxRetries ?? DEFAULT_MAX_RETRIES;\n // A header value cannot carry CR/LF, so collapse them rather than letting a caller's\n // string decide where the header block ends.\n const suffix = options.userAgentSuffix?.replace(/[\\r\\n]+/g, \" \").trim();\n this.userAgent = suffix\n ? `sentisense-node/${VERSION} ${suffix}`\n : `sentisense-node/${VERSION}`;\n\n this.stocks = new Stocks(this);\n this.documents = new Documents(this);\n this.etfs = new Etfs(this);\n this.institutional = new Institutional(this);\n this.insider = new Insider(this);\n this.politicians = new Politicians(this);\n this.insights = new Insights(this);\n this.analyst = new Analyst(this);\n this.entityMetrics = new EntityMetrics(this);\n this.marketMood = new MarketMoodResource(this);\n this.marketSummary = new MarketSummaryResource(this);\n this.kb = new KB(this);\n this.indexes = new Indexes(this);\n this.trackers = new Trackers(this);\n this.calendar = new Calendar(this);\n this.earnings = new Earnings(this);\n this.screener = new Screener(this);\n }\n\n /** @internal */\n async get<T = unknown>(path: string, params?: object): Promise<T> {\n const url = this.buildUrl(path, params);\n const headers: Record<string, string> = {\n \"Accept\": \"application/json\",\n };\n\n if (this.apiKey) {\n headers[\"X-SentiSense-API-Key\"] = this.apiKey;\n }\n\n // User-Agent is only set in Node.js (browsers disallow it)\n if (typeof process !== \"undefined\" && process.versions?.node) {\n headers[\"User-Agent\"] = this.userAgent;\n }\n\n let delayMs = 0;\n\n for (let attempt = 0; attempt <= this.maxRetries; attempt++) {\n if (delayMs > 0) {\n await sleep(delayMs);\n delayMs = 0;\n }\n\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await fetch(url, {\n method: \"GET\",\n headers,\n signal: controller.signal,\n });\n\n // 202 means a deep chart range is still being built server-side. It is a 2xx, so\n // without this it would fall through and return an empty array: the caller would\n // see \"no data\" rather than \"not ready yet\", which is the exact confusion the\n // status code exists to prevent. Retry honouring Retry-After, then surface it.\n if (response.status === 202) {\n const waitSeconds = retryAfterSeconds(\n response.headers.get(\"Retry-After\"),\n DEEP_HISTORY_FALLBACK_WAIT_S,\n MAX_DEEP_HISTORY_WAIT_S,\n );\n try { await response.body?.cancel(); } catch { /* ignore */ }\n if (attempt < this.maxRetries) {\n delayMs = waitSeconds * 1000;\n continue;\n }\n throw new DeepHistoryUnavailableError(\n \"Deep history is still being assembled. Retry in a few seconds.\",\n waitSeconds,\n );\n }\n\n if (!response.ok) {\n const isRetryable = response.status === 429 || response.status >= 500;\n if (isRetryable && attempt < this.maxRetries) {\n if (response.status === 429) {\n delayMs = retryAfterSeconds(\n response.headers.get(\"Retry-After\"),\n RATE_LIMIT_FALLBACK_WAIT_S,\n MAX_RATE_LIMIT_WAIT_S,\n ) * 1000;\n } else {\n delayMs = Math.min(BASE_DELAY_MS * Math.pow(2, attempt), MAX_DELAY_MS) + Math.random() * 1000;\n }\n try { await response.body?.cancel(); } catch { /* ignore */ }\n continue;\n }\n await this.handleErrorResponse(response);\n }\n\n return (await response.json()) as T;\n } catch (error) {\n if (error instanceof SentiSenseError) throw error;\n if (error instanceof Error && error.name === \"AbortError\") {\n throw new SentiSenseError(`Request timed out after ${this.timeout}ms`);\n }\n throw new SentiSenseError(\n error instanceof Error ? error.message : \"Unknown error\",\n );\n } finally {\n clearTimeout(timer);\n }\n }\n\n throw new SentiSenseError(\"All retries exhausted\");\n }\n\n /** @internal */\n async post<T = unknown>(path: string, body: unknown): Promise<T> {\n const url = this.buildUrl(path);\n const headers: Record<string, string> = {\n \"Accept\": \"application/json\",\n \"Content-Type\": \"application/json\",\n };\n\n if (this.apiKey) {\n headers[\"X-SentiSense-API-Key\"] = this.apiKey;\n }\n\n if (typeof process !== \"undefined\" && process.versions?.node) {\n headers[\"User-Agent\"] = this.userAgent;\n }\n\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await fetch(url, {\n method: \"POST\",\n headers,\n body: JSON.stringify(body),\n signal: controller.signal,\n });\n\n if (!response.ok) {\n await this.handleErrorResponse(response);\n }\n\n return (await response.json()) as T;\n } catch (error) {\n if (error instanceof SentiSenseError) throw error;\n if (error instanceof Error && error.name === \"AbortError\") {\n throw new SentiSenseError(`Request timed out after ${this.timeout}ms`);\n }\n throw new SentiSenseError(\n error instanceof Error ? error.message : \"Unknown error\",\n );\n } finally {\n clearTimeout(timer);\n }\n }\n\n private buildUrl(path: string, params?: object): string {\n const url = new URL(path, this.baseUrl);\n if (params) {\n for (const [key, value] of Object.entries(params as Record<string, unknown>)) {\n if (value !== undefined && value !== null) {\n url.searchParams.set(key, String(value));\n }\n }\n }\n return url.toString();\n }\n\n private async handleErrorResponse(response: Response): Promise<never> {\n let body: { error?: string; message?: string } = {};\n try {\n body = await response.json();\n } catch {\n // Response may not be JSON\n }\n\n const message = body.message ?? response.statusText ?? \"API request failed\";\n const code = body.error;\n\n switch (response.status) {\n case 401:\n case 403:\n throw new AuthenticationError(message, response.status, code);\n case 404:\n throw new NotFoundError(message, code);\n case 429: {\n // Same clamp the retry loop uses, so a caller running its own backoff off\n // `error.retryAfter` gets a number it can pass to setTimeout, or nothing at all.\n const retryAfter = clampRetryAfter(\n response.headers.get(\"Retry-After\"),\n MAX_RATE_LIMIT_WAIT_S,\n );\n throw new RateLimitError(message, code, retryAfter);\n }\n default:\n throw new APIError(message, response.status, code);\n }\n }\n}\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sentisense",
3
- "version": "0.43.0",
3
+ "version": "0.44.0",
4
4
  "description": "Official JavaScript/TypeScript SDK for the SentiSense market intelligence API",
5
5
  "author": "SentiSense <support@sentisense.ai>",
6
6
  "license": "MIT",