@aisa-one/cli 0.1.5 → 0.1.6
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 +4 -3
- package/dist/commands/finance.js +57 -18
- package/dist/constants.d.ts +1 -1
- package/dist/constants.js +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -84,11 +84,12 @@ aisa scholar "transformer architecture" # academic papers
|
|
|
84
84
|
### Finance
|
|
85
85
|
|
|
86
86
|
```bash
|
|
87
|
+
aisa stock AAPL # summary: company info + estimates + news
|
|
87
88
|
aisa stock AAPL --field insider # insider trades
|
|
88
89
|
aisa stock AAPL --field news # company news
|
|
89
90
|
aisa stock TSLA --field filings # SEC filings
|
|
90
|
-
aisa stock
|
|
91
|
-
aisa stock
|
|
91
|
+
aisa stock MSFT --field estimates # analyst EPS & revenue estimates
|
|
92
|
+
aisa stock AAPL --field financials # balance sheets, income statements
|
|
92
93
|
aisa crypto BTC # crypto price snapshot
|
|
93
94
|
aisa crypto ETH --period 30d # historical
|
|
94
95
|
aisa screener --sector Technology # stock screener
|
|
@@ -215,7 +216,7 @@ The `domain: true` option in `RequestOptions` (see `src/api.ts`) selects which b
|
|
|
215
216
|
|
|
216
217
|
**Models API follows OpenAI format.** The `/v1/models` endpoint returns `owned_by` (not `provider`) and has no `name`, `pricing`, or `contextWindow` fields.
|
|
217
218
|
|
|
218
|
-
**Some financial endpoints return empty data.** `financial/prices` and `financial/financial-metrics/snapshot`
|
|
219
|
+
**Some financial endpoints return empty data.** `financial/prices` and `financial/financial-metrics/snapshot` return `{}` for all tickers (backend issue). The default `aisa stock` now fetches `company/facts` + `analyst-estimates` + `news` instead. Working fields: `info`, `estimates`, `financials`, `filings`, `insider`, `institutional`, `news`.
|
|
219
220
|
|
|
220
221
|
## License
|
|
221
222
|
|
package/dist/commands/finance.js
CHANGED
|
@@ -1,40 +1,79 @@
|
|
|
1
1
|
import ora from "ora";
|
|
2
|
+
import chalk from "chalk";
|
|
2
3
|
import { requireApiKey } from "../config.js";
|
|
3
4
|
import { apiRequest } from "../api.js";
|
|
4
5
|
import { error, formatJson } from "../utils/display.js";
|
|
5
6
|
const FIELD_ENDPOINTS = {
|
|
6
|
-
|
|
7
|
-
|
|
7
|
+
info: "financial/company/facts",
|
|
8
|
+
estimates: "financial/analyst-estimates",
|
|
8
9
|
financials: "financial/financials",
|
|
9
10
|
filings: "financial/filings",
|
|
10
11
|
insider: "financial/insider-trades",
|
|
11
12
|
institutional: "financial/institutional-ownership",
|
|
12
|
-
metrics: "financial/financial-metrics/snapshot",
|
|
13
13
|
news: "financial/news",
|
|
14
14
|
};
|
|
15
15
|
export async function stockAction(symbol, options) {
|
|
16
16
|
const key = requireApiKey();
|
|
17
|
-
const field = options.field || "
|
|
17
|
+
const field = options.field || "info";
|
|
18
|
+
const ticker = symbol.toUpperCase();
|
|
19
|
+
// Default: show a summary of company info + estimates + news
|
|
20
|
+
if (!options.field) {
|
|
21
|
+
const spinner = ora(`Fetching ${ticker}...`).start();
|
|
22
|
+
const [infoRes, estRes, newsRes] = await Promise.all([
|
|
23
|
+
apiRequest(key, "financial/company/facts", { query: { ticker }, domain: true }),
|
|
24
|
+
apiRequest(key, "financial/analyst-estimates", { query: { ticker }, domain: true }),
|
|
25
|
+
apiRequest(key, "financial/news", { query: { ticker, limit: "3" }, domain: true }),
|
|
26
|
+
]);
|
|
27
|
+
spinner.stop();
|
|
28
|
+
if (options.raw) {
|
|
29
|
+
console.log(JSON.stringify({ info: infoRes.data, estimates: estRes.data, news: newsRes.data }));
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
// Company info
|
|
33
|
+
const facts = infoRes.data?.company_facts;
|
|
34
|
+
if (facts) {
|
|
35
|
+
console.log(`\n ${chalk.cyan.bold(facts.name || ticker)} ${chalk.gray(`(${facts.ticker || ticker})`)}`);
|
|
36
|
+
const details = [facts.exchange, facts.sector, facts.industry].filter(Boolean).join(" · ");
|
|
37
|
+
if (details)
|
|
38
|
+
console.log(` ${chalk.gray(details)}`);
|
|
39
|
+
if (facts.location)
|
|
40
|
+
console.log(` ${chalk.gray(facts.location)}`);
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
console.log(`\n ${chalk.cyan.bold(ticker)}`);
|
|
44
|
+
}
|
|
45
|
+
// Analyst estimates
|
|
46
|
+
const estimates = estRes.data?.analyst_estimates;
|
|
47
|
+
if (estimates && estimates.length > 0) {
|
|
48
|
+
console.log(`\n ${chalk.white.bold("Analyst Estimates")}`);
|
|
49
|
+
for (const e of estimates.slice(0, 3)) {
|
|
50
|
+
const period = e.fiscal_period?.split("T")[0] || e.period || "";
|
|
51
|
+
const eps = e.earnings_per_share != null ? `EPS $${e.earnings_per_share.toFixed(2)}` : "";
|
|
52
|
+
const rev = e.revenue != null ? `Rev $${(e.revenue / 1e9).toFixed(1)}B` : "";
|
|
53
|
+
console.log(` ${chalk.gray(period)} ${eps} ${rev}`);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
// Latest news
|
|
57
|
+
const news = newsRes.data?.news;
|
|
58
|
+
if (news && news.length > 0) {
|
|
59
|
+
console.log(`\n ${chalk.white.bold("Latest News")}`);
|
|
60
|
+
for (const n of news) {
|
|
61
|
+
const date = n.date ? new Date(n.date).toLocaleDateString() : "";
|
|
62
|
+
console.log(` ${chalk.gray(date)} ${n.title}`);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
console.log();
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
// Specific field
|
|
18
69
|
const endpoint = FIELD_ENDPOINTS[field];
|
|
19
70
|
if (!endpoint) {
|
|
20
71
|
error(`Unknown field: ${field}. Valid: ${Object.keys(FIELD_ENDPOINTS).join(", ")}`);
|
|
21
72
|
return;
|
|
22
73
|
}
|
|
23
|
-
const spinner = ora(`Fetching ${field} for ${
|
|
24
|
-
const query = { ticker: symbol.toUpperCase() };
|
|
25
|
-
// Price endpoint needs additional params for sensible defaults
|
|
26
|
-
if (field === "price") {
|
|
27
|
-
const end = new Date();
|
|
28
|
-
const start = new Date();
|
|
29
|
-
start.setDate(start.getDate() - 30);
|
|
30
|
-
query.interval = "day";
|
|
31
|
-
query.interval_multiplier = "1";
|
|
32
|
-
query.start_date = start.toISOString().split("T")[0];
|
|
33
|
-
query.end_date = end.toISOString().split("T")[0];
|
|
34
|
-
query.limit = "30";
|
|
35
|
-
}
|
|
74
|
+
const spinner = ora(`Fetching ${field} for ${ticker}...`).start();
|
|
36
75
|
const res = await apiRequest(key, endpoint, {
|
|
37
|
-
query,
|
|
76
|
+
query: { ticker },
|
|
38
77
|
domain: true,
|
|
39
78
|
});
|
|
40
79
|
if (!res.success) {
|
package/dist/constants.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export declare const VERSION = "0.1.
|
|
1
|
+
export declare const VERSION = "0.1.6";
|
|
2
2
|
export declare const BASE_URL = "https://api.aisa.one";
|
|
3
3
|
export declare const CLI_BASE_URL = "https://api.aisa.one/v1";
|
|
4
4
|
export declare const APIS_BASE_URL = "https://api.aisa.one/apis/v1";
|
package/dist/constants.js
CHANGED
package/dist/index.js
CHANGED
|
@@ -143,7 +143,7 @@ program
|
|
|
143
143
|
program
|
|
144
144
|
.command("stock <symbol>")
|
|
145
145
|
.description("Look up stock data")
|
|
146
|
-
.option("--field <field>", "Data field:
|
|
146
|
+
.option("--field <field>", "Data field: info, estimates, financials, filings, insider, institutional, news")
|
|
147
147
|
.option("--raw", "Raw JSON output")
|
|
148
148
|
.action(wrap(stockAction));
|
|
149
149
|
program
|
package/package.json
CHANGED