mozyfin-cli 0.2.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/LICENSE ADDED
@@ -0,0 +1,10 @@
1
+ Copyright (c) 2024 Mozyfin. All rights reserved.
2
+
3
+ This software and associated documentation files (the "Software") are proprietary
4
+ and confidential. Unauthorized copying, distribution, modification, sublicensing,
5
+ or use of this Software, in whole or in part, via any medium, is strictly
6
+ prohibited without the prior written permission of Mozyfin.
7
+
8
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
9
+ IMPLIED. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
10
+ CLAIM, DAMAGES, OR OTHER LIABILITY ARISING FROM USE OF THE SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,280 @@
1
+ # Mozyfin CLI
2
+
3
+ A Bun-powered command line interface for Vietnamese market data from the Mozyfin/Antofin APIs. It is designed for both humans and AI agents: short ticker-first commands, Markdown tables by default, CSV export for long datasets, and predictable plain-text errors.
4
+
5
+ ## Highlights
6
+
7
+ - Human-readable Markdown output by default
8
+ - CSV export with `--csv <file>` for spreadsheets or agent pipelines
9
+ - Public market/entity endpoints work without an API key
10
+ - Authenticated commands support `MOZYFIN_API_KEY`, saved config, or `--api-key`
11
+ - Client-side 1 request/second rate limit for API friendliness
12
+ - Built-in technical indicators and risk metrics from OHLCV candles
13
+ - Mocked CLI test suite covering command wiring, auth, config, CSV, validation, and output shape
14
+
15
+ ## Requirements
16
+
17
+ - [Bun](https://bun.sh) `>= 1.1.0`
18
+ - A Mozyfin API key for authenticated commands such as `ask`, `doc`, and `credits`
19
+
20
+ Create an API key at: https://research.mozyfin.com/setting
21
+
22
+ ## Install
23
+
24
+ ```bash
25
+ npm install -g mozyfin-cli
26
+ ```
27
+
28
+ Or with Bun:
29
+
30
+ ```bash
31
+ bun install -g mozyfin-cli
32
+ ```
33
+
34
+ ### Save API Key
35
+
36
+ ```bash
37
+ mozyfin login --api-key mozy_ak_xxx
38
+ ```
39
+
40
+ You can also use an environment variable:
41
+
42
+ ```bash
43
+ export MOZYFIN_API_KEY=mozy_ak_xxx
44
+ ```
45
+
46
+ ## Quick Start
47
+
48
+ ```bash
49
+ mozyfin search --query VNM
50
+ mozyfin profile VNM.VN
51
+ mozyfin news --entities VNM.VN --topics stock,earning --limit 10
52
+ mozyfin ohlcv VNM.VN --timeframe 1d --limit 200
53
+ mozyfin financials VNM.VN --year 2024 --quarter 4
54
+ mozyfin doc "định giá HPG"
55
+ mozyfin ask "compare VNM and MSN margin trend"
56
+ ```
57
+
58
+ ## Commands
59
+
60
+ | Command | Purpose | Example |
61
+ | --- | --- | --- |
62
+ | `login` | Save API key locally | `mozyfin login --api-key <key>` |
63
+ | `logout` | Remove saved API key | `mozyfin logout` |
64
+ | `search` | Search ticker/company/entity | `mozyfin search --query VNM` |
65
+ | `profile` | Company/entity profile | `mozyfin profile VNM.VN` |
66
+ | `news` | Market headlines and article search | `mozyfin news --entities VNM.VN --topics stock,earning` |
67
+ | `ohlcv` | Historical candles | `mozyfin ohlcv VNM.VN --timeframe 1d --limit 200` |
68
+ | `quote` | Historical quote stats | `mozyfin quote VNM.VN --limit 10` |
69
+ | `officers` | Company officers/directors | `mozyfin officers VNM.VN` |
70
+ | `subsidiary` | Subsidiaries | `mozyfin subsidiary VNM.VN` |
71
+ | `holder` | Major shareholders | `mozyfin holder VNM.VN --is-organization true` |
72
+ | `holder-tx` | Shareholder transactions | `mozyfin holder-tx VNM.VN --transaction-type buy --limit 100` |
73
+ | `financials` | Financial statements summary | `mozyfin financials VNM.VN --year 2024 --quarter 4` |
74
+ | `stats` | Financial statistics/ratios | `mozyfin stats VNM.VN --year 2024` |
75
+ | `ta` | Technical indicators | `mozyfin ta VNM.VN --sma 20,50 --rsi 14 --macd` |
76
+ | `risk` | Return, volatility, Sharpe, drawdown | `mozyfin risk VNM.VN --limit 252 --risk-free 0.03` |
77
+ | `doc` | Query analysis reports (RAG) | `mozyfin doc "định giá HPG"` |
78
+ | `ask` | Ask the Mozyfin agent | `mozyfin ask "analyze VNM" --timeout 300` |
79
+ | `credits` | Check subscription usage | `mozyfin credits` |
80
+ | `doctor` | Runtime/config/API health check | `mozyfin doctor` |
81
+ | `update` | Print upgrade hint | `mozyfin update` |
82
+
83
+ ## Command Reference
84
+
85
+ ### Auth
86
+
87
+ ```bash
88
+ mozyfin login --api-key <key>
89
+ mozyfin logout
90
+ mozyfin credits
91
+ ```
92
+
93
+ Auth precedence is:
94
+
95
+ 1. Explicit global `--api-key <key>`
96
+ 2. `MOZYFIN_API_KEY` environment variable
97
+ 3. Saved config from `mozyfin login`
98
+
99
+ Config is stored at:
100
+
101
+ ```text
102
+ ~/.config/mozyfin-cli/config.json
103
+ ```
104
+
105
+ ### Search and Profile
106
+
107
+ ```bash
108
+ mozyfin search --query VNM
109
+ mozyfin search -q "Vinamilk"
110
+ mozyfin search -q "" # broad search/all, depending on API behavior
111
+ mozyfin profile VNM.VN
112
+ ```
113
+
114
+ `search` intentionally only exposes `--query` to keep the CLI simple and aligned with the current product workflow.
115
+
116
+ ### News
117
+
118
+ ```bash
119
+ mozyfin news --query "Vinamilk" --limit 10
120
+ mozyfin news --entities VNM.VN,MSN.VN --topics stock,earning --limit 20
121
+ ```
122
+
123
+ Allowed topics:
124
+
125
+ ```text
126
+ stock, crypto, forex, tariff, economic, earning, tech, housing, mergers_and_ipo
127
+ ```
128
+
129
+ ### Market Data
130
+
131
+ ```bash
132
+ mozyfin ohlcv VNM.VN --timeframe 1d --limit 200
133
+ mozyfin ohlcv VNM.VN --timeframe 1w --to 2024-12-31 --limit 52
134
+ mozyfin quote VNM.VN --to 2024-12-31 --limit 10
135
+ ```
136
+
137
+ Allowed OHLCV timeframes:
138
+
139
+ ```text
140
+ 1h, 1d, 1w, 1mo, 1y
141
+ ```
142
+
143
+ ### Entity Details
144
+
145
+ ```bash
146
+ mozyfin officers VNM.VN
147
+ mozyfin subsidiary VNM.VN
148
+ mozyfin holder VNM.VN --is-organization true --is-foreigner false
149
+ mozyfin holder-tx VNM.VN --transaction-type buy --limit 100
150
+ ```
151
+
152
+ Note: the upstream endpoint for `officers` is named `/office`, but the returned data is officers/directors, so the CLI command uses `officers` for clarity.
153
+
154
+ ### Financials
155
+
156
+ ```bash
157
+ mozyfin financials VNM.VN --year 2024 --quarter 4
158
+ mozyfin financials VNM.VN --year 2024 --quarter 4 --statement-type BALANCE_SHEET
159
+ mozyfin stats VNM.VN --year 2024
160
+ ```
161
+
162
+ `financials` summarizes nested statement values into common readable columns such as `net_sales`, `gross_profit`, `profit_after_tax`, `total_assets`, `owner_equity`, and `net_operating_cash_flow`.
163
+
164
+ ### Analytics
165
+
166
+ ```bash
167
+ mozyfin ta VNM.VN --sma 20,50,200 --rsi 14 --macd
168
+ mozyfin risk VNM.VN --limit 252 --risk-free 0.03
169
+ ```
170
+
171
+ `ta` and `risk` compute over chronological candles even when the API returns latest-first data.
172
+
173
+ ### Document Query
174
+
175
+ ```bash
176
+ mozyfin doc "định giá HPG"
177
+ mozyfin doc "VNM Q4 2024 earnings analysis"
178
+ mozyfin doc "so sánh biên lợi nhuận VNM và MSN"
179
+ ```
180
+
181
+ Queries analysis reports using natural language via RAG. Returns structured Markdown with sections:
182
+
183
+ - **Entities** — knowledge graph entities extracted from reports
184
+ - **Relationships** — connections between entities
185
+ - **Document Chunks** — retrieved report passages relevant to the query
186
+ - **References** — source documents mapped to chunks
187
+ - **Context** — grounding instructions from the RAG system
188
+
189
+ Requires an API key.
190
+
191
+ ### Agent
192
+
193
+ ```bash
194
+ mozyfin ask "summarize VNM risks and catalysts" --timeout 300
195
+ ```
196
+
197
+ The command creates an auto-mode chat, sends the prompt, polls until the message finishes, and prints the final text response.
198
+
199
+ ## Output
200
+
201
+ Default output is Markdown table or key-value text:
202
+
203
+ ```bash
204
+ mozyfin search --query VNM
205
+ ```
206
+
207
+ ```text
208
+ | symbol | name | exchange | market_cap | id |
209
+ | --- | --- | --- | --- | --- |
210
+ | VNM | Vietnam Dairy Products Joint Stock Company | HOSE | ... | VNM.VN |
211
+ ```
212
+
213
+ Use CSV for long datasets:
214
+
215
+ ```bash
216
+ mozyfin ohlcv VNM.VN --timeframe 1d --limit 200 --csv vnm.csv
217
+ ```
218
+
219
+ ## Development
220
+
221
+ ```bash
222
+ bun install
223
+ bun run check
224
+ bun test
225
+ ```
226
+
227
+ Useful scripts:
228
+
229
+ | Script | Description |
230
+ | --- | --- |
231
+ | `bun run dev -- <args>` | Run CLI from source |
232
+ | `bun test` | Run unit/CLI tests |
233
+ | `bun run lint` | Check formatting/linting |
234
+ | `bun run format` | Format files |
235
+ | `bun run check` | Format/lint with write fixes |
236
+
237
+ Run from source:
238
+
239
+ ```bash
240
+ bun run src/index.ts search --query VNM
241
+ ```
242
+
243
+ ## Test Coverage
244
+
245
+ The test suite uses Bun's test runner plus a mocked local HTTP server. It covers:
246
+
247
+ - API URL construction and endpoint mapping
248
+ - HTTP response and error parsing
249
+ - CLI command output shape
250
+ - Query parameter mapping for command options
251
+ - Auth precedence and config persistence
252
+ - CSV file output
253
+ - Empty data rendering
254
+ - Validation errors and missing API key errors
255
+ - `ask` polling and malformed response handling
256
+ - Technical indicator and risk helper behavior
257
+
258
+ ## Project Structure
259
+
260
+ ```text
261
+ src/index.ts CLI command definitions
262
+ src/lib/api.ts API client, auth, rate limit, URL construction
263
+ src/lib/config.ts Local config load/save/clear
264
+ src/lib/format.ts Markdown, key-value, CSV formatting
265
+ src/lib/analytics.ts SMA, EMA, RSI, MACD, risk metrics
266
+ test/*.test.ts Unit and mocked CLI tests
267
+ ```
268
+
269
+ ## Notes for AI Agents
270
+
271
+ - Prefer Markdown output for short responses and `--csv <file>` for large tables.
272
+ - Use `search --query <text>` to discover entity ids, then pass ids such as `VNM.VN` into detail commands.
273
+ - Do not use removed commands/options such as `markets`, `exchanges`, or `ask --no-wait`.
274
+ - `officers` returns people and roles, not physical office addresses.
275
+ - Public market endpoints do not require an API key; `ask`, `doc`, and `credits` do.
276
+ - Use `doc` for natural language queries against analysis reports (RAG); use `ask` for open-ended AI research that may call multiple data sources.
277
+
278
+ ## License
279
+
280
+ Private/internal unless a license is added.
@@ -0,0 +1,300 @@
1
+ ---
2
+ name: mozyfin-cli
3
+ description: "Mozyfin CLI: Vietnam stock market data, quotes, financials, technical analysis, AI-powered research."
4
+ ---
5
+
6
+ # mozyfin-cli
7
+
8
+ Use `mozyfin` when you need Vietnamese stock market data, company information, technical analysis, or AI-powered research on Vietnam equities.
9
+
10
+ ## Fast Path
11
+
12
+ ```bash
13
+ mozyfin --version
14
+ mozyfin --help
15
+ mozyfin <command> --help
16
+ ```
17
+
18
+ Quick data retrieval without authentication:
19
+
20
+ ```bash
21
+ mozyfin search --query VNM
22
+ mozyfin profile VNM.VN
23
+ mozyfin quote VNM.VN
24
+ mozyfin ohlcv VNM.VN --timeframe 1d --limit 30
25
+ mozyfin news VNM.VN --limit 10
26
+ ```
27
+
28
+ Use `--csv <file>` for large datasets that need further processing.
29
+
30
+ ## Authentication
31
+
32
+ Public market data commands work without an API key. Authenticated commands (`ask`, `doc`, `credits`) require one:
33
+
34
+ ```bash
35
+ # Login and save credentials
36
+ mozyfin login --api-key <your-key>
37
+
38
+ # Or use environment variable
39
+ export MOZYFIN_API_KEY=<your-key>
40
+
41
+ # Or pass directly
42
+ mozyfin ask "Analyze VNM" --api-key <your-key>
43
+ ```
44
+
45
+ Get your API key at: https://research.mozyfin.com/settings
46
+
47
+ Auth precedence:
48
+ 1. Explicit `--api-key` flag
49
+ 2. `MOZYFIN_API_KEY` environment variable
50
+ 3. Saved config from `mozyfin login`
51
+
52
+ Config location: `~/.config/mozyfin-cli/config.json`
53
+
54
+ ## Ticker Format
55
+
56
+ All commands use the format `SYMBOL.VN`:
57
+
58
+ ```bash
59
+ mozyfin profile VNM.VN
60
+ mozyfin quote FPT.VN VIC.VN MWG.VN # Multiple tickers
61
+ ```
62
+
63
+ The `search` command is the exception - it accepts partial names:
64
+
65
+ ```bash
66
+ mozyfin search --query vinamilk
67
+ mozyfin search --query VNM
68
+ ```
69
+
70
+ ## Commands
71
+
72
+ ### Search
73
+
74
+ Find tickers by name or symbol:
75
+
76
+ ```bash
77
+ mozyfin search --query VNM
78
+ mozyfin search --query vinamilk
79
+ mozyfin search -q bank
80
+ ```
81
+
82
+ ### Company Information
83
+
84
+ ```bash
85
+ # Company profile
86
+ mozyfin profile VNM.VN
87
+
88
+ # Officers and directors
89
+ mozyfin officers VNM.VN
90
+
91
+ # Corporate events
92
+ mozyfin events VNM.VN --limit 20
93
+ ```
94
+
95
+ ### Market Data
96
+
97
+ ```bash
98
+ # Real-time quotes
99
+ mozyfin quote VNM.VN
100
+ mozyfin quote VNM.VN FPT.VN VIC.VN
101
+
102
+ # Quote at specific time (Unix timestamp)
103
+ mozyfin quote VNM.VN --to 1746038400
104
+
105
+ # Historical OHLCV data
106
+ mozyfin ohlcv VNM.VN --timeframe 1d --limit 100
107
+ mozyfin ohlcv VNM.VN -t 1h -l 200 --csv vnm-hourly.csv
108
+
109
+ # OHLCV with end time (Unix timestamp)
110
+ mozyfin ohlcv VNM.VN --timeframe 1d --to 1746038400 --limit 365
111
+
112
+ # Timeframes: 1h, 1d, 1w, 1mo, 1y
113
+ # Note: --to accepts Unix timestamp (seconds since epoch)
114
+ ```
115
+
116
+ ### News
117
+
118
+ ```bash
119
+ mozyfin news VNM.VN --limit 10
120
+ mozyfin news FPT.VN -l 20
121
+ ```
122
+
123
+ ### Financials
124
+
125
+ ```bash
126
+ # Financial statements
127
+ mozyfin financials VNM.VN
128
+
129
+ # Key statistics
130
+ mozyfin stats VNM.VN
131
+
132
+ # Export to CSV
133
+ mozyfin financials VNM.VN --csv financials.csv
134
+ ```
135
+
136
+ ### Technical Analysis
137
+
138
+ ```bash
139
+ # Technical indicators
140
+ mozyfin ta VNM.VN --timeframe 1d
141
+ mozyfin ta VNM.VN -t 1h
142
+
143
+ # Risk metrics
144
+ mozyfin risk VNM.VN --timeframe 1d
145
+ mozyfin risk VNM.VN -t 1w
146
+ ```
147
+
148
+ ### Document Query (Requires API Key)
149
+
150
+ Query analysis reports using natural language. Returns structured Markdown with entities, relationships, retrieved report chunks, source references, and grounding context.
151
+
152
+ ```bash
153
+ mozyfin doc "định giá HPG"
154
+ mozyfin doc "VNM Q4 2024 earnings analysis"
155
+ mozyfin doc "so sánh biên lợi nhuận VNM và MSN"
156
+ mozyfin doc "rủi ro ngành thép 2024"
157
+ ```
158
+
159
+ Output sections (in order):
160
+ 1. **Entities** — knowledge graph nodes from retrieved reports
161
+ 2. **Relationships** — entity connections
162
+ 3. **Document Chunks** — relevant passages from reports
163
+ 4. **References** — source file paths for each chunk
164
+ 5. **Context** — RAG grounding instructions
165
+
166
+ Use `doc` when you need grounded answers from actual report documents. Use `ask` for open-ended research that may synthesize multiple data sources.
167
+
168
+ ### AI Research (Requires API Key)
169
+
170
+ **Recommended for agents**: Use `ask` instead of multiple individual commands. It saves tokens and provides better analysis by leveraging server-side AI with full market context.
171
+
172
+ ```bash
173
+ # Ask AI about stocks
174
+ mozyfin ask "Analyze VNM financial performance"
175
+ mozyfin ask "Compare VNM and MSN margins" --timeout 120
176
+ mozyfin ask "What are the risks for FPT?" -t 60
177
+ ```
178
+
179
+ **Why agents should prefer `ask`:**
180
+ - Single API call vs. multiple commands
181
+ - Server-side AI has access to full historical data and context
182
+ - Returns comprehensive analysis in one response
183
+ - More efficient token usage for the agent
184
+ - Better synthesis across multiple data sources
185
+
186
+ ### Account Management
187
+
188
+ ```bash
189
+ # Check remaining credits
190
+ mozyfin credits
191
+
192
+ # Update CLI
193
+ mozyfin update
194
+
195
+ # Update CLI and skills
196
+ mozyfin update --skill
197
+ mozyfin update --skill claude
198
+ mozyfin update --skill all
199
+
200
+ # Logout
201
+ mozyfin logout
202
+ ```
203
+
204
+ ### Install Skills for Agents
205
+
206
+ ```bash
207
+ # Install skill for specific agent
208
+ mozyfin skill claude
209
+ mozyfin skill cursor
210
+ mozyfin skill copilot
211
+ mozyfin skill windsurf
212
+ mozyfin skill codex
213
+ mozyfin skill gemini
214
+ mozyfin skill hermes
215
+ mozyfin skill openclaw
216
+
217
+ # Install for all agents
218
+ mozyfin skill all
219
+
220
+ # List installed skills
221
+ mozyfin skill --list
222
+
223
+ # Remove skill
224
+ mozyfin skill claude --remove
225
+ ```
226
+
227
+ ## Output Formats
228
+
229
+ Default output is human-readable Markdown tables. Use `--csv` for data export:
230
+
231
+ ```bash
232
+ # Markdown table (default)
233
+ mozyfin ohlcv VNM.VN --limit 10
234
+
235
+ # CSV export
236
+ mozyfin ohlcv VNM.VN --limit 1000 --csv ohlcv.csv
237
+ mozyfin financials VNM.VN --csv financials.csv
238
+ mozyfin ta VNM.VN --csv technical.csv
239
+ ```
240
+
241
+ ## Common Workflows
242
+
243
+ ### Research a Stock
244
+
245
+ ```bash
246
+ mozyfin search --query vnm
247
+ mozyfin profile VNM.VN
248
+ mozyfin financials VNM.VN
249
+ mozyfin quote VNM.VN
250
+ mozyfin news VNM.VN --limit 10
251
+ mozyfin ta VNM.VN
252
+ mozyfin risk VNM.VN
253
+ ```
254
+
255
+ ### Compare Multiple Stocks
256
+
257
+ ```bash
258
+ mozyfin quote VNM.VN FPT.VN VIC.VN MWG.VN
259
+ mozyfin stats VNM.VN FPT.VN
260
+ ```
261
+
262
+ ### Export Data for Analysis
263
+
264
+ ```bash
265
+ mozyfin ohlcv VNM.VN --timeframe 1d --limit 365 --csv vnm-yearly.csv
266
+ mozyfin financials VNM.VN --csv vnm-financials.csv
267
+ mozyfin ta VNM.VN --csv vnm-technical.csv
268
+ ```
269
+
270
+ ### Document-Grounded Research
271
+
272
+ ```bash
273
+ mozyfin doc "định giá HPG"
274
+ mozyfin doc "triển vọng ngành ngân hàng 2024"
275
+ mozyfin doc "FPT revenue growth outlook"
276
+ ```
277
+
278
+ ### AI-Powered Analysis
279
+
280
+ ```bash
281
+ mozyfin ask "What is VNM's competitive position in dairy?"
282
+ mozyfin ask "Analyze FPT's revenue growth over the last 5 years"
283
+ mozyfin ask "Compare banking sector stocks: TCB, VCB, BID"
284
+ ```
285
+
286
+ ## Error Handling
287
+
288
+ - Commands return clear error messages for invalid tickers
289
+ - Auth-required commands show helpful message if no API key is found
290
+ - Network errors include status codes for debugging
291
+ - Use `--help` on any command for usage details
292
+
293
+ ## Notes
294
+
295
+ - All price data is in VND (Vietnamese Dong)
296
+ - Market hours: 9:00-11:30 and 13:00-15:00 ICT (UTC+7)
297
+ - Data sourced from HoSE and HNX exchanges
298
+ - Real-time quotes may have a few seconds delay
299
+ - `doc` accepts both Vietnamese and English queries
300
+ - `doc` returns RAG context for grounded answers; `ask` performs open-ended AI reasoning
package/dist/index.js ADDED
@@ -0,0 +1,75 @@
1
+ #!/usr/bin/env bun
2
+ // @bun
3
+ var O0=Object.create;var{getPrototypeOf:h0,defineProperty:z0,getOwnPropertyNames:v0}=Object;var u0=Object.prototype.hasOwnProperty;var g0=($,q,Q)=>{Q=$!=null?O0(h0($)):{};let z=q||!$||!$.__esModule?z0(Q,"default",{value:$,enumerable:!0}):Q;for(let J of v0($))if(!u0.call(z,J))z0(z,J,{get:()=>$[J],enumerable:!0});return z};var V=($,q)=>()=>(q||$((q={exports:{}}).exports,q),q.exports);var E=import.meta.require;var k=V((c0)=>{class c extends Error{constructor($,q,Q){super(Q);Error.captureStackTrace(this,this.constructor),this.name=this.constructor.name,this.code=q,this.exitCode=$,this.nestedError=void 0}}class J0 extends c{constructor($){super(1,"commander.invalidArgument",$);Error.captureStackTrace(this,this.constructor),this.name=this.constructor.name}}c0.CommanderError=c;c0.InvalidArgumentError=J0});var x=V((s0)=>{var{InvalidArgumentError:d0}=k();class M0{constructor($,q){switch(this.description=q||"",this.variadic=!1,this.parseArg=void 0,this.defaultValue=void 0,this.defaultValueDescription=void 0,this.argChoices=void 0,$[0]){case"<":this.required=!0,this._name=$.slice(1,-1);break;case"[":this.required=!1,this._name=$.slice(1,-1);break;default:this.required=!0,this._name=$;break}if(this._name.length>3&&this._name.slice(-3)==="...")this.variadic=!0,this._name=this._name.slice(0,-3)}name(){return this._name}_concatValue($,q){if(q===this.defaultValue||!Array.isArray(q))return[$];return q.concat($)}default($,q){return this.defaultValue=$,this.defaultValueDescription=q,this}argParser($){return this.parseArg=$,this}choices($){return this.argChoices=$.slice(),this.parseArg=(q,Q)=>{if(!this.argChoices.includes(q))throw new d0(`Allowed choices are ${this.argChoices.join(", ")}.`);if(this.variadic)return this._concatValue(q,Q);return q},this}argRequired(){return this.required=!0,this}argOptional(){return this.required=!1,this}}function r0($){let q=$.name()+($.variadic===!0?"...":"");return $.required?"<"+q+">":"["+q+"]"}s0.Argument=M0;s0.humanReadableArgName=r0});var l=V((n0)=>{var{humanReadableArgName:t0}=x();class Y0{constructor(){this.helpWidth=void 0,this.sortSubcommands=!1,this.sortOptions=!1,this.showGlobalOptions=!1}visibleCommands($){let q=$.commands.filter((z)=>!z._hidden),Q=$._getHelpCommand();if(Q&&!Q._hidden)q.push(Q);if(this.sortSubcommands)q.sort((z,J)=>{return z.name().localeCompare(J.name())});return q}compareOptions($,q){let Q=(z)=>{return z.short?z.short.replace(/^-/,""):z.long.replace(/^--/,"")};return Q($).localeCompare(Q(q))}visibleOptions($){let q=$.options.filter((z)=>!z.hidden),Q=$._getHelpOption();if(Q&&!Q.hidden){let z=Q.short&&$._findOption(Q.short),J=Q.long&&$._findOption(Q.long);if(!z&&!J)q.push(Q);else if(Q.long&&!J)q.push($.createOption(Q.long,Q.description));else if(Q.short&&!z)q.push($.createOption(Q.short,Q.description))}if(this.sortOptions)q.sort(this.compareOptions);return q}visibleGlobalOptions($){if(!this.showGlobalOptions)return[];let q=[];for(let Q=$.parent;Q;Q=Q.parent){let z=Q.options.filter((J)=>!J.hidden);q.push(...z)}if(this.sortOptions)q.sort(this.compareOptions);return q}visibleArguments($){if($._argsDescription)$.registeredArguments.forEach((q)=>{q.description=q.description||$._argsDescription[q.name()]||""});if($.registeredArguments.find((q)=>q.description))return $.registeredArguments;return[]}subcommandTerm($){let q=$.registeredArguments.map((Q)=>t0(Q)).join(" ");return $._name+($._aliases[0]?"|"+$._aliases[0]:"")+($.options.length?" [options]":"")+(q?" "+q:"")}optionTerm($){return $.flags}argumentTerm($){return $.name()}longestSubcommandTermLength($,q){return q.visibleCommands($).reduce((Q,z)=>{return Math.max(Q,q.subcommandTerm(z).length)},0)}longestOptionTermLength($,q){return q.visibleOptions($).reduce((Q,z)=>{return Math.max(Q,q.optionTerm(z).length)},0)}longestGlobalOptionTermLength($,q){return q.visibleGlobalOptions($).reduce((Q,z)=>{return Math.max(Q,q.optionTerm(z).length)},0)}longestArgumentTermLength($,q){return q.visibleArguments($).reduce((Q,z)=>{return Math.max(Q,q.argumentTerm(z).length)},0)}commandUsage($){let q=$._name;if($._aliases[0])q=q+"|"+$._aliases[0];let Q="";for(let z=$.parent;z;z=z.parent)Q=z.name()+" "+Q;return Q+q+" "+$.usage()}commandDescription($){return $.description()}subcommandDescription($){return $.summary()||$.description()}optionDescription($){let q=[];if($.argChoices)q.push(`choices: ${$.argChoices.map((Q)=>JSON.stringify(Q)).join(", ")}`);if($.defaultValue!==void 0){if($.required||$.optional||$.isBoolean()&&typeof $.defaultValue==="boolean")q.push(`default: ${$.defaultValueDescription||JSON.stringify($.defaultValue)}`)}if($.presetArg!==void 0&&$.optional)q.push(`preset: ${JSON.stringify($.presetArg)}`);if($.envVar!==void 0)q.push(`env: ${$.envVar}`);if(q.length>0)return`${$.description} (${q.join(", ")})`;return $.description}argumentDescription($){let q=[];if($.argChoices)q.push(`choices: ${$.argChoices.map((Q)=>JSON.stringify(Q)).join(", ")}`);if($.defaultValue!==void 0)q.push(`default: ${$.defaultValueDescription||JSON.stringify($.defaultValue)}`);if(q.length>0){let Q=`(${q.join(", ")})`;if($.description)return`${$.description} ${Q}`;return Q}return $.description}formatHelp($,q){let Q=q.padWidth($,q),z=q.helpWidth||80,J=2,M=2;function X(W,N){if(N){let g=`${W.padEnd(Q+2)}${N}`;return q.wrap(g,z-2,Q+2)}return W}function Y(W){return W.join(`
4
+ `).replace(/^/gm," ".repeat(2))}let Z=[`Usage: ${q.commandUsage($)}`,""],_=q.commandDescription($);if(_.length>0)Z=Z.concat([q.wrap(_,z,0),""]);let U=q.visibleArguments($).map((W)=>{return X(q.argumentTerm(W),q.argumentDescription(W))});if(U.length>0)Z=Z.concat(["Arguments:",Y(U),""]);let G=q.visibleOptions($).map((W)=>{return X(q.optionTerm(W),q.optionDescription(W))});if(G.length>0)Z=Z.concat(["Options:",Y(G),""]);if(this.showGlobalOptions){let W=q.visibleGlobalOptions($).map((N)=>{return X(q.optionTerm(N),q.optionDescription(N))});if(W.length>0)Z=Z.concat(["Global Options:",Y(W),""])}let L=q.visibleCommands($).map((W)=>{return X(q.subcommandTerm(W),q.subcommandDescription(W))});if(L.length>0)Z=Z.concat(["Commands:",Y(L),""]);return Z.join(`
5
+ `)}padWidth($,q){return Math.max(q.longestOptionTermLength($,q),q.longestGlobalOptionTermLength($,q),q.longestSubcommandTermLength($,q),q.longestArgumentTermLength($,q))}wrap($,q,Q,z=40){let M=new RegExp(`[\\n][${" \\f\\t\\v\xA0\u1680\u2000-\u200A\u202F\u205F\u3000\uFEFF"}]+`);if($.match(M))return $;let X=q-Q;if(X<z)return $;let Y=$.slice(0,Q),Z=$.slice(Q).replace(`\r
6
+ `,`
7
+ `),_=" ".repeat(Q),G=`\\s${"\u200B"}`,L=new RegExp(`
8
+ |.{1,${X-1}}([${G}]|$)|[^${G}]+?([${G}]|$)`,"g"),W=Z.match(L)||[];return Y+W.map((N,g)=>{if(N===`
9
+ `)return"";return(g>0?_:"")+N.trimEnd()}).join(`
10
+ `)}}n0.Help=Y0});var m=V((q1)=>{var{InvalidArgumentError:e0}=k();class X0{constructor($,q){this.flags=$,this.description=q||"",this.required=$.includes("<"),this.optional=$.includes("["),this.variadic=/\w\.\.\.[>\]]$/.test($),this.mandatory=!1;let Q=$1($);if(this.short=Q.shortFlag,this.long=Q.longFlag,this.negate=!1,this.long)this.negate=this.long.startsWith("--no-");this.defaultValue=void 0,this.defaultValueDescription=void 0,this.presetArg=void 0,this.envVar=void 0,this.parseArg=void 0,this.hidden=!1,this.argChoices=void 0,this.conflictsWith=[],this.implied=void 0}default($,q){return this.defaultValue=$,this.defaultValueDescription=q,this}preset($){return this.presetArg=$,this}conflicts($){return this.conflictsWith=this.conflictsWith.concat($),this}implies($){let q=$;if(typeof $==="string")q={[$]:!0};return this.implied=Object.assign(this.implied||{},q),this}env($){return this.envVar=$,this}argParser($){return this.parseArg=$,this}makeOptionMandatory($=!0){return this.mandatory=!!$,this}hideHelp($=!0){return this.hidden=!!$,this}_concatValue($,q){if(q===this.defaultValue||!Array.isArray(q))return[$];return q.concat($)}choices($){return this.argChoices=$.slice(),this.parseArg=(q,Q)=>{if(!this.argChoices.includes(q))throw new e0(`Allowed choices are ${this.argChoices.join(", ")}.`);if(this.variadic)return this._concatValue(q,Q);return q},this}name(){if(this.long)return this.long.replace(/^--/,"");return this.short.replace(/^-/,"")}attributeName(){return o0(this.name().replace(/^no-/,""))}is($){return this.short===$||this.long===$}isBoolean(){return!this.required&&!this.optional&&!this.negate}}class Z0{constructor($){this.positiveOptions=new Map,this.negativeOptions=new Map,this.dualOptions=new Set,$.forEach((q)=>{if(q.negate)this.negativeOptions.set(q.attributeName(),q);else this.positiveOptions.set(q.attributeName(),q)}),this.negativeOptions.forEach((q,Q)=>{if(this.positiveOptions.has(Q))this.dualOptions.add(Q)})}valueFromOption($,q){let Q=q.attributeName();if(!this.dualOptions.has(Q))return!0;let z=this.negativeOptions.get(Q).presetArg,J=z!==void 0?z:!1;return q.negate===(J===$)}}function o0($){return $.split("-").reduce((q,Q)=>{return q+Q[0].toUpperCase()+Q.slice(1)})}function $1($){let q,Q,z=$.split(/[ |,]+/);if(z.length>1&&!/^[[<]/.test(z[1]))q=z.shift();if(Q=z.shift(),!q&&/^-[^-]$/.test(Q))q=Q,Q=void 0;return{shortFlag:q,longFlag:Q}}q1.Option=X0;q1.DualOptions=Z0});var _0=V((Y1)=>{function J1($,q){if(Math.abs($.length-q.length)>3)return Math.max($.length,q.length);let Q=[];for(let z=0;z<=$.length;z++)Q[z]=[z];for(let z=0;z<=q.length;z++)Q[0][z]=z;for(let z=1;z<=q.length;z++)for(let J=1;J<=$.length;J++){let M=1;if($[J-1]===q[z-1])M=0;else M=1;if(Q[J][z]=Math.min(Q[J-1][z]+1,Q[J][z-1]+1,Q[J-1][z-1]+M),J>1&&z>1&&$[J-1]===q[z-2]&&$[J-2]===q[z-1])Q[J][z]=Math.min(Q[J][z],Q[J-2][z-2]+1)}return Q[$.length][q.length]}function M1($,q){if(!q||q.length===0)return"";q=Array.from(new Set(q));let Q=$.startsWith("--");if(Q)$=$.slice(2),q=q.map((X)=>X.slice(2));let z=[],J=3,M=0.4;if(q.forEach((X)=>{if(X.length<=1)return;let Y=J1($,X),Z=Math.max($.length,X.length);if((Z-Y)/Z>M){if(Y<J)J=Y,z=[X];else if(Y===J)z.push(X)}}),z.sort((X,Y)=>X.localeCompare(Y)),Q)z=z.map((X)=>`--${X}`);if(z.length>1)return`
11
+ (Did you mean one of ${z.join(", ")}?)`;if(z.length===1)return`
12
+ (Did you mean ${z[0]}?)`;return""}Y1.suggestSimilar=M1});var W0=V((W1)=>{var Z1=E("events").EventEmitter,d=E("child_process"),j=E("path"),r=E("fs"),H=E("process"),{Argument:_1,humanReadableArgName:U1}=x(),{CommanderError:s}=k(),{Help:B1}=l(),{Option:U0,DualOptions:K1}=m(),{suggestSimilar:B0}=_0();class i extends Z1{constructor($){super();this.commands=[],this.options=[],this.parent=null,this._allowUnknownOption=!1,this._allowExcessArguments=!0,this.registeredArguments=[],this._args=this.registeredArguments,this.args=[],this.rawArgs=[],this.processedArgs=[],this._scriptPath=null,this._name=$||"",this._optionValues={},this._optionValueSources={},this._storeOptionsAsProperties=!1,this._actionHandler=null,this._executableHandler=!1,this._executableFile=null,this._executableDir=null,this._defaultCommandName=null,this._exitCallback=null,this._aliases=[],this._combineFlagAndOptionalValue=!0,this._description="",this._summary="",this._argsDescription=void 0,this._enablePositionalOptions=!1,this._passThroughOptions=!1,this._lifeCycleHooks={},this._showHelpAfterError=!1,this._showSuggestionAfterError=!0,this._outputConfiguration={writeOut:(q)=>H.stdout.write(q),writeErr:(q)=>H.stderr.write(q),getOutHelpWidth:()=>H.stdout.isTTY?H.stdout.columns:void 0,getErrHelpWidth:()=>H.stderr.isTTY?H.stderr.columns:void 0,outputError:(q,Q)=>Q(q)},this._hidden=!1,this._helpOption=void 0,this._addImplicitHelpCommand=void 0,this._helpCommand=void 0,this._helpConfiguration={}}copyInheritedSettings($){return this._outputConfiguration=$._outputConfiguration,this._helpOption=$._helpOption,this._helpCommand=$._helpCommand,this._helpConfiguration=$._helpConfiguration,this._exitCallback=$._exitCallback,this._storeOptionsAsProperties=$._storeOptionsAsProperties,this._combineFlagAndOptionalValue=$._combineFlagAndOptionalValue,this._allowExcessArguments=$._allowExcessArguments,this._enablePositionalOptions=$._enablePositionalOptions,this._showHelpAfterError=$._showHelpAfterError,this._showSuggestionAfterError=$._showSuggestionAfterError,this}_getCommandAndAncestors(){let $=[];for(let q=this;q;q=q.parent)$.push(q);return $}command($,q,Q){let z=q,J=Q;if(typeof z==="object"&&z!==null)J=z,z=null;J=J||{};let[,M,X]=$.match(/([^ ]+) *(.*)/),Y=this.createCommand(M);if(z)Y.description(z),Y._executableHandler=!0;if(J.isDefault)this._defaultCommandName=Y._name;if(Y._hidden=!!(J.noHelp||J.hidden),Y._executableFile=J.executableFile||null,X)Y.arguments(X);if(this._registerCommand(Y),Y.parent=this,Y.copyInheritedSettings(this),z)return this;return Y}createCommand($){return new i($)}createHelp(){return Object.assign(new B1,this.configureHelp())}configureHelp($){if($===void 0)return this._helpConfiguration;return this._helpConfiguration=$,this}configureOutput($){if($===void 0)return this._outputConfiguration;return Object.assign(this._outputConfiguration,$),this}showHelpAfterError($=!0){if(typeof $!=="string")$=!!$;return this._showHelpAfterError=$,this}showSuggestionAfterError($=!0){return this._showSuggestionAfterError=!!$,this}addCommand($,q){if(!$._name)throw Error(`Command passed to .addCommand() must have a name
13
+ - specify the name in Command constructor or using .name()`);if(q=q||{},q.isDefault)this._defaultCommandName=$._name;if(q.noHelp||q.hidden)$._hidden=!0;return this._registerCommand($),$.parent=this,$._checkForBrokenPassThrough(),this}createArgument($,q){return new _1($,q)}argument($,q,Q,z){let J=this.createArgument($,q);if(typeof Q==="function")J.default(z).argParser(Q);else J.default(Q);return this.addArgument(J),this}arguments($){return $.trim().split(/ +/).forEach((q)=>{this.argument(q)}),this}addArgument($){let q=this.registeredArguments.slice(-1)[0];if(q&&q.variadic)throw Error(`only the last argument can be variadic '${q.name()}'`);if($.required&&$.defaultValue!==void 0&&$.parseArg===void 0)throw Error(`a default value for a required argument is never used: '${$.name()}'`);return this.registeredArguments.push($),this}helpCommand($,q){if(typeof $==="boolean")return this._addImplicitHelpCommand=$,this;$=$??"help [command]";let[,Q,z]=$.match(/([^ ]+) *(.*)/),J=q??"display help for command",M=this.createCommand(Q);if(M.helpOption(!1),z)M.arguments(z);if(J)M.description(J);return this._addImplicitHelpCommand=!0,this._helpCommand=M,this}addHelpCommand($,q){if(typeof $!=="object")return this.helpCommand($,q),this;return this._addImplicitHelpCommand=!0,this._helpCommand=$,this}_getHelpCommand(){if(this._addImplicitHelpCommand??(this.commands.length&&!this._actionHandler&&!this._findCommand("help"))){if(this._helpCommand===void 0)this.helpCommand(void 0,void 0);return this._helpCommand}return null}hook($,q){let Q=["preSubcommand","preAction","postAction"];if(!Q.includes($))throw Error(`Unexpected value for event passed to hook : '${$}'.
14
+ Expecting one of '${Q.join("', '")}'`);if(this._lifeCycleHooks[$])this._lifeCycleHooks[$].push(q);else this._lifeCycleHooks[$]=[q];return this}exitOverride($){if($)this._exitCallback=$;else this._exitCallback=(q)=>{if(q.code!=="commander.executeSubCommandAsync")throw q};return this}_exit($,q,Q){if(this._exitCallback)this._exitCallback(new s($,q,Q));H.exit($)}action($){let q=(Q)=>{let z=this.registeredArguments.length,J=Q.slice(0,z);if(this._storeOptionsAsProperties)J[z]=this;else J[z]=this.opts();return J.push(this),$.apply(this,J)};return this._actionHandler=q,this}createOption($,q){return new U0($,q)}_callParseArg($,q,Q,z){try{return $.parseArg(q,Q)}catch(J){if(J.code==="commander.invalidArgument"){let M=`${z} ${J.message}`;this.error(M,{exitCode:J.exitCode,code:J.code})}throw J}}_registerOption($){let q=$.short&&this._findOption($.short)||$.long&&this._findOption($.long);if(q){let Q=$.long&&this._findOption($.long)?$.long:$.short;throw Error(`Cannot add option '${$.flags}'${this._name&&` to command '${this._name}'`} due to conflicting flag '${Q}'
15
+ - already used by option '${q.flags}'`)}this.options.push($)}_registerCommand($){let q=(z)=>{return[z.name()].concat(z.aliases())},Q=q($).find((z)=>this._findCommand(z));if(Q){let z=q(this._findCommand(Q)).join("|"),J=q($).join("|");throw Error(`cannot add command '${J}' as already have command '${z}'`)}this.commands.push($)}addOption($){this._registerOption($);let q=$.name(),Q=$.attributeName();if($.negate){let J=$.long.replace(/^--no-/,"--");if(!this._findOption(J))this.setOptionValueWithSource(Q,$.defaultValue===void 0?!0:$.defaultValue,"default")}else if($.defaultValue!==void 0)this.setOptionValueWithSource(Q,$.defaultValue,"default");let z=(J,M,X)=>{if(J==null&&$.presetArg!==void 0)J=$.presetArg;let Y=this.getOptionValue(Q);if(J!==null&&$.parseArg)J=this._callParseArg($,J,Y,M);else if(J!==null&&$.variadic)J=$._concatValue(J,Y);if(J==null)if($.negate)J=!1;else if($.isBoolean()||$.optional)J=!0;else J="";this.setOptionValueWithSource(Q,J,X)};if(this.on("option:"+q,(J)=>{let M=`error: option '${$.flags}' argument '${J}' is invalid.`;z(J,M,"cli")}),$.envVar)this.on("optionEnv:"+q,(J)=>{let M=`error: option '${$.flags}' value '${J}' from env '${$.envVar}' is invalid.`;z(J,M,"env")});return this}_optionEx($,q,Q,z,J){if(typeof q==="object"&&q instanceof U0)throw Error("To add an Option object use addOption() instead of option() or requiredOption()");let M=this.createOption(q,Q);if(M.makeOptionMandatory(!!$.mandatory),typeof z==="function")M.default(J).argParser(z);else if(z instanceof RegExp){let X=z;z=(Y,Z)=>{let _=X.exec(Y);return _?_[0]:Z},M.default(J).argParser(z)}else M.default(z);return this.addOption(M)}option($,q,Q,z){return this._optionEx({},$,q,Q,z)}requiredOption($,q,Q,z){return this._optionEx({mandatory:!0},$,q,Q,z)}combineFlagAndOptionalValue($=!0){return this._combineFlagAndOptionalValue=!!$,this}allowUnknownOption($=!0){return this._allowUnknownOption=!!$,this}allowExcessArguments($=!0){return this._allowExcessArguments=!!$,this}enablePositionalOptions($=!0){return this._enablePositionalOptions=!!$,this}passThroughOptions($=!0){return this._passThroughOptions=!!$,this._checkForBrokenPassThrough(),this}_checkForBrokenPassThrough(){if(this.parent&&this._passThroughOptions&&!this.parent._enablePositionalOptions)throw Error(`passThroughOptions cannot be used for '${this._name}' without turning on enablePositionalOptions for parent command(s)`)}storeOptionsAsProperties($=!0){if(this.options.length)throw Error("call .storeOptionsAsProperties() before adding options");if(Object.keys(this._optionValues).length)throw Error("call .storeOptionsAsProperties() before setting option values");return this._storeOptionsAsProperties=!!$,this}getOptionValue($){if(this._storeOptionsAsProperties)return this[$];return this._optionValues[$]}setOptionValue($,q){return this.setOptionValueWithSource($,q,void 0)}setOptionValueWithSource($,q,Q){if(this._storeOptionsAsProperties)this[$]=q;else this._optionValues[$]=q;return this._optionValueSources[$]=Q,this}getOptionValueSource($){return this._optionValueSources[$]}getOptionValueSourceWithGlobals($){let q;return this._getCommandAndAncestors().forEach((Q)=>{if(Q.getOptionValueSource($)!==void 0)q=Q.getOptionValueSource($)}),q}_prepareUserArgs($,q){if($!==void 0&&!Array.isArray($))throw Error("first parameter to parse must be array or undefined");if(q=q||{},$===void 0&&q.from===void 0){if(H.versions?.electron)q.from="electron";let z=H.execArgv??[];if(z.includes("-e")||z.includes("--eval")||z.includes("-p")||z.includes("--print"))q.from="eval"}if($===void 0)$=H.argv;this.rawArgs=$.slice();let Q;switch(q.from){case void 0:case"node":this._scriptPath=$[1],Q=$.slice(2);break;case"electron":if(H.defaultApp)this._scriptPath=$[1],Q=$.slice(2);else Q=$.slice(1);break;case"user":Q=$.slice(0);break;case"eval":Q=$.slice(1);break;default:throw Error(`unexpected parse option { from: '${q.from}' }`)}if(!this._name&&this._scriptPath)this.nameFromFilename(this._scriptPath);return this._name=this._name||"program",Q}parse($,q){let Q=this._prepareUserArgs($,q);return this._parseCommand([],Q),this}async parseAsync($,q){let Q=this._prepareUserArgs($,q);return await this._parseCommand([],Q),this}_executeSubCommand($,q){q=q.slice();let Q=!1,z=[".js",".ts",".tsx",".mjs",".cjs"];function J(_,U){let G=j.resolve(_,U);if(r.existsSync(G))return G;if(z.includes(j.extname(U)))return;let L=z.find((W)=>r.existsSync(`${G}${W}`));if(L)return`${G}${L}`;return}this._checkForMissingMandatoryOptions(),this._checkForConflictingOptions();let M=$._executableFile||`${this._name}-${$._name}`,X=this._executableDir||"";if(this._scriptPath){let _;try{_=r.realpathSync(this._scriptPath)}catch(U){_=this._scriptPath}X=j.resolve(j.dirname(_),X)}if(X){let _=J(X,M);if(!_&&!$._executableFile&&this._scriptPath){let U=j.basename(this._scriptPath,j.extname(this._scriptPath));if(U!==this._name)_=J(X,`${U}-${$._name}`)}M=_||M}Q=z.includes(j.extname(M));let Y;if(H.platform!=="win32")if(Q)q.unshift(M),q=K0(H.execArgv).concat(q),Y=d.spawn(H.argv[0],q,{stdio:"inherit"});else Y=d.spawn(M,q,{stdio:"inherit"});else q.unshift(M),q=K0(H.execArgv).concat(q),Y=d.spawn(H.execPath,q,{stdio:"inherit"});if(!Y.killed)["SIGUSR1","SIGUSR2","SIGTERM","SIGINT","SIGHUP"].forEach((U)=>{H.on(U,()=>{if(Y.killed===!1&&Y.exitCode===null)Y.kill(U)})});let Z=this._exitCallback;Y.on("close",(_)=>{if(_=_??1,!Z)H.exit(_);else Z(new s(_,"commander.executeSubCommandAsync","(close)"))}),Y.on("error",(_)=>{if(_.code==="ENOENT"){let U=X?`searched for local subcommand relative to directory '${X}'`:"no directory for search for local subcommand, use .executableDir() to supply a custom directory",G=`'${M}' does not exist
16
+ - if '${$._name}' is not meant to be an executable command, remove description parameter from '.command()' and use '.description()' instead
17
+ - if the default executable name is not suitable, use the executableFile option to supply a custom name or path
18
+ - ${U}`;throw Error(G)}else if(_.code==="EACCES")throw Error(`'${M}' not executable`);if(!Z)H.exit(1);else{let U=new s(1,"commander.executeSubCommandAsync","(error)");U.nestedError=_,Z(U)}}),this.runningCommand=Y}_dispatchSubcommand($,q,Q){let z=this._findCommand($);if(!z)this.help({error:!0});let J;return J=this._chainOrCallSubCommandHook(J,z,"preSubcommand"),J=this._chainOrCall(J,()=>{if(z._executableHandler)this._executeSubCommand(z,q.concat(Q));else return z._parseCommand(q,Q)}),J}_dispatchHelpCommand($){if(!$)this.help();let q=this._findCommand($);if(q&&!q._executableHandler)q.help();return this._dispatchSubcommand($,[],[this._getHelpOption()?.long??this._getHelpOption()?.short??"--help"])}_checkNumberOfArguments(){if(this.registeredArguments.forEach(($,q)=>{if($.required&&this.args[q]==null)this.missingArgument($.name())}),this.registeredArguments.length>0&&this.registeredArguments[this.registeredArguments.length-1].variadic)return;if(this.args.length>this.registeredArguments.length)this._excessArguments(this.args)}_processArguments(){let $=(Q,z,J)=>{let M=z;if(z!==null&&Q.parseArg){let X=`error: command-argument value '${z}' is invalid for argument '${Q.name()}'.`;M=this._callParseArg(Q,z,J,X)}return M};this._checkNumberOfArguments();let q=[];this.registeredArguments.forEach((Q,z)=>{let J=Q.defaultValue;if(Q.variadic){if(z<this.args.length){if(J=this.args.slice(z),Q.parseArg)J=J.reduce((M,X)=>{return $(Q,X,M)},Q.defaultValue)}else if(J===void 0)J=[]}else if(z<this.args.length){if(J=this.args[z],Q.parseArg)J=$(Q,J,Q.defaultValue)}q[z]=J}),this.processedArgs=q}_chainOrCall($,q){if($&&$.then&&typeof $.then==="function")return $.then(()=>q());return q()}_chainOrCallHooks($,q){let Q=$,z=[];if(this._getCommandAndAncestors().reverse().filter((J)=>J._lifeCycleHooks[q]!==void 0).forEach((J)=>{J._lifeCycleHooks[q].forEach((M)=>{z.push({hookedCommand:J,callback:M})})}),q==="postAction")z.reverse();return z.forEach((J)=>{Q=this._chainOrCall(Q,()=>{return J.callback(J.hookedCommand,this)})}),Q}_chainOrCallSubCommandHook($,q,Q){let z=$;if(this._lifeCycleHooks[Q]!==void 0)this._lifeCycleHooks[Q].forEach((J)=>{z=this._chainOrCall(z,()=>{return J(this,q)})});return z}_parseCommand($,q){let Q=this.parseOptions(q);if(this._parseOptionsEnv(),this._parseOptionsImplied(),$=$.concat(Q.operands),q=Q.unknown,this.args=$.concat(q),$&&this._findCommand($[0]))return this._dispatchSubcommand($[0],$.slice(1),q);if(this._getHelpCommand()&&$[0]===this._getHelpCommand().name())return this._dispatchHelpCommand($[1]);if(this._defaultCommandName)return this._outputHelpIfRequested(q),this._dispatchSubcommand(this._defaultCommandName,$,q);if(this.commands.length&&this.args.length===0&&!this._actionHandler&&!this._defaultCommandName)this.help({error:!0});this._outputHelpIfRequested(Q.unknown),this._checkForMissingMandatoryOptions(),this._checkForConflictingOptions();let z=()=>{if(Q.unknown.length>0)this.unknownOption(Q.unknown[0])},J=`command:${this.name()}`;if(this._actionHandler){z(),this._processArguments();let M;if(M=this._chainOrCallHooks(M,"preAction"),M=this._chainOrCall(M,()=>this._actionHandler(this.processedArgs)),this.parent)M=this._chainOrCall(M,()=>{this.parent.emit(J,$,q)});return M=this._chainOrCallHooks(M,"postAction"),M}if(this.parent&&this.parent.listenerCount(J))z(),this._processArguments(),this.parent.emit(J,$,q);else if($.length){if(this._findCommand("*"))return this._dispatchSubcommand("*",$,q);if(this.listenerCount("command:*"))this.emit("command:*",$,q);else if(this.commands.length)this.unknownCommand();else z(),this._processArguments()}else if(this.commands.length)z(),this.help({error:!0});else z(),this._processArguments()}_findCommand($){if(!$)return;return this.commands.find((q)=>q._name===$||q._aliases.includes($))}_findOption($){return this.options.find((q)=>q.is($))}_checkForMissingMandatoryOptions(){this._getCommandAndAncestors().forEach(($)=>{$.options.forEach((q)=>{if(q.mandatory&&$.getOptionValue(q.attributeName())===void 0)$.missingMandatoryOptionValue(q)})})}_checkForConflictingLocalOptions(){let $=this.options.filter((Q)=>{let z=Q.attributeName();if(this.getOptionValue(z)===void 0)return!1;return this.getOptionValueSource(z)!=="default"});$.filter((Q)=>Q.conflictsWith.length>0).forEach((Q)=>{let z=$.find((J)=>Q.conflictsWith.includes(J.attributeName()));if(z)this._conflictingOption(Q,z)})}_checkForConflictingOptions(){this._getCommandAndAncestors().forEach(($)=>{$._checkForConflictingLocalOptions()})}parseOptions($){let q=[],Q=[],z=q,J=$.slice();function M(Y){return Y.length>1&&Y[0]==="-"}let X=null;while(J.length){let Y=J.shift();if(Y==="--"){if(z===Q)z.push(Y);z.push(...J);break}if(X&&!M(Y)){this.emit(`option:${X.name()}`,Y);continue}if(X=null,M(Y)){let Z=this._findOption(Y);if(Z){if(Z.required){let _=J.shift();if(_===void 0)this.optionMissingArgument(Z);this.emit(`option:${Z.name()}`,_)}else if(Z.optional){let _=null;if(J.length>0&&!M(J[0]))_=J.shift();this.emit(`option:${Z.name()}`,_)}else this.emit(`option:${Z.name()}`);X=Z.variadic?Z:null;continue}}if(Y.length>2&&Y[0]==="-"&&Y[1]!=="-"){let Z=this._findOption(`-${Y[1]}`);if(Z){if(Z.required||Z.optional&&this._combineFlagAndOptionalValue)this.emit(`option:${Z.name()}`,Y.slice(2));else this.emit(`option:${Z.name()}`),J.unshift(`-${Y.slice(2)}`);continue}}if(/^--[^=]+=/.test(Y)){let Z=Y.indexOf("="),_=this._findOption(Y.slice(0,Z));if(_&&(_.required||_.optional)){this.emit(`option:${_.name()}`,Y.slice(Z+1));continue}}if(M(Y))z=Q;if((this._enablePositionalOptions||this._passThroughOptions)&&q.length===0&&Q.length===0){if(this._findCommand(Y)){if(q.push(Y),J.length>0)Q.push(...J);break}else if(this._getHelpCommand()&&Y===this._getHelpCommand().name()){if(q.push(Y),J.length>0)q.push(...J);break}else if(this._defaultCommandName){if(Q.push(Y),J.length>0)Q.push(...J);break}}if(this._passThroughOptions){if(z.push(Y),J.length>0)z.push(...J);break}z.push(Y)}return{operands:q,unknown:Q}}opts(){if(this._storeOptionsAsProperties){let $={},q=this.options.length;for(let Q=0;Q<q;Q++){let z=this.options[Q].attributeName();$[z]=z===this._versionOptionName?this._version:this[z]}return $}return this._optionValues}optsWithGlobals(){return this._getCommandAndAncestors().reduce(($,q)=>Object.assign($,q.opts()),{})}error($,q){if(this._outputConfiguration.outputError(`${$}
19
+ `,this._outputConfiguration.writeErr),typeof this._showHelpAfterError==="string")this._outputConfiguration.writeErr(`${this._showHelpAfterError}
20
+ `);else if(this._showHelpAfterError)this._outputConfiguration.writeErr(`
21
+ `),this.outputHelp({error:!0});let Q=q||{},z=Q.exitCode||1,J=Q.code||"commander.error";this._exit(z,J,$)}_parseOptionsEnv(){this.options.forEach(($)=>{if($.envVar&&$.envVar in H.env){let q=$.attributeName();if(this.getOptionValue(q)===void 0||["default","config","env"].includes(this.getOptionValueSource(q)))if($.required||$.optional)this.emit(`optionEnv:${$.name()}`,H.env[$.envVar]);else this.emit(`optionEnv:${$.name()}`)}})}_parseOptionsImplied(){let $=new K1(this.options),q=(Q)=>{return this.getOptionValue(Q)!==void 0&&!["default","implied"].includes(this.getOptionValueSource(Q))};this.options.filter((Q)=>Q.implied!==void 0&&q(Q.attributeName())&&$.valueFromOption(this.getOptionValue(Q.attributeName()),Q)).forEach((Q)=>{Object.keys(Q.implied).filter((z)=>!q(z)).forEach((z)=>{this.setOptionValueWithSource(z,Q.implied[z],"implied")})})}missingArgument($){let q=`error: missing required argument '${$}'`;this.error(q,{code:"commander.missingArgument"})}optionMissingArgument($){let q=`error: option '${$.flags}' argument missing`;this.error(q,{code:"commander.optionMissingArgument"})}missingMandatoryOptionValue($){let q=`error: required option '${$.flags}' not specified`;this.error(q,{code:"commander.missingMandatoryOptionValue"})}_conflictingOption($,q){let Q=(M)=>{let X=M.attributeName(),Y=this.getOptionValue(X),Z=this.options.find((U)=>U.negate&&X===U.attributeName()),_=this.options.find((U)=>!U.negate&&X===U.attributeName());if(Z&&(Z.presetArg===void 0&&Y===!1||Z.presetArg!==void 0&&Y===Z.presetArg))return Z;return _||M},z=(M)=>{let X=Q(M),Y=X.attributeName();if(this.getOptionValueSource(Y)==="env")return`environment variable '${X.envVar}'`;return`option '${X.flags}'`},J=`error: ${z($)} cannot be used with ${z(q)}`;this.error(J,{code:"commander.conflictingOption"})}unknownOption($){if(this._allowUnknownOption)return;let q="";if($.startsWith("--")&&this._showSuggestionAfterError){let z=[],J=this;do{let M=J.createHelp().visibleOptions(J).filter((X)=>X.long).map((X)=>X.long);z=z.concat(M),J=J.parent}while(J&&!J._enablePositionalOptions);q=B0($,z)}let Q=`error: unknown option '${$}'${q}`;this.error(Q,{code:"commander.unknownOption"})}_excessArguments($){if(this._allowExcessArguments)return;let q=this.registeredArguments.length,Q=q===1?"":"s",J=`error: too many arguments${this.parent?` for '${this.name()}'`:""}. Expected ${q} argument${Q} but got ${$.length}.`;this.error(J,{code:"commander.excessArguments"})}unknownCommand(){let $=this.args[0],q="";if(this._showSuggestionAfterError){let z=[];this.createHelp().visibleCommands(this).forEach((J)=>{if(z.push(J.name()),J.alias())z.push(J.alias())}),q=B0($,z)}let Q=`error: unknown command '${$}'${q}`;this.error(Q,{code:"commander.unknownCommand"})}version($,q,Q){if($===void 0)return this._version;this._version=$,q=q||"-V, --version",Q=Q||"output the version number";let z=this.createOption(q,Q);return this._versionOptionName=z.attributeName(),this._registerOption(z),this.on("option:"+z.name(),()=>{this._outputConfiguration.writeOut(`${$}
22
+ `),this._exit(0,"commander.version",$)}),this}description($,q){if($===void 0&&q===void 0)return this._description;if(this._description=$,q)this._argsDescription=q;return this}summary($){if($===void 0)return this._summary;return this._summary=$,this}alias($){if($===void 0)return this._aliases[0];let q=this;if(this.commands.length!==0&&this.commands[this.commands.length-1]._executableHandler)q=this.commands[this.commands.length-1];if($===q._name)throw Error("Command alias can't be the same as its name");let Q=this.parent?._findCommand($);if(Q){let z=[Q.name()].concat(Q.aliases()).join("|");throw Error(`cannot add alias '${$}' to command '${this.name()}' as already have command '${z}'`)}return q._aliases.push($),this}aliases($){if($===void 0)return this._aliases;return $.forEach((q)=>this.alias(q)),this}usage($){if($===void 0){if(this._usage)return this._usage;let q=this.registeredArguments.map((Q)=>{return U1(Q)});return[].concat(this.options.length||this._helpOption!==null?"[options]":[],this.commands.length?"[command]":[],this.registeredArguments.length?q:[]).join(" ")}return this._usage=$,this}name($){if($===void 0)return this._name;return this._name=$,this}nameFromFilename($){return this._name=j.basename($,j.extname($)),this}executableDir($){if($===void 0)return this._executableDir;return this._executableDir=$,this}helpInformation($){let q=this.createHelp();if(q.helpWidth===void 0)q.helpWidth=$&&$.error?this._outputConfiguration.getErrHelpWidth():this._outputConfiguration.getOutHelpWidth();return q.formatHelp(this,q)}_getHelpContext($){$=$||{};let q={error:!!$.error},Q;if(q.error)Q=(z)=>this._outputConfiguration.writeErr(z);else Q=(z)=>this._outputConfiguration.writeOut(z);return q.write=$.write||Q,q.command=this,q}outputHelp($){let q;if(typeof $==="function")q=$,$=void 0;let Q=this._getHelpContext($);this._getCommandAndAncestors().reverse().forEach((J)=>J.emit("beforeAllHelp",Q)),this.emit("beforeHelp",Q);let z=this.helpInformation(Q);if(q){if(z=q(z),typeof z!=="string"&&!Buffer.isBuffer(z))throw Error("outputHelp callback must return a string or a Buffer")}if(Q.write(z),this._getHelpOption()?.long)this.emit(this._getHelpOption().long);this.emit("afterHelp",Q),this._getCommandAndAncestors().forEach((J)=>J.emit("afterAllHelp",Q))}helpOption($,q){if(typeof $==="boolean"){if($)this._helpOption=this._helpOption??void 0;else this._helpOption=null;return this}return $=$??"-h, --help",q=q??"display help for command",this._helpOption=this.createOption($,q),this}_getHelpOption(){if(this._helpOption===void 0)this.helpOption(void 0,void 0);return this._helpOption}addHelpOption($){return this._helpOption=$,this}help($){this.outputHelp($);let q=H.exitCode||0;if(q===0&&$&&typeof $!=="function"&&$.error)q=1;this._exit(q,"commander.help","(outputHelp)")}addHelpText($,q){let Q=["beforeAll","before","after","afterAll"];if(!Q.includes($))throw Error(`Unexpected value for position to addHelpText.
23
+ Expecting one of '${Q.join("', '")}'`);let z=`${$}Help`;return this.on(z,(J)=>{let M;if(typeof q==="function")M=q({error:J.error,command:J.command});else M=q;if(M)J.write(`${M}
24
+ `)}),this}_outputHelpIfRequested($){let q=this._getHelpOption();if(q&&$.find((z)=>q.is(z)))this.outputHelp(),this._exit(0,"commander.helpDisplayed","(outputHelp)")}}function K0($){return $.map((q)=>{if(!q.startsWith("--inspect"))return q;let Q,z="127.0.0.1",J="9229",M;if((M=q.match(/^(--inspect(-brk)?)$/))!==null)Q=M[1];else if((M=q.match(/^(--inspect(-brk|-port)?)=([^:]+)$/))!==null)if(Q=M[1],/^\d+$/.test(M[3]))J=M[3];else z=M[3];else if((M=q.match(/^(--inspect(-brk|-port)?)=([^:]+):(\d+)$/))!==null)Q=M[1],z=M[3],J=M[4];if(Q&&J!=="0")return`${Q}=${z}:${parseInt(J)+1}`;return q})}W1.Command=i});var L0=V((L1)=>{var{Argument:G0}=x(),{Command:p}=W0(),{CommanderError:H1,InvalidArgumentError:H0}=k(),{Help:R1}=l(),{Option:R0}=m();L1.program=new p;L1.createCommand=($)=>new p($);L1.createOption=($,q)=>new R0($,q);L1.createArgument=($,q)=>new G0($,q);L1.Command=p;L1.Option=R0;L1.Argument=G0;L1.Help=R1;L1.CommanderError=H1;L1.InvalidArgumentError=H0;L1.InvalidOptionArgumentError=H0});import{spawnSync as C0}from"child_process";import{cpSync as u,existsSync as T,mkdirSync as A,readFileSync as h,rmSync as v}from"fs";import{homedir as F}from"os";import{dirname as $0,join as K}from"path";import{fileURLToPath as m1}from"url";var T0=g0(L0(),1),{program:q$,createCommand:Q$,createArgument:z$,createOption:J$,CommanderError:M$,InvalidArgumentError:Y$,InvalidOptionArgumentError:X$,Command:E0,Argument:Z$,Option:_$,Help:U$}=T0.default;function n($){return $.map((q)=>Number(q.close??q.c)).filter(Number.isFinite)}function y0($,q){return $.map((Q,z)=>{if(z+1<q)return null;let J=$.slice(z+1-q,z+1);return w(J)})}function t($,q){let Q=2/(q+1),z=null;return $.map((J,M)=>{return z=M===0||z===null?J:J*Q+z*(1-Q),z})}function I0($,q=14){return $.map((Q,z)=>{if(z<q)return null;let J=$.slice(z+1-q,z+1).map((Z,_,U)=>_===0?0:Z-U[_-1]),M=J.filter((Z)=>Z>0),X=J.filter((Z)=>Z<0).map(Math.abs);return 100-100/(1+w(M)/(w(X)||0.000000001))})}function P0($){let q=t($,12),Q=t($,26),z=q.map((M,X)=>M-Q[X]),J=t(z,9);return z.map((M,X)=>({macd:M,signal:J[X],histogram:M-J[X]}))}function j0($,q=0){let Q=$.slice(1).map((Y,Z)=>Y/$[Z]-1).filter(Number.isFinite),z=w(Q),J=w1(Q)*Math.sqrt(252),M=z*252,X=J===0?null:(M-q)/J;return{count:$.length,annualReturn:M,volatility:J,sharpe:X,maxDrawdown:f1($)}}function w($){return $.length?$.reduce((q,Q)=>q+Q,0)/$.length:0}function w1($){let q=w($);return Math.sqrt(w($.map((Q)=>(Q-q)**2)))}function f1($){let q=$[0]??0,Q=0;for(let z of $)q=Math.max(q,z),Q=Math.min(Q,z/q-1);return Q}import{mkdir as A1,readFile as b1,rm as k1,writeFile as C1}from"fs/promises";import{dirname as x1,join as O1}from"path";var h1=process.env.HOME??process.cwd(),D=O1(h1,".config","mozyfin-cli","config.json"),C="https://api.mozyfin.com";async function a(){try{return JSON.parse(await b1(D,"utf8"))}catch{return{}}}async function F0($){await A1(x1(D),{recursive:!0}),await C1(D,`${JSON.stringify($,null,2)}
25
+ `,{mode:384})}async function N0(){await k1(D,{force:!0})}async function V0($){let q=await a();return $??process.env.MOZYFIN_API_KEY??q.apiKey}function D0(){return"Missing API key. Run `mozyfin login --api-key <key>` or create one at https://research.mozyfin.com/settings"}var S0=0;async function v1($=Date.now()){let q=Math.max(0,1000-($-S0));if(q>0)await new Promise((Q)=>setTimeout(Q,q));S0=Date.now()}function u1($,q,Q={}){let z=new URL(q,$);for(let[J,M]of Object.entries(Q)){if(M===void 0||M==="")continue;if(Array.isArray(M))for(let X of M)z.searchParams.append(J,X);else z.searchParams.set(J,String(M))}return z}class O{baseUrl;apiKey;constructor($={}){this.baseUrl=$.baseUrl??C,this.apiKey=$.apiKey}static async fromConfig($){let q=await a();return new O({baseUrl:q.baseUrl??C,apiKey:await V0($)})}async request($,q={}){if(q.auth!==!1&&!this.apiKey)throw Error(D0());await v1();let Q=await fetch(u1(this.baseUrl,$,q.query),{method:q.method??"GET",headers:{"content-type":"application/json",...this.apiKey?{"X-API-Key":this.apiKey,authorization:`Bearer ${this.apiKey}`}:{}},body:q.body?JSON.stringify(q.body):void 0}),z=await Q.text(),J=z?JSON.parse(z):null;if(!Q.ok)throw Error(J?.message??J?.detail??`HTTP ${Q.status}`);return J}entities($){return this.request("/api/v1/market/exchange/entity",{query:$,auth:!1})}entity($){return this.request(`/api/v1/market/exchange/entity/${$}`,{auth:!1})}news($){return this.request("/api/v1/news",{query:$,auth:!1})}ohlcv($,q){return this.request(`/api/v1/market/exchange/entity/${$}/ohlcv`,{query:q,auth:!1})}historicalQuote($,q){return this.request(`/api/v1/market/exchange/entity/${$}/historical-quote`,{query:q,auth:!1})}offices($){return this.request(`/api/v1/market/exchange/entity/${$}/office`,{auth:!1})}subsidiaries($){return this.request(`/api/v1/market/exchange/entity/${$}/subsidiary`,{auth:!1})}holders($,q){return this.request(`/api/v1/market/exchange/entity/${$}/holder`,{query:q,auth:!1})}holderTransactions($,q){return this.request(`/api/v1/market/exchange/entity/${$}/holder-transaction`,{query:q,auth:!1})}financialStatements($,q){return this.request(`/api/v1/market/exchange/entity/${$}/financial-statement`,{query:q,auth:!1})}financialStatistics($,q){return this.request(`/api/v1/market/exchange/entity/${$}/financial-statistic`,{query:q,auth:!1})}usage(){return this.request("/api/v1/subscription/usage")}createChat(){return this.request("/api/v1/chat",{method:"POST",body:{title:"mozyfin-cli",mode:"auto"}})}sendMessage($,q){return this.request(`/api/v1/chat/${$}/message`,{method:"POST",body:{content:q}})}getMessage($){return this.request(`/api/v1/chat/messages/${$}`)}queryReport($){return this.request("/api/v1/document/query-report",{method:"POST",body:{query:$}})}}import{writeFile as g1}from"fs/promises";function e($){return $?.data??$?.result??$}function P($){let q=e($);if(Array.isArray(q))return q;if(Array.isArray(q?.items))return q.items;if(Array.isArray(q?.results))return q.results;if(Array.isArray(q?.data))return q.data;return q?[q]:[]}function S($){let q=P($);if(q.length===0)return"_No data_";return o(q,Object.keys(q[0]).slice(0,8))}function o($,q){let Q=P($);if(Q.length===0)return"_No data_";let z=q.filter((Y)=>Q.some((Z)=>Z?.[Y]!==void 0));if(z.length===0)return S($);let J=`| ${z.join(" | ")} |`,M=`| ${z.map(()=>"---").join(" | ")} |`,X=Q.map((Y)=>`| ${z.map((Z)=>A0(Y?.[Z])).join(" | ")} |`).join(`
26
+ `);return`${J}
27
+ ${M}
28
+ ${X}`}function w0($,q){let[Q]=P($);if(!Q)return"_No data_";return(q?.filter((J)=>Q[J]!==void 0)??Object.keys(Q)).map((J)=>`- ${J}: ${A0(Q[J])}`).join(`
29
+ `)}function f0($,q="content"){let Q=P($)[0]??e($);return Q?.[q]??Q?.message?.[q]??Q?.data?.[q]??"_No content_"}function A0($){if($===null||$===void 0)return"";if(typeof $==="object"){let q=$,Q=q.symbol??q.id??q.name??q.title;if(Q!==void 0)return String(Q).replaceAll("|","\\|");return JSON.stringify($).replaceAll("|","\\|").slice(0,120)}return String($).replaceAll("|","\\|")}function c1($){let q=P($);if(q.length===0)return"";let Q=Array.from(new Set(q.flatMap((z)=>Object.keys(z))));return[Q.join(","),...q.map((z)=>Q.map((J)=>l1(z[J])).join(","))].join(`
30
+ `)}function l1($){let q=$===null||$===void 0?"":typeof $==="object"?JSON.stringify($):String($);return/[",\n]/.test(q)?`"${q.replaceAll('"','""')}"`:q}function b0($){let q=e($),Q=[],z=q?.entities??[];if(z.length>0)Q.push(`### Entities (${z.length})
31
+
32
+ ${S(z)}`);let J=q?.relationships??[];if(J.length>0)Q.push(`
33
+ ### Relationships (${J.length})
34
+
35
+ ${S(J)}`);let M=q?.chunks??[];if(M.length>0)Q.push(`
36
+ ### Document Chunks (${M.length})
37
+
38
+ ${S(M)}`);let X=q?.references??[];if(X.length>0)Q.push(`
39
+ ### References (${X.length})
40
+
41
+ ${S(X)}`);if(q?.instructions)Q.push(`
42
+ ### Context
43
+
44
+ ${q.instructions}`);return Q.length>0?Q.join(`
45
+ `):"_No data_"}async function f($,q){if(q.csv){await g1(q.csv,`${c1($)}
46
+ `),console.log(S([{ok:!0,file:q.csv,rows:P($).length}]));return}console.log(S($))}var q0=$0(m1(import.meta.url)),d1=JSON.parse(h(K(q0,"..","package.json"),"utf8")),B=new E0;B.name("mozyfin").description("Vietnam stock market CLI for humans and AI agents").version(d1.version).showHelpAfterError().addHelpText("after",`
47
+
48
+ Examples:
49
+ $ mozyfin login --api-key <key>
50
+ $ mozyfin search --query VNM --md
51
+ $ mozyfin quote VNM.VN --md
52
+ $ mozyfin ohlcv VNM.VN --timeframe 1d --limit 200 --csv vnm.csv
53
+ $ mozyfin ta VNM.VN --sma 20,50 --rsi 14 --macd --csv vnm-ta.csv
54
+ $ mozyfin doc "VNM Q4 2024 earnings analysis"
55
+ $ mozyfin ask "compare VNM and MSN margin trend"
56
+ `).option("--api-key <key>","API key, or set MOZYFIN_API_KEY").option("--base-url <url>","API base URL",C).option("--no-color","reserved for scripts/agents; output stays plain text");function y($){return $.option("-m, --md","print Markdown table (default)").option("--csv <file>","write rows to CSV file")}async function R(){let $=B.opts(),q=await O.fromConfig($.apiKey);return q.baseUrl=$.baseUrl,q}function k0($){if(!$)return;let q=$.split(",").map((Q)=>Q.trim()).filter(Boolean);return q.length?q:void 0}function x0($,q,Q){if(!q.includes($))throw Error(`${Q} must be one of: ${q.join(", ")}`);return $}async function I($,q,Q){if(q.csv)return f($,q);console.log(o($,Q))}async function Q0($,q,Q){if(q.csv)return f($,q);console.log(w0($,Q))}function r1($){return P($).map((q)=>{let Q=q.values??{};return{year:q.year,quarter:q.quarter,type:q.type,net_sales:Q["Net sales"]??Q.Sales,gross_profit:Q["Gross Profit"],profit_after_tax:Q["Net profit/(loss) after tax"],total_assets:Q["Total Assets"],owner_equity:Q["Owner's Equity"],net_operating_cash_flow:Q["Net cash inflows/(outflows) from operating activities"],public_at:q.public_at}})}B.command("login").description("Save API key locally").option("--api-key <key>").action(async($)=>{let q=$.apiKey??B.opts().apiKey;if(!q)throw Error("Missing --api-key <key>");await F0({apiKey:q,baseUrl:B.opts().baseUrl}),await f([{ok:!0,configPath:D}],{})});B.command("logout").description("Remove saved API key").action(async()=>{await N0(),await f([{ok:!0}],{})});y(B.command("search").description("Search companies/entities by ticker, name or text")).option("-q, --query [text]","search query; empty means all","").action(async($)=>I(await(await R()).entities({search:$.query}),$,["symbol","ticker","name","exchange","market","price","market_cap","id"]));y(B.command("profile").argument("<tickerOrEntityId>").description("Company profile/entity details")).action(async($,q)=>Q0(await(await R()).entity($),q,["symbol","ticker","name","exchange","market","sector","industry","website","description","entity_id","id"]));y(B.command("news").description("Market headlines and article search")).option("--query <text>","search query; empty means all","").option("--entities <ids>","comma-separated entity ids; OR semantics").option("--topics <topics>","comma-separated topics: stock,crypto,forex,tariff,economic,earning,tech,housing,mergers_and_ipo; OR semantics").option("--limit <n>","max rows","20").option("--page <n>","page hint for APIs that support it","1").action(async($)=>I(await(await R()).news(s1($)),$,["published_at","created_at","title","source","topics","entities","url","id"]));function s1($){let q=["stock","crypto","forex","tariff","economic","earning","tech","housing","mergers_and_ipo"],Q=k0($.topics);for(let z of Q??[])x0(z,q,"topic");return{search:$.query,entities:k0($.entities),topics:Q,limit:$.limit,page:$.page}}y(B.command("ohlcv").argument("<entity>").description("Historical OHLCV candles")).option("--timeframe <value>","1h, 1d, 1w, 1mo, 1y","1d").option("--to <timestamp>","end timestamp").option("--limit <n>","max rows").action(async($,q)=>{return x0(q.timeframe,["1h","1d","1w","1mo","1y"],"timeframe"),I(await(await R()).ohlcv($,q),q,["timestamp","time","date","open","high","low","close","volume"])});y(B.command("quote").argument("<entity>").description("Latest daily quote snapshot")).option("--to <timestamp>","end timestamp").option("--limit <n>","max rows","1").action(async($,q)=>I(await(await R()).historicalQuote($,{to:q.to,limit:q.limit}),q,["timestamp","total_volume","deal_volume","total_value","buy_foreign_quantity","sell_foreign_quantity","current_foreign_room"]));y(B.command("officers").argument("<entity>").description("Company officers/directors")).action(async($,q)=>I(await(await R()).offices($),q,["name","position","is_foreigner","sort_order"]));y(B.command("subsidiary").argument("<entity>").description("Company subsidiaries")).action(async($,q)=>I(await(await R()).subsidiaries($),q,["name","symbol","ownership_rate","charter_capital","business_area","id"]));y(B.command("holder").argument("<entity>").description("Major shareholders")).option("--is-organization <true|false>","filter organization holders").option("--is-foreigner <true|false>","filter foreign holders").action(async($,q)=>I(await(await R()).holders($,{is_organization:q.isOrganization,is_foreigner:q.isForeigner}),q,["name","holder_name","ownership_rate","shares","is_organization","is_foreigner"]));y(B.command("holder-tx").argument("<entity>").description("Shareholder transactions")).option("--cursor <cursor>","pagination cursor").option("--limit <n>","max rows","100").option("--transaction-type <type>","transaction type filter").action(async($,q)=>I(await(await R()).holderTransactions($,{cursor:q.cursor,limit:q.limit,transaction_type:q.transactionType}),q,["name","type","registered_volume","execution_volume","start_at","end_at","position"]));y(B.command("financials").argument("<entity>").description("Financial statements")).option("--year <year>","report year").option("--quarter <quarter>","report quarter").option("--statement-type <type>","statement type filter").action(async($,q)=>I(r1(await(await R()).financialStatements($,{year:q.year,quarter:q.quarter,statement_type:q.statementType})),q,["year","quarter","type","net_sales","gross_profit","profit_after_tax","total_assets","owner_equity","net_operating_cash_flow"]));y(B.command("stats").argument("<entity>").description("Financial statistics/ratios")).option("--year <year>","report year").option("--quarter <quarter>","report quarter").action(async($,q)=>I(await(await R()).financialStatistics($,{year:q.year,quarter:q.quarter}),q,["year","quarter","pe","pb","roe","roa","gross_margin","market_cap"]));y(B.command("ta").argument("<tickerOrEntityId>").description("Technical indicators over OHLCV close prices")).option("--sma <list>","comma-separated SMA periods","20").option("--rsi <n>","RSI period").option("--macd","include MACD").option("--limit <n>","max candles","300").action(async($,q)=>{let Q=await(await R()).ohlcv($,{timeframe:"1d",limit:q.limit}),J=[...P(Q)].reverse(),M=n(J),X=String(q.sma).split(",").map(Number).filter(Number.isFinite),Y=Object.fromEntries(X.map((G)=>[G,y0(M,G)])),Z=q.rsi?I0(M,Number(q.rsi)):[],_=q.macd?P0(M):[],U=J.map((G,L)=>({...G,...Object.fromEntries(X.map((W)=>[`sma_${W}`,Y[W][L]])),...q.rsi?{[`rsi_${q.rsi}`]:Z[L]}:{},...q.macd?_[L]:{}})).reverse();await I(U,q,["timestamp","time","date","close",...X.map((G)=>`sma_${G}`),...q.rsi?[`rsi_${q.rsi}`]:[],...q.macd?["macd","signal","histogram"]:[]])});B.command("risk").argument("<tickerOrEntityId>").description("Risk/performance metrics: return, volatility, Sharpe, max drawdown").option("--limit <n>","max candles","252").option("--risk-free <n>","annual risk-free rate","0").action(async($,q)=>{let Q=await(await R()).ohlcv($,{timeframe:"1d",limit:q.limit});await Q0([j0(n([...P(Q)].reverse()),Number(q.riskFree))],{},["count","annualReturn","volatility","sharpe","maxDrawdown"])});B.command("doc").argument("<query...>").description("Query analysis reports using natural language").action(async($)=>{let q=await(await R()).queryReport($.join(" "));console.log(b0(q))});B.command("ask").argument("<prompt...>").description("Ask Mozyfin agent in auto mode, no workspace needed").option("--timeout <seconds>","max wait time","300").action(async($,q)=>{let Q=await R(),z=await Q.createChat(),J=z?.data?.id??z?.id;if(!J)throw Error("Could not create chat");let X=await Q.sendMessage(J,$.join(" ")),Y=X?.data?.id??X?.id,Z=Date.now()+Number(q.timeout)*1000;while(Y&&Date.now()<Z){let _=X?.data?.status??X?.status;if(_&&_!=="thinking"&&_!=="streaming")break;await new Promise((U)=>setTimeout(U,2000)),X=await Q.getMessage(Y)}console.log(f0(X))});B.command("credits").description("Check subscription usage/credits").action(async()=>Q0(await(await R()).usage(),{},["credits_used","credits_cap","remaining","plan"]));B.command("doctor").description("Check runtime, config and API health").action(async()=>{let $=C0("bun",["--version"],{encoding:"utf8"}).stdout.trim(),q=await R(),Q=await q.request("/health",{auth:!1});await f([{bun:$,configPath:D,baseUrl:q.baseUrl,health:Q}],{})});B.command("update").description("Upgrade CLI to latest version; auto-updates skills for any agents that already have it installed").option("--skill [agent]","Force update skill for specific agent (claude, cursor, copilot, windsurf, codex, gemini, hermes, openclaw, or 'all')").action(async($)=>{let q=B.version(),Q=await fetch("https://registry.npmjs.org/mozyfin-cli/latest").then((X)=>X.json()).then((X)=>X.version).catch(()=>null);if(console.log(`Current version: ${q}`),Q)if(console.log(`Latest version: ${Q}`),q===Q)console.log(`
57
+ You're already on the latest version!`);else if(console.log(`
58
+ Updating CLI...`),C0("npm",["install","-g","mozyfin-cli@latest"],{encoding:"utf8",stdio:"inherit"}).status===0)console.log(`
59
+ \u2713 CLI updated successfully!`);else console.log(`
60
+ \u2717 CLI update failed. Try running manually:`),console.log(" npm install -g mozyfin-cli@latest");let z=K(q0,"..","agent-skills","mozyfin-cli"),J="mozyfin-cli",M=[];if($.skill){let X=$.skill===!0?"all":$.skill;M=X==="all"?Object.keys(b):[X]}else for(let[X,Y]of Object.entries(b)){let Z=!1;if(Y.format==="directory")Z=T(K(Y.path,J,"SKILL.md"));else if(Y.format==="file")Z=T(K(Y.path,`${J}.md`));else if(Y.format==="append"){if(T(Y.path))Z=h(Y.path,"utf8").includes(`<!-- ${J} -->`)}if(Z)M.push(X)}if(M.length===0)return;if(!T(z)){console.log(`
61
+ \u2717 Skill source not found in package`);return}console.log(`
62
+ Updating skills for: ${M.join(", ")}`);for(let X of M){let Y=b[X];if(!Y){console.log(`\u2717 Unknown agent: ${X}`);continue}let{path:Z,format:_}=Y;try{if(_==="append"){A($0(Z),{recursive:!0});let U=h(K(z,"SKILL.md"),"utf8"),W=`${(T(Z)?h(Z,"utf8"):"").replace(new RegExp(`<!-- ${J} -->[\\s\\S]*<!-- /${J} -->`,"g"),"").trim()}
63
+
64
+ <!-- ${J} -->
65
+ ${U}
66
+ <!-- /${J} -->
67
+ `;E("fs").writeFileSync(Z,W),console.log(`\u2713 Updated skill for ${X}`)}else if(_==="file"){A(Z,{recursive:!0});let U=K(Z,`${J}.md`);u(K(z,"SKILL.md"),U),console.log(`\u2713 Updated skill for ${X}`)}else if(_==="directory"){let U=K(Z,J);v(U,{recursive:!0,force:!0}),A(Z,{recursive:!0}),u(z,U,{recursive:!0}),console.log(`\u2713 Updated skill for ${X}`)}}catch(U){console.log(`\u2717 Failed to update skill for ${X}: ${U}`)}}});var b={claude:{path:K(F(),".claude","skills"),format:"directory"},cursor:{path:K(F(),".cursor","commands"),format:"file"},copilot:{path:K(F(),".github","copilot-instructions.md"),format:"append"},windsurf:{path:K(F(),".windsurf","workflows"),format:"file"},codex:{path:K(F(),".agents","skills"),format:"directory"},gemini:{path:K(F(),".gemini","instructions"),format:"file"},hermes:{path:K(F(),".hermes","skills"),format:"directory"},openclaw:{path:K(F(),".openclaw","skills"),format:"directory"},antigravity:{path:K(F(),".gemini","antigravity","skills"),format:"directory"}};B.command("skill").description("Install mozyfin-cli skill into AI agents (claude, cursor, copilot, windsurf, codex, gemini, hermes, openclaw, antigravity)").argument("[agent]","Target agent (claude, cursor, copilot, windsurf, codex, gemini, hermes, openclaw, antigravity) or 'all'").option("--list","List available agents").option("--remove","Remove skill from agent").action(($,q)=>{let Q=K(q0,"..","agent-skills","mozyfin-cli"),z="mozyfin-cli";if(q.list){console.log(`Available agents:
68
+ `);for(let[M,X]of Object.entries(b)){let Y=!1;if(X.format==="directory")Y=T(K(X.path,"mozyfin-cli","SKILL.md"));else if(X.format==="file")Y=T(K(X.path,"mozyfin-cli.md"));else if(X.format==="append"){if(T(X.path))Y=E("fs").readFileSync(X.path,"utf8").includes("<!-- mozyfin-cli -->")}console.log(` ${M.padEnd(10)} ${Y?"\u2713 installed":"\u25CB not installed"}`),console.log(` ${X.path}`)}return}if(!$){console.log("Usage: mozyfin skill <agent>"),console.log(`
69
+ Available agents: claude, cursor, copilot, windsurf, codex, gemini, hermes, openclaw, all`),console.log(`
70
+ Options:`),console.log(" --list List available agents"),console.log(" --remove Remove skill from agent");return}let J=$==="all"?Object.keys(b):[$];for(let M of J){let X=b[M];if(!X){console.log(`Unknown agent: ${M}`),console.log("Available: claude, cursor, copilot, windsurf, codex, gemini, hermes, openclaw");continue}let{path:Y,format:Z}=X;if(q.remove){if(Z==="append")if(T(Y)){let U=E("fs").readFileSync(Y,"utf8").replace(new RegExp("<!-- mozyfin-cli -->[\\s\\S]*<!-- /mozyfin-cli -->","g"),"").trim();E("fs").writeFileSync(Y,U),console.log(`\u2713 Removed skill from ${M}`)}else console.log(`Skill not installed in ${M}`);else if(Z==="file"){let _=K(Y,"mozyfin-cli.md");if(T(_))v(_),console.log(`\u2713 Removed skill from ${M}`);else console.log(`Skill not installed in ${M}`)}else if(Z==="directory"){let _=K(Y,"mozyfin-cli");if(T(_))v(_,{recursive:!0,force:!0}),console.log(`\u2713 Removed skill from ${M}`);else console.log(`Skill not installed in ${M}`)}continue}if(!T(Q)){console.log(`Skill directory not found: ${Q}`);continue}if(Z==="append"){A($0(Y),{recursive:!0});let _=E("fs").readFileSync(K(Q,"SKILL.md"),"utf8"),L=`${(T(Y)?E("fs").readFileSync(Y,"utf8"):"").replace(new RegExp("<!-- mozyfin-cli -->[\\s\\S]*<!-- /mozyfin-cli -->","g"),"").trim()}
71
+
72
+ <!-- mozyfin-cli -->
73
+ ${_}
74
+ <!-- /mozyfin-cli -->
75
+ `;E("fs").writeFileSync(Y,L),console.log(`\u2713 Installed skill to ${M}`)}else if(Z==="file"){A(Y,{recursive:!0});let _=K(Y,"mozyfin-cli.md");u(K(Q,"SKILL.md"),_),console.log(`\u2713 Installed skill to ${M}`)}else if(Z==="directory"){let _=K(Y,"mozyfin-cli");v(_,{recursive:!0,force:!0}),A(Y,{recursive:!0}),u(Q,_,{recursive:!0}),console.log(`\u2713 Installed skill to ${M}`)}}});B.parseAsync().catch(($)=>{console.error(`Error: ${$.message}`),process.exit(1)});
package/package.json ADDED
@@ -0,0 +1,42 @@
1
+ {
2
+ "name": "mozyfin-cli",
3
+ "version": "0.2.6",
4
+ "description": "Human- and agent-friendly CLI for Vietnamese market data via Mozyfin/Antofin APIs.",
5
+ "type": "module",
6
+ "bin": {
7
+ "mozyfin": "./dist/index.js",
8
+ "mozyfin-cli": "./dist/index.js"
9
+ },
10
+ "files": ["dist", "agent-skills", "package.json", "README.md"],
11
+ "keywords": ["mozyfin", "antofin", "vietnam", "stocks", "market-data", "cli"],
12
+ "scripts": {
13
+ "dev": "bun run src/index.ts",
14
+ "build": "bun build ./src/index.ts --target bun --minify --outfile dist/index.js && chmod +x dist/index.js",
15
+ "test": "bun test",
16
+ "lint": "biome check .",
17
+ "format": "biome format --write .",
18
+ "check": "biome check --write .",
19
+ "prepublishOnly": "bun run build && bun test"
20
+ },
21
+ "dependencies": {
22
+ "commander": "^12.1.0"
23
+ },
24
+ "devDependencies": {
25
+ "@biomejs/biome": "^1.9.4",
26
+ "@types/bun": "latest",
27
+ "typescript": "^5.7.2"
28
+ },
29
+ "engines": {
30
+ "bun": ">=1.1.0"
31
+ },
32
+ "repository": {
33
+ "type": "git",
34
+ "url": "git+https://github.com/onlyai-team/mozyfin-cli.git"
35
+ },
36
+ "author": "Mozyfin",
37
+ "license": "UNLICENSED",
38
+ "bugs": {
39
+ "url": "https://github.com/onlyai-team/mozyfin-cli/issues"
40
+ },
41
+ "homepage": "https://github.com/onlyai-team/mozyfin-cli#readme"
42
+ }