fmp-ai-tools 0.2.4-beta.1 → 0.2.4-beta.2
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 +2 -1
- package/dist/providers/openai/index.js +114 -62
- package/dist/providers/openai/index.js.map +1 -1
- package/dist/providers/openai/index.mjs +114 -62
- package/dist/providers/openai/index.mjs.map +1 -1
- package/dist/providers/vercel-ai/index.js +114 -62
- package/dist/providers/vercel-ai/index.js.map +1 -1
- package/dist/providers/vercel-ai/index.mjs +114 -62
- package/dist/providers/vercel-ai/index.mjs.map +1 -1
- package/package.json +2 -2
|
@@ -195,6 +195,20 @@ function limitRows(res, limit2, compare) {
|
|
|
195
195
|
const rows = compare ? [...res.data].sort(compare) : res.data;
|
|
196
196
|
return { ...res, data: rows.slice(0, limit2) };
|
|
197
197
|
}
|
|
198
|
+
function toCappedToolResponse(res, limit2, options = {}) {
|
|
199
|
+
const total = res.success !== false && Array.isArray(res.data) ? res.data.length : 0;
|
|
200
|
+
const capped = limitRows(res, limit2, options.compare);
|
|
201
|
+
if (total <= limit2) return toToolResponse(capped);
|
|
202
|
+
return JSON.stringify(
|
|
203
|
+
{
|
|
204
|
+
data: capped.data,
|
|
205
|
+
truncated: true,
|
|
206
|
+
note: `Showing ${limit2} of ${total} rows. ${options.hint ?? "Increase `limit` to see more."}`
|
|
207
|
+
},
|
|
208
|
+
null,
|
|
209
|
+
2
|
|
210
|
+
);
|
|
211
|
+
}
|
|
198
212
|
function toToolError(error) {
|
|
199
213
|
const message = error instanceof Error ? error.message : String(error);
|
|
200
214
|
let type = "unknown";
|
|
@@ -276,7 +290,7 @@ var quoteDefinitions = [
|
|
|
276
290
|
to: z.string().optional().nullable().describe("End date in YYYY-MM-DD format (optional)"),
|
|
277
291
|
limit: z.number().int().positive().default(30).describe("Max number of most-recent days to return (default 30)")
|
|
278
292
|
}),
|
|
279
|
-
execute: async ({ symbol: symbol2, from, to, limit: limit2
|
|
293
|
+
execute: async ({ symbol: symbol2, from, to, limit: limit2 }) => {
|
|
280
294
|
const res = await getFMPClient().quote.getHistoricalPrice({
|
|
281
295
|
symbol: symbol2,
|
|
282
296
|
from: from ?? void 0,
|
|
@@ -286,7 +300,7 @@ var quoteDefinitions = [
|
|
|
286
300
|
if (res.success && data && Array.isArray(data.historical)) {
|
|
287
301
|
return toToolResponse({
|
|
288
302
|
...res,
|
|
289
|
-
data: { ...data, historical: data.historical.slice(0, limit2) }
|
|
303
|
+
data: { ...data, historical: data.historical.slice(0, limit2 ?? 30) }
|
|
290
304
|
});
|
|
291
305
|
}
|
|
292
306
|
return toToolResponse(res);
|
|
@@ -302,7 +316,7 @@ var quoteDefinitions = [
|
|
|
302
316
|
to: z.string().optional().nullable().describe("End date in YYYY-MM-DD format (optional)"),
|
|
303
317
|
limit: z.number().int().positive().default(50).describe("Max number of most-recent bars to return (default 50)")
|
|
304
318
|
}),
|
|
305
|
-
execute: async ({ symbol: symbol2, interval = "5min", from, to, limit: limit2
|
|
319
|
+
execute: async ({ symbol: symbol2, interval = "5min", from, to, limit: limit2 }) => {
|
|
306
320
|
const res = await getFMPClient().quote.getIntraday({
|
|
307
321
|
symbol: symbol2,
|
|
308
322
|
interval,
|
|
@@ -310,7 +324,7 @@ var quoteDefinitions = [
|
|
|
310
324
|
to: to ?? void 0
|
|
311
325
|
});
|
|
312
326
|
if (res.success && Array.isArray(res.data)) {
|
|
313
|
-
return toToolResponse({ ...res, data: res.data.slice(0, limit2) });
|
|
327
|
+
return toToolResponse({ ...res, data: res.data.slice(0, limit2 ?? 50) });
|
|
314
328
|
}
|
|
315
329
|
return toToolResponse(res);
|
|
316
330
|
}
|
|
@@ -338,7 +352,7 @@ var companyDefinitions = [
|
|
|
338
352
|
inputSchema: symbolSchema.extend({
|
|
339
353
|
limit: z.number().int().positive().default(20).describe("Max number of compensation records to return (default 20)")
|
|
340
354
|
}),
|
|
341
|
-
execute: async ({ symbol: symbol2, limit: limit2
|
|
355
|
+
execute: async ({ symbol: symbol2, limit: limit2 }) => toCappedToolResponse(await getFMPClient().company.getExecutiveCompensation(symbol2), limit2 ?? 20)
|
|
342
356
|
}),
|
|
343
357
|
defineTool({
|
|
344
358
|
name: "getStockPeers",
|
|
@@ -354,7 +368,7 @@ var statementTool = (name, description, what, call) => defineTool({
|
|
|
354
368
|
name,
|
|
355
369
|
description,
|
|
356
370
|
inputSchema: z.object({ symbol: symbol(what), period, limit }),
|
|
357
|
-
execute: async ({ symbol: symbol2, period: period2, limit: limit2 }) => toToolResponse(await call({ symbol: symbol2, period: period2, limit: limit2 }))
|
|
371
|
+
execute: async ({ symbol: symbol2, period: period2, limit: limit2 }) => toToolResponse(await call({ symbol: symbol2, period: period2, limit: limit2 ?? void 0 }))
|
|
358
372
|
});
|
|
359
373
|
var financialDefinitions = [
|
|
360
374
|
statementTool(
|
|
@@ -424,7 +438,9 @@ var financialDefinitions = [
|
|
|
424
438
|
symbol: symbol("earnings historical"),
|
|
425
439
|
limit: z.number().default(10).describe("The number of periods to retrieve")
|
|
426
440
|
}),
|
|
427
|
-
execute: async ({ symbol: symbol2, limit: limit2 }) => toToolResponse(
|
|
441
|
+
execute: async ({ symbol: symbol2, limit: limit2 }) => toToolResponse(
|
|
442
|
+
await getFMPClient().financial.getEarningsHistorical({ symbol: symbol2, limit: limit2 ?? 10 })
|
|
443
|
+
)
|
|
428
444
|
}),
|
|
429
445
|
defineTool({
|
|
430
446
|
name: "getFinancialScores",
|
|
@@ -469,30 +485,33 @@ var dateRangeSchema = z.object({
|
|
|
469
485
|
var calendarDefinitions = [
|
|
470
486
|
defineTool({
|
|
471
487
|
name: "getEarningsCalendar",
|
|
472
|
-
description: "Get earnings calendar showing upcoming and recent earnings announcements
|
|
473
|
-
inputSchema: dateRangeSchema
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
)
|
|
482
|
-
|
|
488
|
+
description: "Get earnings calendar showing upcoming and recent earnings announcements, in date order. A week can hold ~2,000 companies worldwide, so pass `symbols` to look up specific companies (e.g. mega-cap tech) instead of scanning the whole calendar.",
|
|
489
|
+
inputSchema: dateRangeSchema.extend({
|
|
490
|
+
symbols: z.array(z.string().min(1)).optional().nullable().describe('Only return these symbols (e.g., ["AAPL", "MSFT", "NVDA"])')
|
|
491
|
+
}),
|
|
492
|
+
execute: async ({ from, to, symbols, limit: limit2 }) => {
|
|
493
|
+
const res = await getFMPClient().calendar.getEarningsCalendar({
|
|
494
|
+
from: from ?? void 0,
|
|
495
|
+
to: to ?? void 0
|
|
496
|
+
});
|
|
497
|
+
const wanted = symbols?.length ? new Set(symbols.map((s) => s.toUpperCase())) : null;
|
|
498
|
+
const filtered = wanted && res.success !== false && Array.isArray(res.data) ? { ...res, data: res.data.filter((row) => wanted.has(row.symbol.toUpperCase())) } : res;
|
|
499
|
+
return toCappedToolResponse(filtered, limit2 ?? 50, {
|
|
500
|
+
hint: "Rows are in date order. Pass `symbols` to find specific companies, or narrow the date range."
|
|
501
|
+
});
|
|
502
|
+
}
|
|
483
503
|
}),
|
|
484
504
|
defineTool({
|
|
485
505
|
name: "getEconomicCalendar",
|
|
486
|
-
description: "Get economic calendar showing upcoming and recent economic events and indicators (at most `limit` entries; narrow the date range for full coverage)",
|
|
506
|
+
description: "Get economic calendar showing upcoming and recent economic events and indicators, in date order (at most `limit` entries; narrow the date range for full coverage)",
|
|
487
507
|
inputSchema: dateRangeSchema,
|
|
488
|
-
execute: async ({ from, to, limit: limit2
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
)
|
|
508
|
+
execute: async ({ from, to, limit: limit2 }) => toCappedToolResponse(
|
|
509
|
+
await getFMPClient().calendar.getEconomicsCalendar({
|
|
510
|
+
from: from ?? void 0,
|
|
511
|
+
to: to ?? void 0
|
|
512
|
+
}),
|
|
513
|
+
limit2 ?? 50,
|
|
514
|
+
{ hint: "Rows are in date order; narrow the date range to see the rest." }
|
|
496
515
|
)
|
|
497
516
|
})
|
|
498
517
|
];
|
|
@@ -559,17 +578,29 @@ var etfDefinitions = [
|
|
|
559
578
|
description: "Get the largest holdings of an ETF (by portfolio weight), showing the underlying assets and their weights",
|
|
560
579
|
inputSchema: z.object({
|
|
561
580
|
symbol: z.string().min(1, "ETF symbol is required").describe("ETF symbol (e.g., SPY, QQQ, VTI)"),
|
|
562
|
-
date: z.string().optional().nullable().describe("
|
|
581
|
+
date: z.string().optional().nullable().describe("Holdings date in YYYY-MM-DD format (optional; defaults to the latest filing)"),
|
|
563
582
|
limit: z.number().int().positive().default(50).describe("Max number of holdings to return, largest weight first (default 50)")
|
|
564
583
|
}),
|
|
565
|
-
execute: async ({ symbol: symbol2, date, limit: limit2
|
|
584
|
+
execute: async ({ symbol: symbol2, date, limit: limit2 }) => {
|
|
585
|
+
const client = getFMPClient();
|
|
586
|
+
let holdingsDate = date ?? void 0;
|
|
587
|
+
if (!holdingsDate) {
|
|
588
|
+
const dates = await client.etf.getHoldingDates(symbol2);
|
|
589
|
+
if (dates.success !== false && Array.isArray(dates.data)) {
|
|
590
|
+
holdingsDate = dates.data.reduce(
|
|
591
|
+
(latest, d) => !latest || d.date > latest ? d.date : latest,
|
|
592
|
+
void 0
|
|
593
|
+
);
|
|
594
|
+
}
|
|
595
|
+
}
|
|
566
596
|
const params = { symbol: symbol2 };
|
|
567
|
-
if (
|
|
568
|
-
params.date =
|
|
597
|
+
if (holdingsDate) {
|
|
598
|
+
params.date = holdingsDate;
|
|
569
599
|
}
|
|
570
|
-
return
|
|
571
|
-
|
|
572
|
-
|
|
600
|
+
return toCappedToolResponse(await client.etf.getHoldings(params), limit2 ?? 50, {
|
|
601
|
+
compare: (a, b) => b.pctVal - a.pctVal,
|
|
602
|
+
hint: `Largest positions first, as of ${holdingsDate ?? "the requested date"}.`
|
|
603
|
+
});
|
|
573
604
|
}
|
|
574
605
|
}),
|
|
575
606
|
defineTool({
|
|
@@ -592,23 +623,36 @@ var insiderDefinitions = [
|
|
|
592
623
|
execute: async ({ symbol: symbol2, page }) => toToolResponse(await getFMPClient().insider.getInsiderTradesBySymbol(symbol2, page))
|
|
593
624
|
})
|
|
594
625
|
];
|
|
626
|
+
var YEAR_MS = 365 * 24 * 60 * 60 * 1e3;
|
|
627
|
+
var holderKey = (name) => name.toLowerCase().replace(/[^a-z0-9]+/g, " ").replace(/\b(inc|corp|corporation|co|llc|ltd|lp|plc|the)\b/g, " ").replace(/\s+/g, " ").trim();
|
|
628
|
+
function currentHolders(rows) {
|
|
629
|
+
const newest = rows.reduce((max, r) => Math.max(max, Date.parse(r.dateReported) || 0), 0);
|
|
630
|
+
const latest = /* @__PURE__ */ new Map();
|
|
631
|
+
for (const row of rows) {
|
|
632
|
+
const reported = Date.parse(row.dateReported);
|
|
633
|
+
if (!(reported >= newest - YEAR_MS)) continue;
|
|
634
|
+
const key = holderKey(row.holder);
|
|
635
|
+
const prev = latest.get(key);
|
|
636
|
+
if (!prev || reported > Date.parse(prev.dateReported)) latest.set(key, row);
|
|
637
|
+
}
|
|
638
|
+
return [...latest.values()];
|
|
639
|
+
}
|
|
595
640
|
var institutionalDefinitions = [
|
|
596
641
|
defineTool({
|
|
597
642
|
name: "getInstitutionalHolders",
|
|
598
|
-
description: "Get
|
|
643
|
+
description: "Get a stock's largest current institutional holders by shares held (each holder's latest 13F filing from the past year)",
|
|
599
644
|
inputSchema: z.object({
|
|
600
645
|
symbol: z.string().min(1, "Stock symbol is required").describe("Stock symbol (e.g., AAPL, MSFT, GOOGL)"),
|
|
601
646
|
limit: z.number().int().positive().default(20).describe("Max number of holders to return, largest first (default 20)")
|
|
602
647
|
}),
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
)
|
|
648
|
+
execute: async ({ symbol: symbol2, limit: limit2 }) => {
|
|
649
|
+
const res = await getFMPClient().institutional.getInstitutionalHolders({ symbol: symbol2 });
|
|
650
|
+
const current = res.success !== false && Array.isArray(res.data) ? { ...res, data: currentHolders(res.data) } : res;
|
|
651
|
+
return toCappedToolResponse(current, limit2 ?? 20, {
|
|
652
|
+
compare: (a, b) => b.shares - a.shares,
|
|
653
|
+
hint: "Holders are ordered by shares held, largest first."
|
|
654
|
+
});
|
|
655
|
+
}
|
|
612
656
|
})
|
|
613
657
|
];
|
|
614
658
|
var empty = z.object({});
|
|
@@ -623,7 +667,7 @@ var marketDefinitions = [
|
|
|
623
667
|
inputSchema: z.object({
|
|
624
668
|
limit: z.number().int().positive().default(50).describe("Max number of indices to return (default 50)")
|
|
625
669
|
}),
|
|
626
|
-
execute: async ({ limit: limit2
|
|
670
|
+
execute: async ({ limit: limit2 }) => toCappedToolResponse(await getFMPClient().market.getMarketPerformance(), limit2 ?? 50)
|
|
627
671
|
}),
|
|
628
672
|
defineTool({
|
|
629
673
|
name: "getSectorPerformance",
|
|
@@ -675,11 +719,11 @@ var newsDefinitions = [
|
|
|
675
719
|
to: z.string().optional().nullable().describe("End date in YYYY-MM-DD format (optional)"),
|
|
676
720
|
limit: z.number().int().positive().default(20).describe("Max number of articles to return (default 20)")
|
|
677
721
|
}),
|
|
678
|
-
execute: async ({ from, to, limit: limit2
|
|
722
|
+
execute: async ({ from, to, limit: limit2 }) => toToolResponse(
|
|
679
723
|
await getFMPClient().news.getStockNews({
|
|
680
724
|
from: from ?? void 0,
|
|
681
725
|
to: to ?? void 0,
|
|
682
|
-
limit: limit2
|
|
726
|
+
limit: limit2 ?? 20
|
|
683
727
|
})
|
|
684
728
|
)
|
|
685
729
|
}),
|
|
@@ -692,12 +736,12 @@ var newsDefinitions = [
|
|
|
692
736
|
to: z.string().optional().nullable().describe("End date in YYYY-MM-DD format (optional)"),
|
|
693
737
|
limit: z.number().int().positive().default(20).describe("Max number of articles to return (default 20)")
|
|
694
738
|
}),
|
|
695
|
-
execute: async ({ symbols, from, to, limit: limit2
|
|
739
|
+
execute: async ({ symbols, from, to, limit: limit2 }) => toToolResponse(
|
|
696
740
|
await getFMPClient().news.getStockNewsBySymbol({
|
|
697
741
|
symbols,
|
|
698
742
|
from: from ?? void 0,
|
|
699
743
|
to: to ?? void 0,
|
|
700
|
-
limit: limit2
|
|
744
|
+
limit: limit2 ?? 20
|
|
701
745
|
})
|
|
702
746
|
)
|
|
703
747
|
})
|
|
@@ -719,8 +763,8 @@ var screenerDefinitions = [
|
|
|
719
763
|
isActivelyTrading: z.boolean().optional().nullable().describe("Restrict to actively trading"),
|
|
720
764
|
limit: z.number().int().positive().default(50).describe("Max number of results to return (default 50)")
|
|
721
765
|
}),
|
|
722
|
-
execute: async ({ limit: limit2
|
|
723
|
-
const params = { limit: limit2 };
|
|
766
|
+
execute: async ({ limit: limit2, ...filters }) => {
|
|
767
|
+
const params = { limit: limit2 ?? 50 };
|
|
724
768
|
for (const [key, value] of Object.entries(filters)) {
|
|
725
769
|
if (value !== null && value !== void 0) params[key] = value;
|
|
726
770
|
}
|
|
@@ -737,8 +781,12 @@ var searchDefinitions = [
|
|
|
737
781
|
limit: z.number().int().positive().default(10).describe("Max number of results to return (default 10)"),
|
|
738
782
|
exchange: z.string().optional().nullable().describe('Restrict to a specific exchange (optional, e.g., "NASDAQ")')
|
|
739
783
|
}),
|
|
740
|
-
execute: async ({ query, limit: limit2
|
|
741
|
-
await getFMPClient().search.search({
|
|
784
|
+
execute: async ({ query, limit: limit2, exchange }) => toToolResponse(
|
|
785
|
+
await getFMPClient().search.search({
|
|
786
|
+
query,
|
|
787
|
+
limit: limit2 ?? 10,
|
|
788
|
+
exchange: exchange ?? void 0
|
|
789
|
+
})
|
|
742
790
|
)
|
|
743
791
|
})
|
|
744
792
|
];
|
|
@@ -751,7 +799,9 @@ var analystDefinitions = [
|
|
|
751
799
|
period: z.enum(["annual", "quarter"]).default("annual").describe("The period type (annual or quarter)"),
|
|
752
800
|
limit: z.number().int().positive().default(10).describe("Max number of periods to return (default 10)")
|
|
753
801
|
}),
|
|
754
|
-
execute: async ({ symbol: symbol2, period: period2 = "annual", limit: limit2
|
|
802
|
+
execute: async ({ symbol: symbol2, period: period2 = "annual", limit: limit2 }) => toToolResponse(
|
|
803
|
+
await getFMPClient().analyst.getEstimates({ symbol: symbol2, period: period2, limit: limit2 ?? 10 })
|
|
804
|
+
)
|
|
755
805
|
}),
|
|
756
806
|
defineTool({
|
|
757
807
|
name: "getPriceTargetConsensus",
|
|
@@ -768,10 +818,10 @@ var analystDefinitions = [
|
|
|
768
818
|
symbol: z.string().min(1).describe("The stock symbol (e.g., AAPL)"),
|
|
769
819
|
limit: z.number().int().positive().default(20).describe("Max number of grade entries to return (default 20)")
|
|
770
820
|
}),
|
|
771
|
-
execute: async ({ symbol: symbol2, limit: limit2
|
|
821
|
+
execute: async ({ symbol: symbol2, limit: limit2 }) => {
|
|
772
822
|
const res = await getFMPClient().analyst.getGrades({ symbol: symbol2 });
|
|
773
823
|
if (res.success && Array.isArray(res.data)) {
|
|
774
|
-
return toToolResponse({ ...res, data: res.data.slice(0, limit2) });
|
|
824
|
+
return toToolResponse({ ...res, data: res.data.slice(0, limit2 ?? 20) });
|
|
775
825
|
}
|
|
776
826
|
return toToolResponse(res);
|
|
777
827
|
}
|
|
@@ -813,7 +863,7 @@ var technicalDefinitions = [
|
|
|
813
863
|
timeframe: z.enum(["1min", "5min", "15min", "30min", "1hour", "4hour", "1day", "1week", "1month"]).default("1day").describe("Bar timeframe"),
|
|
814
864
|
limit: z.number().int().positive().default(50).describe("Max number of most-recent bars to return (default 50)")
|
|
815
865
|
}),
|
|
816
|
-
execute: async ({ symbol: symbol2, type, periodLength = 10, timeframe = "1day", limit: limit2
|
|
866
|
+
execute: async ({ symbol: symbol2, type, periodLength = 10, timeframe = "1day", limit: limit2 }) => {
|
|
817
867
|
const res = await getFMPClient().technical.getTechnicalIndicator({
|
|
818
868
|
symbol: symbol2,
|
|
819
869
|
type,
|
|
@@ -821,7 +871,7 @@ var technicalDefinitions = [
|
|
|
821
871
|
timeframe
|
|
822
872
|
});
|
|
823
873
|
if (res.success && Array.isArray(res.data)) {
|
|
824
|
-
return toToolResponse({ ...res, data: res.data.slice(0, limit2) });
|
|
874
|
+
return toToolResponse({ ...res, data: res.data.slice(0, limit2 ?? 50) });
|
|
825
875
|
}
|
|
826
876
|
return toToolResponse(res);
|
|
827
877
|
}
|
|
@@ -854,8 +904,9 @@ var senateHouseDefinitions = [
|
|
|
854
904
|
name: z.string().min(1, "Name is required").describe("The name of the senator to get trading data for"),
|
|
855
905
|
limit: byNameLimit
|
|
856
906
|
}),
|
|
857
|
-
execute: async ({ name, limit: limit2
|
|
858
|
-
|
|
907
|
+
execute: async ({ name, limit: limit2 }) => toCappedToolResponse(
|
|
908
|
+
await getFMPClient().senateHouse.getSenateTradingByName({ name }),
|
|
909
|
+
limit2 ?? 50
|
|
859
910
|
)
|
|
860
911
|
}),
|
|
861
912
|
defineTool({
|
|
@@ -865,8 +916,9 @@ var senateHouseDefinitions = [
|
|
|
865
916
|
name: z.string().min(1, "Name is required").describe("The name of the representative to get trading data for"),
|
|
866
917
|
limit: byNameLimit
|
|
867
918
|
}),
|
|
868
|
-
execute: async ({ name, limit: limit2
|
|
869
|
-
|
|
919
|
+
execute: async ({ name, limit: limit2 }) => toCappedToolResponse(
|
|
920
|
+
await getFMPClient().senateHouse.getHouseTradingByName({ name }),
|
|
921
|
+
limit2 ?? 50
|
|
870
922
|
)
|
|
871
923
|
}),
|
|
872
924
|
defineTool({
|