fmp-ai-tools 0.2.0-beta.2 → 0.2.0-beta.4
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 +18 -5
- package/dist/providers/openai/index.js +73 -39
- package/dist/providers/openai/index.js.map +1 -1
- package/dist/providers/openai/index.mjs +73 -39
- package/dist/providers/openai/index.mjs.map +1 -1
- package/dist/providers/vercel-ai/index.js +72 -38
- package/dist/providers/vercel-ai/index.js.map +1 -1
- package/dist/providers/vercel-ai/index.mjs +72 -38
- package/dist/providers/vercel-ai/index.mjs.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -302,12 +302,25 @@ Each tool accepts specific parameters. Here are some common ones:
|
|
|
302
302
|
|
|
303
303
|
## Error Handling
|
|
304
304
|
|
|
305
|
-
|
|
305
|
+
When a request fails, a tool returns a structured JSON error (instead of `null`) so the model can explain *why* to the user:
|
|
306
306
|
|
|
307
|
-
|
|
308
|
-
-
|
|
309
|
-
|
|
310
|
-
|
|
307
|
+
```json
|
|
308
|
+
{ "error": true, "type": "plan-restricted", "message": "This endpoint is not available on your current FMP plan. (403: ...)", "status": 403 }
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
The `type` field classifies the failure so your agent can react appropriately:
|
|
312
|
+
|
|
313
|
+
| `type` | Meaning |
|
|
314
|
+
| ----------------- | ------------------------------------------------------------ |
|
|
315
|
+
| `plan-restricted` | Endpoint isn't included in your FMP subscription (402/403) |
|
|
316
|
+
| `rate-limit` | FMP quota / rate limit reached (429) |
|
|
317
|
+
| `auth` | Invalid or missing `FMP_API_KEY` (401) |
|
|
318
|
+
| `not-found` | Resource does not exist (404) |
|
|
319
|
+
| `bad-request` | Invalid parameters (400) |
|
|
320
|
+
| `network` | No response from FMP (timeout / offline) |
|
|
321
|
+
| `unknown` | Anything else |
|
|
322
|
+
|
|
323
|
+
This is especially useful on lower FMP tiers: an agent calling an endpoint your plan doesn't cover now gets a clear `plan-restricted` message it can relay, rather than empty data. (Direct `fmp-node-api` callers get the same classification via `response.errorType`.)
|
|
311
324
|
|
|
312
325
|
## Testing Tools
|
|
313
326
|
|
|
@@ -177,6 +177,36 @@ async function logApiExecutionWithTiming(toolName, input, executeFn) {
|
|
|
177
177
|
}
|
|
178
178
|
}
|
|
179
179
|
|
|
180
|
+
// src/utils/format-response.ts
|
|
181
|
+
function toToolResponse(res) {
|
|
182
|
+
if (res.success === false) {
|
|
183
|
+
return JSON.stringify({
|
|
184
|
+
error: true,
|
|
185
|
+
type: res.errorType ?? "unknown",
|
|
186
|
+
message: res.error ?? "The request failed.",
|
|
187
|
+
status: res.status
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
if (isEmpty(res.data)) {
|
|
191
|
+
return JSON.stringify({ data: [], note: "No data was returned for this request." });
|
|
192
|
+
}
|
|
193
|
+
return JSON.stringify(res.data, null, 2);
|
|
194
|
+
}
|
|
195
|
+
function toToolError(error) {
|
|
196
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
197
|
+
let type = "unknown";
|
|
198
|
+
if (/api[\s_-]?key/i.test(message)) {
|
|
199
|
+
type = "auth";
|
|
200
|
+
}
|
|
201
|
+
return JSON.stringify({ error: true, type, message, status: 0 });
|
|
202
|
+
}
|
|
203
|
+
function isEmpty(data) {
|
|
204
|
+
if (data == null) return true;
|
|
205
|
+
if (Array.isArray(data)) return data.length === 0;
|
|
206
|
+
if (typeof data === "object") return Object.keys(data).length === 0;
|
|
207
|
+
return false;
|
|
208
|
+
}
|
|
209
|
+
|
|
180
210
|
// src/utils/openai-tool-wrapper.ts
|
|
181
211
|
function createOpenAITool(config) {
|
|
182
212
|
const { name, description, inputSchema, execute } = config;
|
|
@@ -185,8 +215,12 @@ function createOpenAITool(config) {
|
|
|
185
215
|
description,
|
|
186
216
|
parameters: inputSchema,
|
|
187
217
|
execute: async (input) => {
|
|
188
|
-
|
|
189
|
-
|
|
218
|
+
try {
|
|
219
|
+
const args = inputSchema.parse(input);
|
|
220
|
+
return await logApiExecutionWithTiming(name, args, () => execute(args));
|
|
221
|
+
} catch (error) {
|
|
222
|
+
return toToolError(error);
|
|
223
|
+
}
|
|
190
224
|
}
|
|
191
225
|
});
|
|
192
226
|
}
|
|
@@ -204,7 +238,7 @@ var getCompanyProfile = createOpenAITool({
|
|
|
204
238
|
execute: async ({ symbol }) => {
|
|
205
239
|
const fmp = getFMPClient();
|
|
206
240
|
const companyProfile = await fmp.company.getCompanyProfile(symbol);
|
|
207
|
-
return
|
|
241
|
+
return toToolResponse(companyProfile);
|
|
208
242
|
}
|
|
209
243
|
});
|
|
210
244
|
var getCompanySharesFloat = createOpenAITool({
|
|
@@ -216,7 +250,7 @@ var getCompanySharesFloat = createOpenAITool({
|
|
|
216
250
|
execute: async ({ symbol }) => {
|
|
217
251
|
const fmp = getFMPClient();
|
|
218
252
|
const companySharesFloat = await fmp.company.getSharesFloat(symbol);
|
|
219
|
-
return
|
|
253
|
+
return toToolResponse(companySharesFloat);
|
|
220
254
|
}
|
|
221
255
|
});
|
|
222
256
|
var getCompanyExecutiveCompensation = createOpenAITool({
|
|
@@ -228,7 +262,7 @@ var getCompanyExecutiveCompensation = createOpenAITool({
|
|
|
228
262
|
execute: async ({ symbol }) => {
|
|
229
263
|
const fmp = getFMPClient();
|
|
230
264
|
const companyExecutiveCompensation = await fmp.company.getExecutiveCompensation(symbol);
|
|
231
|
-
return
|
|
265
|
+
return toToolResponse(companyExecutiveCompensation);
|
|
232
266
|
}
|
|
233
267
|
});
|
|
234
268
|
var calendarInputSchema = zod.z.object({
|
|
@@ -245,7 +279,7 @@ var getEarningsCalendar = createOpenAITool({
|
|
|
245
279
|
from: from ?? void 0,
|
|
246
280
|
to: to ?? void 0
|
|
247
281
|
});
|
|
248
|
-
return
|
|
282
|
+
return toToolResponse(earningsCalendar);
|
|
249
283
|
}
|
|
250
284
|
});
|
|
251
285
|
var getEconomicCalendar = createOpenAITool({
|
|
@@ -258,7 +292,7 @@ var getEconomicCalendar = createOpenAITool({
|
|
|
258
292
|
from: from ?? void 0,
|
|
259
293
|
to: to ?? void 0
|
|
260
294
|
});
|
|
261
|
-
return
|
|
295
|
+
return toToolResponse(economicCalendar);
|
|
262
296
|
}
|
|
263
297
|
});
|
|
264
298
|
var treasuryRatesInputSchema = zod.z.object({
|
|
@@ -305,7 +339,7 @@ var getTreasuryRates = createOpenAITool({
|
|
|
305
339
|
from: from ?? void 0,
|
|
306
340
|
to: to ?? void 0
|
|
307
341
|
});
|
|
308
|
-
return
|
|
342
|
+
return toToolResponse(treasuryRates);
|
|
309
343
|
}
|
|
310
344
|
});
|
|
311
345
|
var getEconomicIndicators = createOpenAITool({
|
|
@@ -319,7 +353,7 @@ var getEconomicIndicators = createOpenAITool({
|
|
|
319
353
|
from: from ?? void 0,
|
|
320
354
|
to: to ?? void 0
|
|
321
355
|
});
|
|
322
|
-
return
|
|
356
|
+
return toToolResponse(economicIndicators);
|
|
323
357
|
}
|
|
324
358
|
});
|
|
325
359
|
var etfHoldingsInputSchema = zod.z.object({
|
|
@@ -340,7 +374,7 @@ var getETFHoldings = createOpenAITool({
|
|
|
340
374
|
params.date = date;
|
|
341
375
|
}
|
|
342
376
|
const etfHoldings = await fmp.etf.getHoldings(params);
|
|
343
|
-
return
|
|
377
|
+
return toToolResponse(etfHoldings);
|
|
344
378
|
}
|
|
345
379
|
});
|
|
346
380
|
var getETFProfile = createOpenAITool({
|
|
@@ -350,7 +384,7 @@ var getETFProfile = createOpenAITool({
|
|
|
350
384
|
execute: async ({ symbol }) => {
|
|
351
385
|
const fmp = getFMPClient();
|
|
352
386
|
const etfProfile = await fmp.etf.getProfile(symbol);
|
|
353
|
-
return
|
|
387
|
+
return toToolResponse(etfProfile);
|
|
354
388
|
}
|
|
355
389
|
});
|
|
356
390
|
var getBalanceSheet = createOpenAITool({
|
|
@@ -368,7 +402,7 @@ var getBalanceSheet = createOpenAITool({
|
|
|
368
402
|
period,
|
|
369
403
|
limit: Number(limit)
|
|
370
404
|
});
|
|
371
|
-
return
|
|
405
|
+
return toToolResponse(balanceSheet);
|
|
372
406
|
}
|
|
373
407
|
});
|
|
374
408
|
var getIncomeStatement = createOpenAITool({
|
|
@@ -386,7 +420,7 @@ var getIncomeStatement = createOpenAITool({
|
|
|
386
420
|
period,
|
|
387
421
|
limit: Number(limit)
|
|
388
422
|
});
|
|
389
|
-
return
|
|
423
|
+
return toToolResponse(incomeStatement);
|
|
390
424
|
}
|
|
391
425
|
});
|
|
392
426
|
var getCashFlowStatement = createOpenAITool({
|
|
@@ -404,7 +438,7 @@ var getCashFlowStatement = createOpenAITool({
|
|
|
404
438
|
period,
|
|
405
439
|
limit: Number(limit)
|
|
406
440
|
});
|
|
407
|
-
return
|
|
441
|
+
return toToolResponse(cashFlowStatement);
|
|
408
442
|
}
|
|
409
443
|
});
|
|
410
444
|
var getKeyMetrics = createOpenAITool({
|
|
@@ -418,7 +452,7 @@ var getKeyMetrics = createOpenAITool({
|
|
|
418
452
|
execute: async ({ symbol, period, limit }) => {
|
|
419
453
|
const fmp = getFMPClient();
|
|
420
454
|
const keyMetrics = await fmp.financial.getKeyMetrics({ symbol, period, limit: Number(limit) });
|
|
421
|
-
return
|
|
455
|
+
return toToolResponse(keyMetrics);
|
|
422
456
|
}
|
|
423
457
|
});
|
|
424
458
|
var getFinancialRatios = createOpenAITool({
|
|
@@ -436,7 +470,7 @@ var getFinancialRatios = createOpenAITool({
|
|
|
436
470
|
period,
|
|
437
471
|
limit: Number(limit)
|
|
438
472
|
});
|
|
439
|
-
return
|
|
473
|
+
return toToolResponse(financialRatios);
|
|
440
474
|
}
|
|
441
475
|
});
|
|
442
476
|
var getEnterpriseValue = createOpenAITool({
|
|
@@ -454,7 +488,7 @@ var getEnterpriseValue = createOpenAITool({
|
|
|
454
488
|
period,
|
|
455
489
|
limit: Number(limit)
|
|
456
490
|
});
|
|
457
|
-
return
|
|
491
|
+
return toToolResponse(enterpriseValue);
|
|
458
492
|
}
|
|
459
493
|
});
|
|
460
494
|
var getCashflowGrowth = createOpenAITool({
|
|
@@ -472,7 +506,7 @@ var getCashflowGrowth = createOpenAITool({
|
|
|
472
506
|
period,
|
|
473
507
|
limit: Number(limit)
|
|
474
508
|
});
|
|
475
|
-
return
|
|
509
|
+
return toToolResponse(cashflowGrowth);
|
|
476
510
|
}
|
|
477
511
|
});
|
|
478
512
|
var getIncomeGrowth = createOpenAITool({
|
|
@@ -490,7 +524,7 @@ var getIncomeGrowth = createOpenAITool({
|
|
|
490
524
|
period,
|
|
491
525
|
limit: Number(limit)
|
|
492
526
|
});
|
|
493
|
-
return
|
|
527
|
+
return toToolResponse(incomeGrowth);
|
|
494
528
|
}
|
|
495
529
|
});
|
|
496
530
|
var getBalanceSheetGrowth = createOpenAITool({
|
|
@@ -508,7 +542,7 @@ var getBalanceSheetGrowth = createOpenAITool({
|
|
|
508
542
|
period,
|
|
509
543
|
limit: Number(limit)
|
|
510
544
|
});
|
|
511
|
-
return
|
|
545
|
+
return toToolResponse(balanceSheetGrowth);
|
|
512
546
|
}
|
|
513
547
|
});
|
|
514
548
|
var getFinancialGrowth = createOpenAITool({
|
|
@@ -526,7 +560,7 @@ var getFinancialGrowth = createOpenAITool({
|
|
|
526
560
|
period,
|
|
527
561
|
limit: Number(limit)
|
|
528
562
|
});
|
|
529
|
-
return
|
|
563
|
+
return toToolResponse(financialGrowth);
|
|
530
564
|
}
|
|
531
565
|
});
|
|
532
566
|
var getEarningsHistorical = createOpenAITool({
|
|
@@ -542,7 +576,7 @@ var getEarningsHistorical = createOpenAITool({
|
|
|
542
576
|
symbol,
|
|
543
577
|
limit: Number(limit)
|
|
544
578
|
});
|
|
545
|
-
return
|
|
579
|
+
return toToolResponse(earningsHistorical);
|
|
546
580
|
}
|
|
547
581
|
});
|
|
548
582
|
var insiderTradingInputSchema = zod.z.object({
|
|
@@ -556,7 +590,7 @@ var getInsiderTrading = createOpenAITool({
|
|
|
556
590
|
execute: async ({ symbol, page }) => {
|
|
557
591
|
const fmp = getFMPClient();
|
|
558
592
|
const insiderTrading = await fmp.insider.getInsiderTradesBySymbol(symbol, page);
|
|
559
|
-
return
|
|
593
|
+
return toToolResponse(insiderTrading);
|
|
560
594
|
}
|
|
561
595
|
});
|
|
562
596
|
var institutionalHoldersInputSchema = zod.z.object({
|
|
@@ -569,7 +603,7 @@ var getInstitutionalHolders = createOpenAITool({
|
|
|
569
603
|
execute: async ({ symbol }) => {
|
|
570
604
|
const fmp = getFMPClient();
|
|
571
605
|
const institutionalHolders = await fmp.institutional.getInstitutionalHolders({ symbol });
|
|
572
|
-
return
|
|
606
|
+
return toToolResponse(institutionalHolders);
|
|
573
607
|
}
|
|
574
608
|
});
|
|
575
609
|
var emptyInputSchema = zod.z.object({});
|
|
@@ -580,7 +614,7 @@ var getMarketPerformance = createOpenAITool({
|
|
|
580
614
|
execute: async () => {
|
|
581
615
|
const fmp = getFMPClient();
|
|
582
616
|
const marketPerformance = await fmp.market.getMarketPerformance();
|
|
583
|
-
return
|
|
617
|
+
return toToolResponse(marketPerformance);
|
|
584
618
|
}
|
|
585
619
|
});
|
|
586
620
|
var getSectorPerformance = createOpenAITool({
|
|
@@ -590,7 +624,7 @@ var getSectorPerformance = createOpenAITool({
|
|
|
590
624
|
execute: async () => {
|
|
591
625
|
const fmp = getFMPClient();
|
|
592
626
|
const sectorPerformance = await fmp.market.getSectorPerformance();
|
|
593
|
-
return
|
|
627
|
+
return toToolResponse(sectorPerformance);
|
|
594
628
|
}
|
|
595
629
|
});
|
|
596
630
|
var getGainers = createOpenAITool({
|
|
@@ -600,7 +634,7 @@ var getGainers = createOpenAITool({
|
|
|
600
634
|
execute: async () => {
|
|
601
635
|
const fmp = getFMPClient();
|
|
602
636
|
const gainers = await fmp.market.getGainers();
|
|
603
|
-
return
|
|
637
|
+
return toToolResponse(gainers);
|
|
604
638
|
}
|
|
605
639
|
});
|
|
606
640
|
var getLosers = createOpenAITool({
|
|
@@ -610,7 +644,7 @@ var getLosers = createOpenAITool({
|
|
|
610
644
|
execute: async () => {
|
|
611
645
|
const fmp = getFMPClient();
|
|
612
646
|
const losers = await fmp.market.getLosers();
|
|
613
|
-
return
|
|
647
|
+
return toToolResponse(losers);
|
|
614
648
|
}
|
|
615
649
|
});
|
|
616
650
|
var getMostActive = createOpenAITool({
|
|
@@ -620,7 +654,7 @@ var getMostActive = createOpenAITool({
|
|
|
620
654
|
execute: async () => {
|
|
621
655
|
const fmp = getFMPClient();
|
|
622
656
|
const mostActive = await fmp.market.getMostActive();
|
|
623
|
-
return
|
|
657
|
+
return toToolResponse(mostActive);
|
|
624
658
|
}
|
|
625
659
|
});
|
|
626
660
|
var stockQuoteInputSchema = zod.z.object({
|
|
@@ -633,7 +667,7 @@ var getStockQuote = createOpenAITool({
|
|
|
633
667
|
execute: async ({ symbol }) => {
|
|
634
668
|
const fmp = getFMPClient();
|
|
635
669
|
const stockQuote = await fmp.quote.getQuote(symbol);
|
|
636
|
-
return
|
|
670
|
+
return toToolResponse(stockQuote);
|
|
637
671
|
}
|
|
638
672
|
});
|
|
639
673
|
var symbolInputSchema = zod.z.object({
|
|
@@ -652,7 +686,7 @@ var getSenateTrading = createOpenAITool({
|
|
|
652
686
|
execute: async ({ symbol }) => {
|
|
653
687
|
const fmp = getFMPClient();
|
|
654
688
|
const senateTrading = await fmp.senateHouse.getSenateTrading({ symbol });
|
|
655
|
-
return
|
|
689
|
+
return toToolResponse(senateTrading);
|
|
656
690
|
}
|
|
657
691
|
});
|
|
658
692
|
var getHouseTrading = createOpenAITool({
|
|
@@ -662,7 +696,7 @@ var getHouseTrading = createOpenAITool({
|
|
|
662
696
|
execute: async ({ symbol }) => {
|
|
663
697
|
const fmp = getFMPClient();
|
|
664
698
|
const houseTrading = await fmp.senateHouse.getHouseTrading({ symbol });
|
|
665
|
-
return
|
|
699
|
+
return toToolResponse(houseTrading);
|
|
666
700
|
}
|
|
667
701
|
});
|
|
668
702
|
var getSenateTradingByName = createOpenAITool({
|
|
@@ -672,7 +706,7 @@ var getSenateTradingByName = createOpenAITool({
|
|
|
672
706
|
execute: async ({ name }) => {
|
|
673
707
|
const fmp = getFMPClient();
|
|
674
708
|
const senateTradingByName = await fmp.senateHouse.getSenateTradingByName({ name });
|
|
675
|
-
return
|
|
709
|
+
return toToolResponse(senateTradingByName);
|
|
676
710
|
}
|
|
677
711
|
});
|
|
678
712
|
var getHouseTradingByName = createOpenAITool({
|
|
@@ -682,7 +716,7 @@ var getHouseTradingByName = createOpenAITool({
|
|
|
682
716
|
execute: async ({ name }) => {
|
|
683
717
|
const fmp = getFMPClient();
|
|
684
718
|
const houseTradingByName = await fmp.senateHouse.getHouseTradingByName({ name });
|
|
685
|
-
return
|
|
719
|
+
return toToolResponse(houseTradingByName);
|
|
686
720
|
}
|
|
687
721
|
});
|
|
688
722
|
var getSenateTradingRSSFeed = createOpenAITool({
|
|
@@ -692,7 +726,7 @@ var getSenateTradingRSSFeed = createOpenAITool({
|
|
|
692
726
|
execute: async ({ page }) => {
|
|
693
727
|
const fmp = getFMPClient();
|
|
694
728
|
const senateTradingRSSFeed = await fmp.senateHouse.getSenateTradingRSSFeed({ page });
|
|
695
|
-
return
|
|
729
|
+
return toToolResponse(senateTradingRSSFeed);
|
|
696
730
|
}
|
|
697
731
|
});
|
|
698
732
|
var getHouseTradingRSSFeed = createOpenAITool({
|
|
@@ -702,7 +736,7 @@ var getHouseTradingRSSFeed = createOpenAITool({
|
|
|
702
736
|
execute: async ({ page }) => {
|
|
703
737
|
const fmp = getFMPClient();
|
|
704
738
|
const houseTradingRSSFeed = await fmp.senateHouse.getHouseTradingRSSFeed({ page });
|
|
705
|
-
return
|
|
739
|
+
return toToolResponse(houseTradingRSSFeed);
|
|
706
740
|
}
|
|
707
741
|
});
|
|
708
742
|
var symbolInputSchema2 = zod.z.object({
|
|
@@ -715,7 +749,7 @@ var getMarketCap = createOpenAITool({
|
|
|
715
749
|
execute: async ({ symbol }) => {
|
|
716
750
|
const fmp = getFMPClient();
|
|
717
751
|
const marketCap = await fmp.stock.getMarketCap(symbol);
|
|
718
|
-
return
|
|
752
|
+
return toToolResponse(marketCap);
|
|
719
753
|
}
|
|
720
754
|
});
|
|
721
755
|
var getStockSplits = createOpenAITool({
|
|
@@ -725,7 +759,7 @@ var getStockSplits = createOpenAITool({
|
|
|
725
759
|
execute: async ({ symbol }) => {
|
|
726
760
|
const fmp = getFMPClient();
|
|
727
761
|
const stockSplits = await fmp.stock.getStockSplits(symbol);
|
|
728
|
-
return
|
|
762
|
+
return toToolResponse(stockSplits);
|
|
729
763
|
}
|
|
730
764
|
});
|
|
731
765
|
var getDividendHistory = createOpenAITool({
|
|
@@ -735,7 +769,7 @@ var getDividendHistory = createOpenAITool({
|
|
|
735
769
|
execute: async ({ symbol }) => {
|
|
736
770
|
const fmp = getFMPClient();
|
|
737
771
|
const dividendHistory = await fmp.stock.getDividendHistory(symbol);
|
|
738
|
-
return
|
|
772
|
+
return toToolResponse(dividendHistory);
|
|
739
773
|
}
|
|
740
774
|
});
|
|
741
775
|
|