@bloomai/cli 0.1.1 → 0.1.3

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
@@ -52,6 +52,8 @@ jq '.data[] | select(.revenue_growth > 0.1)' /tmp/bloom/aapl-revenue.json
52
52
  | `catalysts` | Forward-looking value drivers | `bloom catalysts AAPL MSFT` |
53
53
  | `position-size` | Kelly criterion sizing | `bloom position-size --bull 0.6 --bear -0.15 --conviction 8 --value 100000` |
54
54
  | `transcript` | Search earnings call transcripts | `bloom transcript AAPL "AI" "services"` |
55
+ | `ai-trades` | Recent AI model trade decisions (InvestingArena) | `bloom ai-trades --model claude --limit 5` |
56
+ | `ai-portfolio` | AI model portfolio positions & performance | `bloom ai-portfolio --model openai` |
55
57
 
56
58
  ## Global Flags
57
59
 
@@ -115,6 +117,27 @@ bloom transcript AAPL "AI" "services" "margins" --max 20 -o /tmp/bloom/transcrip
115
117
  jq '.matches[] | {speaker, text}' /tmp/bloom/transcript.json
116
118
  ```
117
119
 
120
+ ### AI Arena (InvestingArena — 3 AIs with real money)
121
+ ```bash
122
+ # All AI models' recent trades
123
+ bloom ai-trades -o /tmp/bloom/ai-trades.json
124
+
125
+ # Claude's last 5 trades
126
+ bloom ai-trades --model claude --limit 5
127
+
128
+ # All trades on NVDA across all models
129
+ bloom ai-trades --symbol NVDA -o /tmp/bloom/nvda-ai-trades.json
130
+
131
+ # Full portfolio snapshot for all 3 models
132
+ bloom ai-portfolio -o /tmp/bloom/ai-portfolio.json
133
+
134
+ # Just Gemini's portfolio
135
+ bloom ai-portfolio --model gemini
136
+
137
+ # Extract model returns
138
+ jq '[.[] | {model: .ai_model, return_pct, account_value}]' /tmp/bloom/ai-portfolio.json
139
+ ```
140
+
118
141
  ## Tips
119
142
 
120
143
  - Use `-o` to download data to files, then `jq` to extract. Saves context tokens.
package/SKILL.md CHANGED
@@ -48,6 +48,8 @@ jq '.data[] | select(.revenue_growth > 0.1)' /tmp/bloom/aapl-revenue.json
48
48
  | `catalysts` | Forward-looking value drivers | `bloom catalysts AAPL MSFT` |
49
49
  | `position-size` | Kelly criterion sizing | `bloom position-size --bull 0.6 --bear -0.15 --conviction 8 --value 100000` |
50
50
  | `transcript` | Search earnings call transcripts | `bloom transcript AAPL "AI" "services"` |
51
+ | `ai-trades` | Recent AI model trade decisions (InvestingArena) | `bloom ai-trades --model claude --limit 5` |
52
+ | `ai-portfolio` | AI model portfolio positions & performance | `bloom ai-portfolio --model openai` |
51
53
 
52
54
  ## Global Flags
53
55
 
@@ -111,6 +113,27 @@ bloom transcript AAPL "AI" "services" "margins" --max 20 -o /tmp/bloom/transcrip
111
113
  jq '.matches[] | {speaker, text}' /tmp/bloom/transcript.json
112
114
  ```
113
115
 
116
+ ### AI Arena (InvestingArena — 3 AIs with real money)
117
+ ```bash
118
+ # All AI models' recent trades
119
+ bloom ai-trades -o /tmp/bloom/ai-trades.json
120
+
121
+ # Claude's last 5 trades
122
+ bloom ai-trades --model claude --limit 5
123
+
124
+ # All trades on NVDA across all models
125
+ bloom ai-trades --symbol NVDA -o /tmp/bloom/nvda-ai-trades.json
126
+
127
+ # Full portfolio snapshot for all 3 models
128
+ bloom ai-portfolio -o /tmp/bloom/ai-portfolio.json
129
+
130
+ # Just Gemini's portfolio
131
+ bloom ai-portfolio --model gemini
132
+
133
+ # Extract model returns
134
+ jq '[.[] | {model: .ai_model, return_pct, account_value}]' /tmp/bloom/ai-portfolio.json
135
+ ```
136
+
114
137
  ## Tips
115
138
 
116
139
  - Use `-o` to download data to files, then `jq` to extract. Saves context tokens.
package/dist/index.js CHANGED
@@ -1,6 +1,9 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/index.ts
4
+ import { readFileSync as readFileSync2 } from "fs";
5
+ import path from "path";
6
+ import { fileURLToPath } from "url";
4
7
  import { Command } from "commander";
5
8
 
6
9
  // src/auth.ts
@@ -779,9 +782,138 @@ function formatTranscript(data, opts) {
779
782
  return makeTable(["Speaker", "Role", "Text"], rows, opts);
780
783
  }
781
784
 
785
+ // src/commands/ai-trades.ts
786
+ function registerAiTradesCommand(program2) {
787
+ addGlobalOptions(
788
+ program2.command("ai-trades").description("Recent trade decisions from AI models competing with real money (InvestingArena)").option("--model <m>", "Filter by AI model: claude|openai|gemini").option("--symbol <s>", "Filter by stock ticker symbol (e.g., AAPL)").option("--limit <n>", "Max recent trades per model (default: 10, max: 50)", "10")
789
+ ).action(async (opts) => {
790
+ const args = {
791
+ limit: parseIntSafe(opts.limit, 10)
792
+ };
793
+ if (opts.model) args.ai_model = opts.model;
794
+ if (opts.symbol) args.symbol = opts.symbol.toUpperCase();
795
+ const data = await callTool("get_ai_trade_ideas", args);
796
+ if (opts.raw) {
797
+ outputResult(data, opts);
798
+ return;
799
+ }
800
+ const obj = data;
801
+ const trades = obj.recent_trades ?? data;
802
+ outputResult(trades, opts, (d, o) => formatTrades(d, o));
803
+ });
804
+ }
805
+ function formatTrades(data, opts) {
806
+ if (!data || !Array.isArray(data)) {
807
+ if (data && typeof data === "object") {
808
+ return JSON.stringify(data, null, 2);
809
+ }
810
+ return String(data ?? "(no trades)");
811
+ }
812
+ if (data.length === 0) return "(no trades found)";
813
+ const rows = data.map((trade) => {
814
+ const t = trade;
815
+ const gain = t.realized_gain_loss != null ? `$${Number(t.realized_gain_loss).toFixed(2)}` : "-";
816
+ return [
817
+ String(t.ai_model ?? t.model ?? "-"),
818
+ String(t.action ?? "-").toUpperCase(),
819
+ String(t.symbol ?? "-"),
820
+ String(t.shares ?? "-"),
821
+ t.fill_price != null ? `$${Number(t.fill_price).toFixed(2)}` : "-",
822
+ gain,
823
+ truncate2(String(t.rationale ?? "-"), 60)
824
+ ];
825
+ });
826
+ return makeTable(
827
+ ["Model", "Action", "Symbol", "Shares", "Fill Price", "Realized P/L", "Rationale"],
828
+ rows,
829
+ opts
830
+ );
831
+ }
832
+ function truncate2(s, max) {
833
+ return s.length > max ? s.slice(0, max - 1) + "\u2026" : s;
834
+ }
835
+
836
+ // src/commands/ai-portfolio.ts
837
+ function registerAiPortfolioCommand(program2) {
838
+ addGlobalOptions(
839
+ program2.command("ai-portfolio").description("Current portfolio positions held by AI models (InvestingArena live accounts)").option("--model <m>", "Filter by AI model: claude|openai|gemini")
840
+ ).action(async (opts) => {
841
+ const args = {};
842
+ if (opts.model) args.ai_model = opts.model;
843
+ const data = await callTool("get_ai_trade_ideas", args);
844
+ if (opts.raw) {
845
+ outputResult(data, opts);
846
+ return;
847
+ }
848
+ const obj = data;
849
+ const portfolios = obj.portfolios ?? data;
850
+ outputResult(portfolios, opts, (d, o) => formatPortfolios(d, o));
851
+ });
852
+ }
853
+ function formatPortfolios(data, opts) {
854
+ if (!data || !Array.isArray(data)) {
855
+ if (data && typeof data === "object") {
856
+ return JSON.stringify(data, null, 2);
857
+ }
858
+ return String(data ?? "(no portfolio data)");
859
+ }
860
+ if (data.length === 0) return "(no portfolio data found)";
861
+ const lines = [];
862
+ for (const portfolio of data) {
863
+ const p = portfolio;
864
+ const modelName = String(p.ai_model ?? p.model ?? "Unknown").toUpperCase();
865
+ lines.push(`
866
+ === ${modelName} ===`);
867
+ const acctValue = p.account_value != null ? `$${Number(p.account_value).toFixed(2)}` : "-";
868
+ const cash = p.cash != null ? `$${Number(p.cash).toFixed(2)}` : "-";
869
+ const returnPct = p.return_pct != null ? `${Number(p.return_pct).toFixed(2)}%` : "-";
870
+ const pnl = p.total_pnl != null ? `$${Number(p.total_pnl).toFixed(2)}` : "-";
871
+ lines.push(` Account Value: ${acctValue} | Cash: ${cash} | Return: ${returnPct} | Total P&L: ${pnl}`);
872
+ const positions = p.positions;
873
+ if (Array.isArray(positions) && positions.length > 0) {
874
+ lines.push("");
875
+ const rows = positions.map((pos) => {
876
+ const position = pos;
877
+ const unrealizedPnl = position.unrealized_pnl != null ? `$${Number(position.unrealized_pnl).toFixed(2)}` : "-";
878
+ const allocation = position.allocation_pct != null ? `${Number(position.allocation_pct).toFixed(1)}%` : "-";
879
+ const avgCost = position.avg_cost != null ? `$${Number(position.avg_cost).toFixed(2)}` : "-";
880
+ return [
881
+ String(position.symbol ?? "-"),
882
+ String(position.qty ?? "-"),
883
+ avgCost,
884
+ unrealizedPnl,
885
+ allocation
886
+ ];
887
+ });
888
+ lines.push(
889
+ makeTable(["Symbol", "Qty", "Avg Cost", "Unrealized P/L", "Allocation"], rows, opts)
890
+ );
891
+ } else {
892
+ lines.push(" (no open positions)");
893
+ }
894
+ }
895
+ return lines.join("\n");
896
+ }
897
+
782
898
  // src/index.ts
783
899
  var program = new Command();
784
- program.name("bloom").description("Bloom CLI \u2014 financial data for coding agents and humans").version("0.1.0");
900
+ var __dirname = path.dirname(fileURLToPath(import.meta.url));
901
+ var pkgPath = path.join(__dirname, "..", "package.json");
902
+ var compiledVersion = "0.1.3".length > 0 ? "0.1.3" : void 0;
903
+ var envVersion = process.env.BLOOM_CLI_VERSION ?? process.env.npm_package_version;
904
+ var fallbackVersion = compiledVersion ?? "unknown";
905
+ var cliVersion = envVersion ?? fallbackVersion;
906
+ try {
907
+ const pkg = JSON.parse(readFileSync2(pkgPath, "utf8"));
908
+ if (typeof pkg.version === "string") {
909
+ cliVersion = pkg.version;
910
+ }
911
+ } catch {
912
+ }
913
+ if (cliVersion === "0.0.0") {
914
+ cliVersion = fallbackVersion;
915
+ }
916
+ program.name("bloom").description("Bloom CLI \u2014 financial data for coding agents and humans").version(cliVersion);
785
917
  registerAuthCommand(program);
786
918
  registerInfoCommand(program);
787
919
  registerNewsCommand(program);
@@ -799,6 +931,8 @@ registerTradesCommand(program);
799
931
  registerCatalystsCommand(program);
800
932
  registerPositionCommand(program);
801
933
  registerTranscriptCommand(program);
934
+ registerAiTradesCommand(program);
935
+ registerAiPortfolioCommand(program);
802
936
  program.parseAsync().catch((err) => {
803
937
  console.error("Error:", err.message || err);
804
938
  process.exit(1);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bloomai/cli",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "CLI tool for Bloom financial data - download market data to files for analysis",
5
5
  "type": "module",
6
6
  "bin": {