tn-financial-data 0.1.1 → 0.1.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 +14 -2
- package/dist/cli.js +375 -10
- package/dist/client/index.d.ts +49 -26
- package/dist/client/index.js +68 -7
- package/package.json +1 -1
- package/skills/tn-financial-data/SKILL.md +2 -2
- package/skills/tn-financial-data/references/cli.md +1 -0
package/README.md
CHANGED
|
@@ -26,7 +26,7 @@ This package is the hosted agent-facing surface only. The repo's website, local
|
|
|
26
26
|
## Features
|
|
27
27
|
|
|
28
28
|
- Company facts, financials, prices, news, insider trades, ownership, and global rates through one hosted API
|
|
29
|
-
- Agent-friendly CLI with
|
|
29
|
+
- Agent-friendly CLI with clean error output, scoped subcommand help, and self-description via `tn-financial-data describe opencli`
|
|
30
30
|
- Packaged skill bundle for Claude and OpenCode installs
|
|
31
31
|
- Typed TypeScript client from the root package export
|
|
32
32
|
- Stable production default at `https://api.truenorth-financial.ai/v1`
|
|
@@ -135,6 +135,17 @@ tn-financial-data describe opencli
|
|
|
135
135
|
Installing the skill bundle does not provision API access. Agents still need the same runtime credential for live reads.
|
|
136
136
|
For OpenCode, that means the `opencode` process itself must see `TN_FINANCIAL_DATA_API_KEY` in its environment.
|
|
137
137
|
|
|
138
|
+
## Rate Limits
|
|
139
|
+
|
|
140
|
+
The hosted API returns standard rate-limit headers:
|
|
141
|
+
|
|
142
|
+
- `X-RateLimit-Limit`
|
|
143
|
+
- `X-RateLimit-Remaining`
|
|
144
|
+
- `X-RateLimit-Reset`
|
|
145
|
+
- `Retry-After` on `429`
|
|
146
|
+
|
|
147
|
+
When the CLI is throttled, it prints a clean retry message instead of a stack trace.
|
|
148
|
+
|
|
138
149
|
## Agent Integration
|
|
139
150
|
|
|
140
151
|
Agents only need two surfaces:
|
|
@@ -155,8 +166,9 @@ const client = new TnFinancialData({
|
|
|
155
166
|
apiKey: process.env.TN_FINANCIAL_DATA_API_KEY!,
|
|
156
167
|
});
|
|
157
168
|
|
|
158
|
-
const company = await client.getCompanyFacts(
|
|
169
|
+
const company = await client.getCompanyFacts("AAPL");
|
|
159
170
|
console.log(company.company_facts.name);
|
|
171
|
+
console.log(company._rateLimit);
|
|
160
172
|
```
|
|
161
173
|
|
|
162
174
|
## Package Scope
|
package/dist/cli.js
CHANGED
|
@@ -7,6 +7,43 @@ import { pathToFileURL } from "url";
|
|
|
7
7
|
|
|
8
8
|
// src/client/index.ts
|
|
9
9
|
var DEFAULT_API_BASE_URL = "https://api.truenorth-financial.ai/v1";
|
|
10
|
+
function parseOptionalInt(value) {
|
|
11
|
+
if (!value) {
|
|
12
|
+
return null;
|
|
13
|
+
}
|
|
14
|
+
const parsed = Number.parseInt(value, 10);
|
|
15
|
+
return Number.isFinite(parsed) ? parsed : null;
|
|
16
|
+
}
|
|
17
|
+
function parseOptionalUnixTimestamp(value) {
|
|
18
|
+
const parsed = parseOptionalInt(value);
|
|
19
|
+
if (parsed === null) {
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
return new Date(parsed * 1e3).toISOString();
|
|
23
|
+
}
|
|
24
|
+
function parseRateLimitInfo(headers) {
|
|
25
|
+
const info = {
|
|
26
|
+
limit: parseOptionalInt(headers.get("X-RateLimit-Limit")),
|
|
27
|
+
remaining: parseOptionalInt(headers.get("X-RateLimit-Remaining")),
|
|
28
|
+
resetAt: parseOptionalUnixTimestamp(headers.get("X-RateLimit-Reset")),
|
|
29
|
+
retryAfterSeconds: parseOptionalInt(headers.get("Retry-After"))
|
|
30
|
+
};
|
|
31
|
+
return Object.values(info).some((value) => value !== null) ? info : null;
|
|
32
|
+
}
|
|
33
|
+
var ApiError = class extends Error {
|
|
34
|
+
status;
|
|
35
|
+
code;
|
|
36
|
+
body;
|
|
37
|
+
rateLimit;
|
|
38
|
+
constructor(options) {
|
|
39
|
+
super(`API error ${options.status}: ${options.message}`);
|
|
40
|
+
this.name = "ApiError";
|
|
41
|
+
this.status = options.status;
|
|
42
|
+
this.code = options.code;
|
|
43
|
+
this.body = options.body;
|
|
44
|
+
this.rateLimit = options.rateLimit;
|
|
45
|
+
}
|
|
46
|
+
};
|
|
10
47
|
var TnFinancialData = class {
|
|
11
48
|
apiKey;
|
|
12
49
|
baseUrl;
|
|
@@ -27,21 +64,44 @@ var TnFinancialData = class {
|
|
|
27
64
|
headers
|
|
28
65
|
});
|
|
29
66
|
if (!res.ok) {
|
|
30
|
-
const
|
|
31
|
-
throw new
|
|
67
|
+
const errorBody = await this.extractErrorBody(res);
|
|
68
|
+
throw new ApiError({
|
|
69
|
+
status: res.status,
|
|
70
|
+
code: errorBody.code,
|
|
71
|
+
message: errorBody.message,
|
|
72
|
+
body: errorBody.rawBody,
|
|
73
|
+
rateLimit: parseRateLimitInfo(res.headers)
|
|
74
|
+
});
|
|
32
75
|
}
|
|
33
|
-
|
|
76
|
+
const payload = await res.json();
|
|
77
|
+
Object.defineProperty(payload, "_rateLimit", {
|
|
78
|
+
value: parseRateLimitInfo(res.headers),
|
|
79
|
+
enumerable: false,
|
|
80
|
+
configurable: true,
|
|
81
|
+
writable: false
|
|
82
|
+
});
|
|
83
|
+
return payload;
|
|
34
84
|
}
|
|
35
|
-
async
|
|
85
|
+
async extractErrorBody(res) {
|
|
36
86
|
const rawBody = await res.text().catch(() => "");
|
|
37
87
|
const trimmed = rawBody.trim();
|
|
38
|
-
if (trimmed.length === 0)
|
|
88
|
+
if (trimmed.length === 0) {
|
|
89
|
+
return { message: "Unknown error", code: null, rawBody: "" };
|
|
90
|
+
}
|
|
39
91
|
try {
|
|
40
92
|
const parsed = JSON.parse(trimmed);
|
|
41
93
|
const code = parsed.code ? `[${parsed.code}] ` : "";
|
|
42
|
-
return
|
|
94
|
+
return {
|
|
95
|
+
message: `${code}${parsed.error?.trim() || trimmed}`,
|
|
96
|
+
code: parsed.code?.trim() || null,
|
|
97
|
+
rawBody: trimmed
|
|
98
|
+
};
|
|
43
99
|
} catch {
|
|
44
|
-
return
|
|
100
|
+
return {
|
|
101
|
+
message: trimmed,
|
|
102
|
+
code: null,
|
|
103
|
+
rawBody: trimmed
|
|
104
|
+
};
|
|
45
105
|
}
|
|
46
106
|
}
|
|
47
107
|
appendLimitParam(params, limit) {
|
|
@@ -1124,6 +1184,273 @@ function buildOpenCliDocument() {
|
|
|
1124
1184
|
};
|
|
1125
1185
|
}
|
|
1126
1186
|
|
|
1187
|
+
// src/cli/query-subcommand-help.ts
|
|
1188
|
+
function renderHelp(command, description, options, example) {
|
|
1189
|
+
return [
|
|
1190
|
+
`tn-financial-data query ${command}`,
|
|
1191
|
+
"",
|
|
1192
|
+
...description,
|
|
1193
|
+
"",
|
|
1194
|
+
"Options:",
|
|
1195
|
+
...options.map((line) => ` ${line}`),
|
|
1196
|
+
"",
|
|
1197
|
+
"Example:",
|
|
1198
|
+
` ${example}`
|
|
1199
|
+
].join("\n");
|
|
1200
|
+
}
|
|
1201
|
+
var QUERY_SUBCOMMAND_HELP = {
|
|
1202
|
+
"available-tickers": renderHelp(
|
|
1203
|
+
"available-tickers",
|
|
1204
|
+
["List tickers currently supported by the hosted read API."],
|
|
1205
|
+
[
|
|
1206
|
+
"--api-key <key> API key. Overrides TN_FINANCIAL_DATA_API_KEY.",
|
|
1207
|
+
"--base-url <url> API base URL override."
|
|
1208
|
+
],
|
|
1209
|
+
"tn-financial-data query available-tickers"
|
|
1210
|
+
),
|
|
1211
|
+
company: renderHelp(
|
|
1212
|
+
"company",
|
|
1213
|
+
["Fetch the basic company identity record for a single ticker."],
|
|
1214
|
+
[
|
|
1215
|
+
"--ticker <symbol> Required. Stock ticker symbol.",
|
|
1216
|
+
"--api-key <key> API key. Overrides TN_FINANCIAL_DATA_API_KEY.",
|
|
1217
|
+
"--base-url <url> API base URL override."
|
|
1218
|
+
],
|
|
1219
|
+
"tn-financial-data query company --ticker AAPL"
|
|
1220
|
+
),
|
|
1221
|
+
"general-overview": renderHelp(
|
|
1222
|
+
"general-overview",
|
|
1223
|
+
["Fetch the bundled company, financials, price snapshot, and news overview for one ticker."],
|
|
1224
|
+
[
|
|
1225
|
+
"--ticker <symbol> Required. Stock ticker symbol.",
|
|
1226
|
+
"--period <period> annual | quarterly | ttm. Default: annual.",
|
|
1227
|
+
"--financial-limit <n> Number of financial periods to return.",
|
|
1228
|
+
"--news-limit <n> Number of news items to return.",
|
|
1229
|
+
"--api-key <key> API key. Overrides TN_FINANCIAL_DATA_API_KEY.",
|
|
1230
|
+
"--base-url <url> API base URL override."
|
|
1231
|
+
],
|
|
1232
|
+
"tn-financial-data query general-overview --ticker AAPL --period quarterly --financial-limit 4 --news-limit 5"
|
|
1233
|
+
),
|
|
1234
|
+
financials: renderHelp(
|
|
1235
|
+
"financials",
|
|
1236
|
+
[
|
|
1237
|
+
"Fetch income statements, balance sheets, cash flow statements, or key statistics for a single ticker."
|
|
1238
|
+
],
|
|
1239
|
+
[
|
|
1240
|
+
"--ticker <symbol> Required. Stock ticker symbol.",
|
|
1241
|
+
"--period <period> annual | quarterly | ttm. Required unless --statement key-stats.",
|
|
1242
|
+
"--statement <type> all | income | balance | cash-flow | key-stats. Default: all.",
|
|
1243
|
+
"--limit <n> Number of periods to return.",
|
|
1244
|
+
"--report-period <date> Exact report period (YYYY-MM-DD).",
|
|
1245
|
+
"--report-period-gte <date> Report period >= date.",
|
|
1246
|
+
"--report-period-lte <date> Report period <= date.",
|
|
1247
|
+
"--report-period-gt <date> Report period > date.",
|
|
1248
|
+
"--report-period-lt <date> Report period < date.",
|
|
1249
|
+
"--api-key <key> API key. Overrides TN_FINANCIAL_DATA_API_KEY.",
|
|
1250
|
+
"--base-url <url> API base URL override."
|
|
1251
|
+
],
|
|
1252
|
+
"tn-financial-data query financials --ticker AAPL --period annual --statement income --limit 4"
|
|
1253
|
+
),
|
|
1254
|
+
"financial-metrics": renderHelp(
|
|
1255
|
+
"financial-metrics",
|
|
1256
|
+
["Fetch derived profitability, leverage, liquidity, and growth metrics for a single ticker."],
|
|
1257
|
+
[
|
|
1258
|
+
"--ticker <symbol> Required. Stock ticker symbol.",
|
|
1259
|
+
"--period <period> annual | quarterly | ttm. Default: annual.",
|
|
1260
|
+
"--limit <n> Number of periods to return.",
|
|
1261
|
+
"--report-period <date> Exact report period (YYYY-MM-DD).",
|
|
1262
|
+
"--report-period-gte <date> Report period >= date.",
|
|
1263
|
+
"--report-period-lte <date> Report period <= date.",
|
|
1264
|
+
"--report-period-gt <date> Report period > date.",
|
|
1265
|
+
"--report-period-lt <date> Report period < date.",
|
|
1266
|
+
"--api-key <key> API key. Overrides TN_FINANCIAL_DATA_API_KEY.",
|
|
1267
|
+
"--base-url <url> API base URL override."
|
|
1268
|
+
],
|
|
1269
|
+
"tn-financial-data query financial-metrics --ticker AAPL --period quarterly --limit 8"
|
|
1270
|
+
),
|
|
1271
|
+
"financial-metrics-snapshot": renderHelp(
|
|
1272
|
+
"financial-metrics-snapshot",
|
|
1273
|
+
["Fetch the latest metrics bundle, price snapshot, and key statistics for one ticker."],
|
|
1274
|
+
[
|
|
1275
|
+
"--ticker <symbol> Required. Stock ticker symbol.",
|
|
1276
|
+
"--period <period> annual | quarterly | ttm. Default: annual.",
|
|
1277
|
+
"--api-key <key> API key. Overrides TN_FINANCIAL_DATA_API_KEY.",
|
|
1278
|
+
"--base-url <url> API base URL override."
|
|
1279
|
+
],
|
|
1280
|
+
"tn-financial-data query financial-metrics-snapshot --ticker AAPL --period quarterly"
|
|
1281
|
+
),
|
|
1282
|
+
earnings: renderHelp(
|
|
1283
|
+
"earnings",
|
|
1284
|
+
["Fetch reported earnings rows and consensus surprise fields for a single ticker."],
|
|
1285
|
+
[
|
|
1286
|
+
"--ticker <symbol> Required. Stock ticker symbol.",
|
|
1287
|
+
"--period <period> annual | quarterly | ttm. Default: quarterly.",
|
|
1288
|
+
"--limit <n> Number of periods to return.",
|
|
1289
|
+
"--report-period <date> Exact report period (YYYY-MM-DD).",
|
|
1290
|
+
"--report-period-gte <date> Report period >= date.",
|
|
1291
|
+
"--report-period-lte <date> Report period <= date.",
|
|
1292
|
+
"--report-period-gt <date> Report period > date.",
|
|
1293
|
+
"--report-period-lt <date> Report period < date.",
|
|
1294
|
+
"--api-key <key> API key. Overrides TN_FINANCIAL_DATA_API_KEY.",
|
|
1295
|
+
"--base-url <url> API base URL override."
|
|
1296
|
+
],
|
|
1297
|
+
"tn-financial-data query earnings --ticker AAPL --period quarterly --limit 8"
|
|
1298
|
+
),
|
|
1299
|
+
"quarterly-highlights": renderHelp(
|
|
1300
|
+
"quarterly-highlights",
|
|
1301
|
+
[
|
|
1302
|
+
"Fetch issuer-reported supplemental quarterly highlights such as segment mix and selected KPIs."
|
|
1303
|
+
],
|
|
1304
|
+
[
|
|
1305
|
+
"--ticker <symbol> Required. Stock ticker symbol.",
|
|
1306
|
+
"--report-period <date> Exact report period (YYYY-MM-DD).",
|
|
1307
|
+
"--api-key <key> API key. Overrides TN_FINANCIAL_DATA_API_KEY.",
|
|
1308
|
+
"--base-url <url> API base URL override."
|
|
1309
|
+
],
|
|
1310
|
+
"tn-financial-data query quarterly-highlights --ticker AAPL"
|
|
1311
|
+
),
|
|
1312
|
+
"analyst-estimates": renderHelp(
|
|
1313
|
+
"analyst-estimates",
|
|
1314
|
+
["Fetch analyst EPS/revenue estimate rows and the current price-target snapshot for a ticker."],
|
|
1315
|
+
[
|
|
1316
|
+
"--ticker <symbol> Required. Stock ticker symbol.",
|
|
1317
|
+
"--api-key <key> API key. Overrides TN_FINANCIAL_DATA_API_KEY.",
|
|
1318
|
+
"--base-url <url> API base URL override."
|
|
1319
|
+
],
|
|
1320
|
+
"tn-financial-data query analyst-estimates --ticker AAPL"
|
|
1321
|
+
),
|
|
1322
|
+
prices: renderHelp(
|
|
1323
|
+
"prices",
|
|
1324
|
+
["Fetch historical price bars for a single ticker."],
|
|
1325
|
+
[
|
|
1326
|
+
"--ticker <symbol> Required. Stock ticker symbol.",
|
|
1327
|
+
"--interval <period> day | 1h.",
|
|
1328
|
+
"--start-date <date> Required. Start date (YYYY-MM-DD).",
|
|
1329
|
+
"--end-date <date> Required. End date (YYYY-MM-DD).",
|
|
1330
|
+
"--api-key <key> API key. Overrides TN_FINANCIAL_DATA_API_KEY.",
|
|
1331
|
+
"--base-url <url> API base URL override."
|
|
1332
|
+
],
|
|
1333
|
+
"tn-financial-data query prices --ticker AAPL --interval day --start-date 2025-01-01 --end-date 2025-01-31"
|
|
1334
|
+
),
|
|
1335
|
+
snapshot: renderHelp(
|
|
1336
|
+
"snapshot",
|
|
1337
|
+
["Fetch the latest price snapshot for a single ticker."],
|
|
1338
|
+
[
|
|
1339
|
+
"--ticker <symbol> Required. Stock ticker symbol.",
|
|
1340
|
+
"--api-key <key> API key. Overrides TN_FINANCIAL_DATA_API_KEY.",
|
|
1341
|
+
"--base-url <url> API base URL override."
|
|
1342
|
+
],
|
|
1343
|
+
"tn-financial-data query snapshot --ticker AAPL"
|
|
1344
|
+
),
|
|
1345
|
+
news: renderHelp(
|
|
1346
|
+
"news",
|
|
1347
|
+
["Fetch curated issuer news for a single ticker."],
|
|
1348
|
+
[
|
|
1349
|
+
"--ticker <symbol> Required. Stock ticker symbol.",
|
|
1350
|
+
"--start-date <date> Optional start date (YYYY-MM-DD).",
|
|
1351
|
+
"--end-date <date> Optional end date (YYYY-MM-DD).",
|
|
1352
|
+
"--publisher <name> Optional publisher filter.",
|
|
1353
|
+
"--limit <n> Number of articles to return.",
|
|
1354
|
+
"--api-key <key> API key. Overrides TN_FINANCIAL_DATA_API_KEY.",
|
|
1355
|
+
"--base-url <url> API base URL override."
|
|
1356
|
+
],
|
|
1357
|
+
"tn-financial-data query news --ticker AAPL --limit 10"
|
|
1358
|
+
),
|
|
1359
|
+
"insider-trades": renderHelp(
|
|
1360
|
+
"insider-trades",
|
|
1361
|
+
["Fetch SEC Form 4 insider-trade rows for a single issuer."],
|
|
1362
|
+
[
|
|
1363
|
+
"--ticker <symbol> Required. Stock ticker symbol.",
|
|
1364
|
+
"--start-date <date> Optional start date (YYYY-MM-DD).",
|
|
1365
|
+
"--end-date <date> Optional end date (YYYY-MM-DD).",
|
|
1366
|
+
"--reporting-owner-cik <cik> Optional reporting owner filter.",
|
|
1367
|
+
"--transaction-code <csv> Optional comma-separated transaction codes.",
|
|
1368
|
+
"--security-type <type> all | non_derivative | derivative.",
|
|
1369
|
+
"--limit <n> Number of rows to return.",
|
|
1370
|
+
"--api-key <key> API key. Overrides TN_FINANCIAL_DATA_API_KEY.",
|
|
1371
|
+
"--base-url <url> API base URL override."
|
|
1372
|
+
],
|
|
1373
|
+
"tn-financial-data query insider-trades --ticker AAPL --transaction-code P,S --limit 25"
|
|
1374
|
+
),
|
|
1375
|
+
"institutional-ownership": renderHelp(
|
|
1376
|
+
"institutional-ownership",
|
|
1377
|
+
["Fetch issuer-centric institutional holder rows for a single ticker."],
|
|
1378
|
+
[
|
|
1379
|
+
"--ticker <symbol> Required. Stock ticker symbol.",
|
|
1380
|
+
"--limit <n> Number of holder rows to return.",
|
|
1381
|
+
"--api-key <key> API key. Overrides TN_FINANCIAL_DATA_API_KEY.",
|
|
1382
|
+
"--base-url <url> API base URL override."
|
|
1383
|
+
],
|
|
1384
|
+
"tn-financial-data query institutional-ownership --ticker AAPL --limit 20"
|
|
1385
|
+
),
|
|
1386
|
+
"investor-portfolio": renderHelp(
|
|
1387
|
+
"investor-portfolio",
|
|
1388
|
+
["Fetch investor-centric SEC 13F holdings by filer CIK or known investor alias."],
|
|
1389
|
+
[
|
|
1390
|
+
"--cik <cik> SEC filer CIK.",
|
|
1391
|
+
"--investor <id> Known investor alias such as vanguard.",
|
|
1392
|
+
"--limit <n> Number of holdings to return.",
|
|
1393
|
+
"--api-key <key> API key. Overrides TN_FINANCIAL_DATA_API_KEY.",
|
|
1394
|
+
"--base-url <url> API base URL override."
|
|
1395
|
+
],
|
|
1396
|
+
"tn-financial-data query investor-portfolio --investor vanguard --limit 20"
|
|
1397
|
+
),
|
|
1398
|
+
"global-rates": renderHelp(
|
|
1399
|
+
"global-rates",
|
|
1400
|
+
["Fetch curated global policy and money-market rate series."],
|
|
1401
|
+
[
|
|
1402
|
+
"--series <csv> Optional comma-separated series keys.",
|
|
1403
|
+
"--start-date <date> Optional start date (YYYY-MM-DD).",
|
|
1404
|
+
"--end-date <date> Optional end date (YYYY-MM-DD).",
|
|
1405
|
+
"--limit <n> Number of observations to return per series.",
|
|
1406
|
+
"--api-key <key> API key. Overrides TN_FINANCIAL_DATA_API_KEY.",
|
|
1407
|
+
"--base-url <url> API base URL override."
|
|
1408
|
+
],
|
|
1409
|
+
"tn-financial-data query global-rates --series ecb_refi,boe_sonia --limit 10"
|
|
1410
|
+
),
|
|
1411
|
+
"segmented-revenues": renderHelp(
|
|
1412
|
+
"segmented-revenues",
|
|
1413
|
+
["Fetch reported segment revenue rows for a single issuer."],
|
|
1414
|
+
[
|
|
1415
|
+
"--ticker <symbol> Required. Stock ticker symbol.",
|
|
1416
|
+
"--period <period> annual | quarterly | ttm.",
|
|
1417
|
+
"--limit <n> Number of periods to return.",
|
|
1418
|
+
"--segment-type <type> Optional segment type filter.",
|
|
1419
|
+
"--report-period <date> Exact report period (YYYY-MM-DD).",
|
|
1420
|
+
"--report-period-gte <date> Report period >= date.",
|
|
1421
|
+
"--report-period-lte <date> Report period <= date.",
|
|
1422
|
+
"--report-period-gt <date> Report period > date.",
|
|
1423
|
+
"--report-period-lt <date> Report period < date.",
|
|
1424
|
+
"--api-key <key> API key. Overrides TN_FINANCIAL_DATA_API_KEY.",
|
|
1425
|
+
"--base-url <url> API base URL override."
|
|
1426
|
+
],
|
|
1427
|
+
"tn-financial-data query segmented-revenues --ticker AAPL --period quarterly --limit 4"
|
|
1428
|
+
),
|
|
1429
|
+
screen: renderHelp(
|
|
1430
|
+
"screen",
|
|
1431
|
+
["Run the hosted equity screener with one or more filter expressions."],
|
|
1432
|
+
[
|
|
1433
|
+
'--filter "field operator value" Required. Repeat for multiple filters.',
|
|
1434
|
+
"--limit <n> Number of rows to return.",
|
|
1435
|
+
"--api-key <key> API key. Overrides TN_FINANCIAL_DATA_API_KEY.",
|
|
1436
|
+
"--base-url <url> API base URL override."
|
|
1437
|
+
],
|
|
1438
|
+
'tn-financial-data query screen --filter "trailing_pe < 25" --filter "recommendation_key = buy" --limit 10'
|
|
1439
|
+
),
|
|
1440
|
+
"screen-fields": renderHelp(
|
|
1441
|
+
"screen-fields",
|
|
1442
|
+
["List the supported screener fields and operator metadata."],
|
|
1443
|
+
[
|
|
1444
|
+
"--api-key <key> API key. Overrides TN_FINANCIAL_DATA_API_KEY.",
|
|
1445
|
+
"--base-url <url> API base URL override."
|
|
1446
|
+
],
|
|
1447
|
+
"tn-financial-data query screen-fields"
|
|
1448
|
+
)
|
|
1449
|
+
};
|
|
1450
|
+
function getQuerySubcommandHelp(resource) {
|
|
1451
|
+
return QUERY_SUBCOMMAND_HELP[resource] ?? null;
|
|
1452
|
+
}
|
|
1453
|
+
|
|
1127
1454
|
// src/cli/skill.ts
|
|
1128
1455
|
import { cpSync, existsSync as existsSync2, mkdirSync, readFileSync as readFileSync2, rmSync } from "fs";
|
|
1129
1456
|
import { homedir as defaultHomedir } from "os";
|
|
@@ -1224,6 +1551,23 @@ function installSkill(options = {}) {
|
|
|
1224
1551
|
// src/cli/index.ts
|
|
1225
1552
|
var CliUsageError = class extends Error {
|
|
1226
1553
|
};
|
|
1554
|
+
function isCliDebugEnabled(runtime) {
|
|
1555
|
+
const debug = runtime.env.DEBUG?.trim().toLowerCase();
|
|
1556
|
+
return debug === "1" || debug === "true" || debug === "tn-financial-data";
|
|
1557
|
+
}
|
|
1558
|
+
function formatRateLimitError(error) {
|
|
1559
|
+
const retryAfterSeconds = error.rateLimit?.retryAfterSeconds;
|
|
1560
|
+
const remaining = error.rateLimit?.remaining;
|
|
1561
|
+
const limit = error.rateLimit?.limit;
|
|
1562
|
+
const segments = ["Rate limit exceeded."];
|
|
1563
|
+
if (remaining !== null && remaining !== void 0 && limit !== null && limit !== void 0) {
|
|
1564
|
+
segments.push(`${remaining}/${limit} requests remaining.`);
|
|
1565
|
+
}
|
|
1566
|
+
if (retryAfterSeconds !== null && retryAfterSeconds !== void 0) {
|
|
1567
|
+
segments.push(`Retry after ${retryAfterSeconds} seconds.`);
|
|
1568
|
+
}
|
|
1569
|
+
return segments.join(" ");
|
|
1570
|
+
}
|
|
1227
1571
|
function logCliErrorDetails(runtime, error, prefix = "") {
|
|
1228
1572
|
runtime.stderr(`${prefix}${error.message}`);
|
|
1229
1573
|
const pgLikeError = error;
|
|
@@ -1252,12 +1596,29 @@ function logCliError(runtime, error) {
|
|
|
1252
1596
|
runtime.stderr("Unknown CLI error.");
|
|
1253
1597
|
return;
|
|
1254
1598
|
}
|
|
1255
|
-
if (
|
|
1599
|
+
if (!isCliDebugEnabled(runtime)) {
|
|
1600
|
+
if (error instanceof CliUsageError) {
|
|
1601
|
+
runtime.stderr(error.message);
|
|
1602
|
+
return;
|
|
1603
|
+
}
|
|
1604
|
+
if (error instanceof ApiError && error.status === 429) {
|
|
1605
|
+
runtime.stderr(formatRateLimitError(error));
|
|
1606
|
+
return;
|
|
1607
|
+
}
|
|
1256
1608
|
runtime.stderr(error.message);
|
|
1257
1609
|
return;
|
|
1258
1610
|
}
|
|
1259
1611
|
logCliErrorDetails(runtime, error);
|
|
1260
1612
|
}
|
|
1613
|
+
function getCliExitCode(error) {
|
|
1614
|
+
if (error instanceof CliUsageError) {
|
|
1615
|
+
return 2;
|
|
1616
|
+
}
|
|
1617
|
+
if (error instanceof ApiError && error.status === 400) {
|
|
1618
|
+
return 2;
|
|
1619
|
+
}
|
|
1620
|
+
return 1;
|
|
1621
|
+
}
|
|
1261
1622
|
function createRuntime(overrides = {}) {
|
|
1262
1623
|
return {
|
|
1263
1624
|
stdout: overrides.stdout ?? ((line) => process.stdout.write(`${line}
|
|
@@ -1613,10 +1974,14 @@ function buildFinancialCliOptions(parsed, statement) {
|
|
|
1613
1974
|
}
|
|
1614
1975
|
async function handleQuery(parsed, runtime) {
|
|
1615
1976
|
const resource = parsed.positionals[1];
|
|
1616
|
-
if (!resource
|
|
1977
|
+
if (!resource) {
|
|
1617
1978
|
runtime.stdout(queryHelp());
|
|
1618
1979
|
return 0;
|
|
1619
1980
|
}
|
|
1981
|
+
if (hasOption(parsed, "help")) {
|
|
1982
|
+
runtime.stdout(getQuerySubcommandHelp(resource) ?? queryHelp());
|
|
1983
|
+
return 0;
|
|
1984
|
+
}
|
|
1620
1985
|
const client = createClient(parsed, runtime);
|
|
1621
1986
|
switch (resource) {
|
|
1622
1987
|
case "available-tickers":
|
|
@@ -2029,7 +2394,7 @@ async function runCli(argv, runtimeOverrides = {}) {
|
|
|
2029
2394
|
}
|
|
2030
2395
|
} catch (error) {
|
|
2031
2396
|
logCliError(runtime, error);
|
|
2032
|
-
return error
|
|
2397
|
+
return getCliExitCode(error);
|
|
2033
2398
|
}
|
|
2034
2399
|
}
|
|
2035
2400
|
function isMainModule() {
|
package/dist/client/index.d.ts
CHANGED
|
@@ -250,6 +250,12 @@ interface ClientOptions {
|
|
|
250
250
|
baseUrl?: string;
|
|
251
251
|
fetch?: typeof fetch;
|
|
252
252
|
}
|
|
253
|
+
interface RateLimitInfo {
|
|
254
|
+
limit: number | null;
|
|
255
|
+
remaining: number | null;
|
|
256
|
+
resetAt: string | null;
|
|
257
|
+
retryAfterSeconds: number | null;
|
|
258
|
+
}
|
|
253
259
|
type SnakeCase<T extends string> = T extends `${infer Head}${infer Tail}` ? Tail extends Uncapitalize<Tail> ? `${Lowercase<Head>}${SnakeCase<Tail>}` : `${Lowercase<Head>}_${SnakeCase<Tail>}` : T;
|
|
254
260
|
type SnakeCasedProperties<T> = {
|
|
255
261
|
[Key in keyof T as Key extends string ? SnakeCase<Key> : Key]: T[Key];
|
|
@@ -701,14 +707,31 @@ interface ScreenerResponse {
|
|
|
701
707
|
filters_applied: ScreenerFilter[];
|
|
702
708
|
results: ScreenerResultRow[];
|
|
703
709
|
}
|
|
710
|
+
interface RateLimitAnnotatedResponse {
|
|
711
|
+
_rateLimit?: RateLimitInfo | null;
|
|
712
|
+
}
|
|
713
|
+
type ApiResponse<T extends object> = T & RateLimitAnnotatedResponse;
|
|
704
714
|
declare const DEFAULT_API_BASE_URL = "https://api.truenorth-financial.ai/v1";
|
|
715
|
+
declare class ApiError extends Error {
|
|
716
|
+
readonly status: number;
|
|
717
|
+
readonly code: string | null;
|
|
718
|
+
readonly body: string;
|
|
719
|
+
readonly rateLimit: RateLimitInfo | null;
|
|
720
|
+
constructor(options: {
|
|
721
|
+
status: number;
|
|
722
|
+
code: string | null;
|
|
723
|
+
message: string;
|
|
724
|
+
body: string;
|
|
725
|
+
rateLimit: RateLimitInfo | null;
|
|
726
|
+
});
|
|
727
|
+
}
|
|
705
728
|
declare class TnFinancialData {
|
|
706
729
|
private apiKey;
|
|
707
730
|
private baseUrl;
|
|
708
731
|
private fetchFn;
|
|
709
732
|
constructor(opts: ClientOptions);
|
|
710
733
|
private request;
|
|
711
|
-
private
|
|
734
|
+
private extractErrorBody;
|
|
712
735
|
private appendLimitParam;
|
|
713
736
|
private appendReportPeriodParams;
|
|
714
737
|
private buildFinancialParams;
|
|
@@ -717,31 +740,31 @@ declare class TnFinancialData {
|
|
|
717
740
|
private buildSegmentedRevenueParams;
|
|
718
741
|
private buildQuarterlyHighlightsParams;
|
|
719
742
|
private buildInsiderTradeParams;
|
|
720
|
-
getIncomeStatements(ticker: string, opts: FinancialOpts): Promise<IncomeStatementsResponse
|
|
721
|
-
getBalanceSheets(ticker: string, opts: FinancialOpts): Promise<BalanceSheetsResponse
|
|
722
|
-
getCashFlowStatements(ticker: string, opts: FinancialOpts): Promise<CashFlowStatementsResponse
|
|
723
|
-
getFinancials(ticker: string, opts: FinancialOpts): Promise<FinancialsResponse
|
|
724
|
-
getFinancialMetrics(ticker: string, opts?: FinancialMetricsOpts): Promise<FinancialMetricsResponse
|
|
725
|
-
getFinancialMetricsSnapshot(ticker: string, opts?: Pick<FinancialMetricsOpts, "period">): Promise<FinancialMetricsSnapshotResponse
|
|
726
|
-
getEarnings(ticker: string, opts?: EarningsOpts): Promise<EarningsResponse
|
|
727
|
-
getGeneralOverview(ticker: string, opts?: GeneralOverviewOpts): Promise<GeneralOverviewResponse
|
|
728
|
-
getKeyStatistics(ticker: string): Promise<KeyStatisticsResponse
|
|
729
|
-
getAvailableTickers(): Promise<AvailableTickersResponse
|
|
730
|
-
getPrices(ticker: string, opts: PriceOpts): Promise<PriceHistoryResponse
|
|
731
|
-
getPriceSnapshot(ticker: string): Promise<PriceSnapshotResponse
|
|
732
|
-
getNews(ticker: string, opts?: NewsOpts): Promise<NewsResponse
|
|
733
|
-
getInsiderTrades(ticker: string, opts?: InsiderTradesOpts): Promise<InsiderTradesResponse
|
|
734
|
-
getInstitutionalOwnership(ticker: string, opts?: InstitutionalOwnershipOpts): Promise<InstitutionalOwnershipResponse
|
|
735
|
-
getInvestorPortfolio(opts: InvestorPortfolioOpts): Promise<InvestorPortfolioResponse
|
|
736
|
-
getGlobalInterestRates(opts?: GlobalInterestRatesOpts): Promise<GlobalInterestRatesResponse
|
|
737
|
-
getAnalystEstimates(ticker: string): Promise<AnalystEstimatesResponse
|
|
738
|
-
getCompanyFacts(ticker: string): Promise<{
|
|
743
|
+
getIncomeStatements(ticker: string, opts: FinancialOpts): Promise<ApiResponse<IncomeStatementsResponse>>;
|
|
744
|
+
getBalanceSheets(ticker: string, opts: FinancialOpts): Promise<ApiResponse<BalanceSheetsResponse>>;
|
|
745
|
+
getCashFlowStatements(ticker: string, opts: FinancialOpts): Promise<ApiResponse<CashFlowStatementsResponse>>;
|
|
746
|
+
getFinancials(ticker: string, opts: FinancialOpts): Promise<ApiResponse<FinancialsResponse>>;
|
|
747
|
+
getFinancialMetrics(ticker: string, opts?: FinancialMetricsOpts): Promise<ApiResponse<FinancialMetricsResponse>>;
|
|
748
|
+
getFinancialMetricsSnapshot(ticker: string, opts?: Pick<FinancialMetricsOpts, "period">): Promise<ApiResponse<FinancialMetricsSnapshotResponse>>;
|
|
749
|
+
getEarnings(ticker: string, opts?: EarningsOpts): Promise<ApiResponse<EarningsResponse>>;
|
|
750
|
+
getGeneralOverview(ticker: string, opts?: GeneralOverviewOpts): Promise<ApiResponse<GeneralOverviewResponse>>;
|
|
751
|
+
getKeyStatistics(ticker: string): Promise<ApiResponse<KeyStatisticsResponse>>;
|
|
752
|
+
getAvailableTickers(): Promise<ApiResponse<AvailableTickersResponse>>;
|
|
753
|
+
getPrices(ticker: string, opts: PriceOpts): Promise<ApiResponse<PriceHistoryResponse>>;
|
|
754
|
+
getPriceSnapshot(ticker: string): Promise<ApiResponse<PriceSnapshotResponse>>;
|
|
755
|
+
getNews(ticker: string, opts?: NewsOpts): Promise<ApiResponse<NewsResponse>>;
|
|
756
|
+
getInsiderTrades(ticker: string, opts?: InsiderTradesOpts): Promise<ApiResponse<InsiderTradesResponse>>;
|
|
757
|
+
getInstitutionalOwnership(ticker: string, opts?: InstitutionalOwnershipOpts): Promise<ApiResponse<InstitutionalOwnershipResponse>>;
|
|
758
|
+
getInvestorPortfolio(opts: InvestorPortfolioOpts): Promise<ApiResponse<InvestorPortfolioResponse>>;
|
|
759
|
+
getGlobalInterestRates(opts?: GlobalInterestRatesOpts): Promise<ApiResponse<GlobalInterestRatesResponse>>;
|
|
760
|
+
getAnalystEstimates(ticker: string): Promise<ApiResponse<AnalystEstimatesResponse>>;
|
|
761
|
+
getCompanyFacts(ticker: string): Promise<ApiResponse<{
|
|
739
762
|
company_facts: CompanyFacts;
|
|
740
|
-
}
|
|
741
|
-
getSegmentedRevenues(ticker: string, opts: SegmentedRevenuesOpts): Promise<SegmentedRevenuesResponse
|
|
742
|
-
getQuarterlyHighlights(ticker: string, opts?: QuarterlyHighlightsOpts): Promise<QuarterlyHighlightsResponse
|
|
743
|
-
getScreenerFields(): Promise<ScreenerFieldsResponse
|
|
744
|
-
screen(request: ScreenerRequest): Promise<ScreenerResponse
|
|
763
|
+
}>>;
|
|
764
|
+
getSegmentedRevenues(ticker: string, opts: SegmentedRevenuesOpts): Promise<ApiResponse<SegmentedRevenuesResponse>>;
|
|
765
|
+
getQuarterlyHighlights(ticker: string, opts?: QuarterlyHighlightsOpts): Promise<ApiResponse<QuarterlyHighlightsResponse>>;
|
|
766
|
+
getScreenerFields(): Promise<ApiResponse<ScreenerFieldsResponse>>;
|
|
767
|
+
screen(request: ScreenerRequest): Promise<ApiResponse<ScreenerResponse>>;
|
|
745
768
|
}
|
|
746
769
|
|
|
747
|
-
export { type AnalystEstimate, type AnalystEstimatesResponse, type AnalystPriceTarget, type AvailableTicker, type AvailableTickersResponse, type BalanceSheet, type BalanceSheetsResponse, type CashFlowStatement, type CashFlowStatementsResponse, type ClientOptions, type CompanyFacts, type ConsensusSurprise, DEFAULT_API_BASE_URL, type DataAvailability, type EarningsOpts, type EarningsResponse, type EarningsRow, type FinancialMetric, type FinancialMetricsOpts, type FinancialMetricsResponse, type FinancialMetricsSnapshotResponse, type FinancialOpts, type FinancialsResponse, type GeneralOverviewFinancials, type GeneralOverviewNews, type GeneralOverviewOpts, type GeneralOverviewPriceSnapshot, type GeneralOverviewResponse, type GlobalInterestRateObservation, type GlobalInterestRateSeries, type GlobalInterestRatesOpts, type GlobalInterestRatesResponse, type IncomeStatement, type IncomeStatementsResponse, type InsiderTrade, type InsiderTradesOpts, type InsiderTradesResponse, type InstitutionalOwnershipEntry, type InstitutionalOwnershipOpts, type InstitutionalOwnershipResponse, type InvestorPortfolioHolding, type InvestorPortfolioInvestor, type InvestorPortfolioOpts, type InvestorPortfolioResponse, type InvestorPortfolioSummary, type KeyStatistics, type KeyStatisticsResponse, type NewsArticle, type NewsOpts, type NewsResponse, type OptionalFinancialQueryOpts, type PriceBar, type PriceHistoryResponse, type PriceOpts, type PriceSnapshot, type PriceSnapshotResponse, type QuarterlyHighlightsMetric, type QuarterlyHighlightsOpts, type QuarterlyHighlightsPayload, type QuarterlyHighlightsResponse, type ReadMetadata, type ReportPeriodFilterOpts, type ScreenerFieldMetadata, type ScreenerFieldsResponse, type ScreenerRequest, type ScreenerResponse, type ScreenerResultRow, type SegmentedRevenueItem, type SegmentedRevenuePeriod, type SegmentedRevenuesOpts, type SegmentedRevenuesResponse, type SnakeCase, TnFinancialData };
|
|
770
|
+
export { type AnalystEstimate, type AnalystEstimatesResponse, type AnalystPriceTarget, ApiError, type ApiResponse, type AvailableTicker, type AvailableTickersResponse, type BalanceSheet, type BalanceSheetsResponse, type CashFlowStatement, type CashFlowStatementsResponse, type ClientOptions, type CompanyFacts, type ConsensusSurprise, DEFAULT_API_BASE_URL, type DataAvailability, type EarningsOpts, type EarningsResponse, type EarningsRow, type FinancialMetric, type FinancialMetricsOpts, type FinancialMetricsResponse, type FinancialMetricsSnapshotResponse, type FinancialOpts, type FinancialsResponse, type GeneralOverviewFinancials, type GeneralOverviewNews, type GeneralOverviewOpts, type GeneralOverviewPriceSnapshot, type GeneralOverviewResponse, type GlobalInterestRateObservation, type GlobalInterestRateSeries, type GlobalInterestRatesOpts, type GlobalInterestRatesResponse, type IncomeStatement, type IncomeStatementsResponse, type InsiderTrade, type InsiderTradesOpts, type InsiderTradesResponse, type InstitutionalOwnershipEntry, type InstitutionalOwnershipOpts, type InstitutionalOwnershipResponse, type InvestorPortfolioHolding, type InvestorPortfolioInvestor, type InvestorPortfolioOpts, type InvestorPortfolioResponse, type InvestorPortfolioSummary, type KeyStatistics, type KeyStatisticsResponse, type NewsArticle, type NewsOpts, type NewsResponse, type OptionalFinancialQueryOpts, type PriceBar, type PriceHistoryResponse, type PriceOpts, type PriceSnapshot, type PriceSnapshotResponse, type QuarterlyHighlightsMetric, type QuarterlyHighlightsOpts, type QuarterlyHighlightsPayload, type QuarterlyHighlightsResponse, type RateLimitAnnotatedResponse, type RateLimitInfo, type ReadMetadata, type ReportPeriodFilterOpts, type ScreenerFieldMetadata, type ScreenerFieldsResponse, type ScreenerRequest, type ScreenerResponse, type ScreenerResultRow, type SegmentedRevenueItem, type SegmentedRevenuePeriod, type SegmentedRevenuesOpts, type SegmentedRevenuesResponse, type SnakeCase, TnFinancialData };
|
package/dist/client/index.js
CHANGED
|
@@ -1,5 +1,42 @@
|
|
|
1
1
|
// src/client/index.ts
|
|
2
2
|
var DEFAULT_API_BASE_URL = "https://api.truenorth-financial.ai/v1";
|
|
3
|
+
function parseOptionalInt(value) {
|
|
4
|
+
if (!value) {
|
|
5
|
+
return null;
|
|
6
|
+
}
|
|
7
|
+
const parsed = Number.parseInt(value, 10);
|
|
8
|
+
return Number.isFinite(parsed) ? parsed : null;
|
|
9
|
+
}
|
|
10
|
+
function parseOptionalUnixTimestamp(value) {
|
|
11
|
+
const parsed = parseOptionalInt(value);
|
|
12
|
+
if (parsed === null) {
|
|
13
|
+
return null;
|
|
14
|
+
}
|
|
15
|
+
return new Date(parsed * 1e3).toISOString();
|
|
16
|
+
}
|
|
17
|
+
function parseRateLimitInfo(headers) {
|
|
18
|
+
const info = {
|
|
19
|
+
limit: parseOptionalInt(headers.get("X-RateLimit-Limit")),
|
|
20
|
+
remaining: parseOptionalInt(headers.get("X-RateLimit-Remaining")),
|
|
21
|
+
resetAt: parseOptionalUnixTimestamp(headers.get("X-RateLimit-Reset")),
|
|
22
|
+
retryAfterSeconds: parseOptionalInt(headers.get("Retry-After"))
|
|
23
|
+
};
|
|
24
|
+
return Object.values(info).some((value) => value !== null) ? info : null;
|
|
25
|
+
}
|
|
26
|
+
var ApiError = class extends Error {
|
|
27
|
+
status;
|
|
28
|
+
code;
|
|
29
|
+
body;
|
|
30
|
+
rateLimit;
|
|
31
|
+
constructor(options) {
|
|
32
|
+
super(`API error ${options.status}: ${options.message}`);
|
|
33
|
+
this.name = "ApiError";
|
|
34
|
+
this.status = options.status;
|
|
35
|
+
this.code = options.code;
|
|
36
|
+
this.body = options.body;
|
|
37
|
+
this.rateLimit = options.rateLimit;
|
|
38
|
+
}
|
|
39
|
+
};
|
|
3
40
|
var TnFinancialData = class {
|
|
4
41
|
apiKey;
|
|
5
42
|
baseUrl;
|
|
@@ -20,21 +57,44 @@ var TnFinancialData = class {
|
|
|
20
57
|
headers
|
|
21
58
|
});
|
|
22
59
|
if (!res.ok) {
|
|
23
|
-
const
|
|
24
|
-
throw new
|
|
60
|
+
const errorBody = await this.extractErrorBody(res);
|
|
61
|
+
throw new ApiError({
|
|
62
|
+
status: res.status,
|
|
63
|
+
code: errorBody.code,
|
|
64
|
+
message: errorBody.message,
|
|
65
|
+
body: errorBody.rawBody,
|
|
66
|
+
rateLimit: parseRateLimitInfo(res.headers)
|
|
67
|
+
});
|
|
25
68
|
}
|
|
26
|
-
|
|
69
|
+
const payload = await res.json();
|
|
70
|
+
Object.defineProperty(payload, "_rateLimit", {
|
|
71
|
+
value: parseRateLimitInfo(res.headers),
|
|
72
|
+
enumerable: false,
|
|
73
|
+
configurable: true,
|
|
74
|
+
writable: false
|
|
75
|
+
});
|
|
76
|
+
return payload;
|
|
27
77
|
}
|
|
28
|
-
async
|
|
78
|
+
async extractErrorBody(res) {
|
|
29
79
|
const rawBody = await res.text().catch(() => "");
|
|
30
80
|
const trimmed = rawBody.trim();
|
|
31
|
-
if (trimmed.length === 0)
|
|
81
|
+
if (trimmed.length === 0) {
|
|
82
|
+
return { message: "Unknown error", code: null, rawBody: "" };
|
|
83
|
+
}
|
|
32
84
|
try {
|
|
33
85
|
const parsed = JSON.parse(trimmed);
|
|
34
86
|
const code = parsed.code ? `[${parsed.code}] ` : "";
|
|
35
|
-
return
|
|
87
|
+
return {
|
|
88
|
+
message: `${code}${parsed.error?.trim() || trimmed}`,
|
|
89
|
+
code: parsed.code?.trim() || null,
|
|
90
|
+
rawBody: trimmed
|
|
91
|
+
};
|
|
36
92
|
} catch {
|
|
37
|
-
return
|
|
93
|
+
return {
|
|
94
|
+
message: trimmed,
|
|
95
|
+
code: null,
|
|
96
|
+
rawBody: trimmed
|
|
97
|
+
};
|
|
38
98
|
}
|
|
39
99
|
}
|
|
40
100
|
appendLimitParam(params, limit) {
|
|
@@ -223,6 +283,7 @@ var TnFinancialData = class {
|
|
|
223
283
|
}
|
|
224
284
|
};
|
|
225
285
|
export {
|
|
286
|
+
ApiError,
|
|
226
287
|
DEFAULT_API_BASE_URL,
|
|
227
288
|
TnFinancialData
|
|
228
289
|
};
|
package/package.json
CHANGED
|
@@ -22,7 +22,7 @@ Covered reads include:
|
|
|
22
22
|
|
|
23
23
|
- company facts and broad one-company overviews
|
|
24
24
|
- financial statements, derived financial metrics, earnings, and analyst estimates
|
|
25
|
-
- issuer-reported
|
|
25
|
+
- quarterly highlights, including issuer-reported release metrics when available and generic latest-quarter summaries otherwise
|
|
26
26
|
- segment and geographic revenue mix
|
|
27
27
|
- price history, latest price snapshot, and stored company news
|
|
28
28
|
- insider trades, issuer-level institutional ownership, and investor `13F` portfolios
|
|
@@ -33,7 +33,7 @@ Covered reads include:
|
|
|
33
33
|
|
|
34
34
|
- For a broad single-company prompt, start with `general-overview`.
|
|
35
35
|
- For a narrow ask, prefer the narrower read instead of widening the problem too early.
|
|
36
|
-
- For Apple product mix or Greater China, Meta ad KPIs, Amazon `AWS` operating income or segment-profit prompts, and Tesla services-and-other or free-cash-flow prompts, start with `quarterly-highlights` before `segmented-revenues`, `financials`, or `general-overview`.
|
|
36
|
+
- For Apple product mix or Greater China, Meta ad KPIs, Amazon `AWS` operating income or segment-profit prompts, and Tesla services-and-other or free-cash-flow prompts, start with `quarterly-highlights` before `segmented-revenues`, `financials`, or `general-overview`. For other covered issuers, `quarterly-highlights` now serves as a generic latest-quarter summary even when no issuer-specific release parser exists.
|
|
37
37
|
- Use `segmented-revenues` when the user explicitly wants XBRL dimension tables, additive segment rows, or issuer coverage that is outside the narrower `quarterly-highlights` surface.
|
|
38
38
|
- For covered-universe filter or ranking questions, use `screen-fields` and `screen`.
|
|
39
39
|
- Keep issuer-centric ownership (`institutional-ownership`) separate from investor-centric portfolio lookup (`investor-portfolio`).
|
|
@@ -5,6 +5,7 @@ Use the CLI for agent access whenever possible.
|
|
|
5
5
|
Auth rule:
|
|
6
6
|
- the published package reads credentials from flags and ambient process env, not from project-local `.env`
|
|
7
7
|
- if there is any doubt, pass `--api-key` and `--base-url` explicitly
|
|
8
|
+
- throttling surfaces as a clean CLI error; raw HTTP callers should read `X-RateLimit-*` and `Retry-After`
|
|
8
9
|
- for broad ticker prompts like "what's up with NVDA?", start with `general-overview`
|
|
9
10
|
- for covered recent-news prompts like "show me recent Nvidia news", start with `news`
|
|
10
11
|
- for latest-quarter product mix, supplemental KPIs, AWS segment profitability, or Tesla free-cash-flow prompts, start with `quarterly-highlights`
|