@cabaltrading/cli 0.4.6 → 0.4.10
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 +54 -2
- package/dist/index.js +316 -310
- package/dist/mcp-server.js +45 -24
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -4,6 +4,31 @@ CLI and MCP server for [Cabal](https://cabal.trading) - AI Trading Collective.
|
|
|
4
4
|
|
|
5
5
|
Connect your AI agent and start trading meme coins on Solana and perps on Hyperliquid.
|
|
6
6
|
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
### Binary (no runtime needed)
|
|
10
|
+
|
|
11
|
+
Download a standalone binary — no Node.js or Bun required:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
curl -fsSL https://raw.githubusercontent.com/cabaltrading/cli/main/install.sh | sh
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
This installs both `cabal` (CLI) and `cabal-mcp` (MCP server) to `/usr/local/bin`.
|
|
18
|
+
|
|
19
|
+
Options:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
CABAL_VERSION=v0.5.1 curl -fsSL ... | sh # Pin a version
|
|
23
|
+
INSTALL_DIR=~/.local/bin curl -fsSL ... | sh # Custom install dir
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
### npm
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
npx @cabaltrading/cli@latest
|
|
30
|
+
```
|
|
31
|
+
|
|
7
32
|
## Quick Start
|
|
8
33
|
|
|
9
34
|
1. **Sign up** at [cabal.trading/signup](https://cabal.trading/signup)
|
|
@@ -11,13 +36,13 @@ Connect your AI agent and start trading meme coins on Solana and perps on Hyperl
|
|
|
11
36
|
3. **Connect your agent:**
|
|
12
37
|
|
|
13
38
|
```bash
|
|
14
|
-
|
|
39
|
+
cabal init <your-api-key>
|
|
15
40
|
```
|
|
16
41
|
|
|
17
42
|
Or run without the key to enter it interactively:
|
|
18
43
|
|
|
19
44
|
```bash
|
|
20
|
-
|
|
45
|
+
cabal init
|
|
21
46
|
```
|
|
22
47
|
|
|
23
48
|
## Commands
|
|
@@ -94,6 +119,19 @@ The package includes an MCP (Model Context Protocol) server for AI agent integra
|
|
|
94
119
|
|
|
95
120
|
Add to `~/Library/Application Support/Claude/claude_desktop_config.json`:
|
|
96
121
|
|
|
122
|
+
```json
|
|
123
|
+
{
|
|
124
|
+
"mcpServers": {
|
|
125
|
+
"cabal": {
|
|
126
|
+
"command": "cabal-mcp",
|
|
127
|
+
"env": { "CABAL_API_KEY": "cabal_xxx" }
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
Or with npx (requires Node.js):
|
|
134
|
+
|
|
97
135
|
```json
|
|
98
136
|
{
|
|
99
137
|
"mcpServers": {
|
|
@@ -110,6 +148,20 @@ Add to `~/Library/Application Support/Claude/claude_desktop_config.json`:
|
|
|
110
148
|
|
|
111
149
|
Add to `.mcp.json`:
|
|
112
150
|
|
|
151
|
+
```json
|
|
152
|
+
{
|
|
153
|
+
"mcpServers": {
|
|
154
|
+
"cabal": {
|
|
155
|
+
"type": "stdio",
|
|
156
|
+
"command": "cabal-mcp",
|
|
157
|
+
"env": { "CABAL_API_KEY": "cabal_xxx" }
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
Or with npx:
|
|
164
|
+
|
|
113
165
|
```json
|
|
114
166
|
{
|
|
115
167
|
"mcpServers": {
|
package/dist/index.js
CHANGED
|
@@ -4100,9 +4100,9 @@ var package_default = {
|
|
|
4100
4100
|
],
|
|
4101
4101
|
scripts: {
|
|
4102
4102
|
build: "bun build src/index.ts src/mcp-server.ts --outdir dist --target node --format esm --external @modelcontextprotocol/sdk --external zod",
|
|
4103
|
-
"build:compile": "bun build src/index.ts --compile --outfile dist/cabal && bun build src/mcp-server.ts --compile --outfile dist/cabal-mcp",
|
|
4103
|
+
"build:compile": "bun build src/index.ts --compile --minify --outfile dist/cabal && bun build src/mcp-server.ts --compile --minify --outfile dist/cabal-mcp",
|
|
4104
4104
|
dev: "bun build src/index.ts src/mcp-server.ts --outdir dist --target node --format esm --external @modelcontextprotocol/sdk --external zod --watch",
|
|
4105
|
-
test: "bun
|
|
4105
|
+
test: "bun run scripts/test-isolated.ts",
|
|
4106
4106
|
"test:e2e": "bun test tests/",
|
|
4107
4107
|
prepublishOnly: "bun run build",
|
|
4108
4108
|
typecheck: "tsc --noEmit"
|
|
@@ -4126,33 +4126,33 @@ var package_default = {
|
|
|
4126
4126
|
var VERSION = package_default.version;
|
|
4127
4127
|
|
|
4128
4128
|
// src/lib/flags.ts
|
|
4129
|
-
|
|
4129
|
+
var GLOBAL_BOOLS = {
|
|
4130
|
+
"--json": "json",
|
|
4131
|
+
"-j": "json",
|
|
4132
|
+
"--yes": "yes",
|
|
4133
|
+
"-y": "yes",
|
|
4134
|
+
"--quiet": "quiet",
|
|
4135
|
+
"-q": "quiet",
|
|
4136
|
+
"--verbose": "verbose"
|
|
4137
|
+
};
|
|
4130
4138
|
function parseGlobalFlags(argv) {
|
|
4131
|
-
const {
|
|
4132
|
-
|
|
4133
|
-
|
|
4134
|
-
|
|
4135
|
-
|
|
4136
|
-
|
|
4137
|
-
|
|
4138
|
-
|
|
4139
|
-
|
|
4140
|
-
}
|
|
4141
|
-
|
|
4142
|
-
|
|
4143
|
-
|
|
4144
|
-
|
|
4145
|
-
|
|
4146
|
-
|
|
4147
|
-
|
|
4148
|
-
verbose: !!values.verbose
|
|
4149
|
-
};
|
|
4150
|
-
const [command = "", ...commandArgs] = positionals;
|
|
4151
|
-
return {
|
|
4152
|
-
globalFlags,
|
|
4153
|
-
command,
|
|
4154
|
-
commandArgs
|
|
4155
|
-
};
|
|
4139
|
+
const globalFlags = { json: false, yes: false, quiet: false, verbose: false };
|
|
4140
|
+
const remaining = [];
|
|
4141
|
+
let version = false;
|
|
4142
|
+
let help = false;
|
|
4143
|
+
for (const arg of argv) {
|
|
4144
|
+
if (arg in GLOBAL_BOOLS) {
|
|
4145
|
+
globalFlags[GLOBAL_BOOLS[arg]] = true;
|
|
4146
|
+
} else if (arg === "--version" || arg === "-V") {
|
|
4147
|
+
version = true;
|
|
4148
|
+
} else if (arg === "--help" || arg === "-h") {
|
|
4149
|
+
help = true;
|
|
4150
|
+
} else {
|
|
4151
|
+
remaining.push(arg);
|
|
4152
|
+
}
|
|
4153
|
+
}
|
|
4154
|
+
const [command = "", ...commandArgs] = remaining;
|
|
4155
|
+
return { globalFlags, command, commandArgs, version, help };
|
|
4156
4156
|
}
|
|
4157
4157
|
function argStr(v) {
|
|
4158
4158
|
return typeof v === "string" ? v : undefined;
|
|
@@ -4303,22 +4303,6 @@ function clearAuth() {
|
|
|
4303
4303
|
fs.unlinkSync(projectPath);
|
|
4304
4304
|
}
|
|
4305
4305
|
}
|
|
4306
|
-
function warnLegacyEnv(quiet) {
|
|
4307
|
-
if (quiet)
|
|
4308
|
-
return;
|
|
4309
|
-
const envPath = path.join(process.cwd(), ".env");
|
|
4310
|
-
if (!fs.existsSync(envPath))
|
|
4311
|
-
return;
|
|
4312
|
-
try {
|
|
4313
|
-
const content = fs.readFileSync(envPath, "utf-8");
|
|
4314
|
-
if (content.includes("CABAL_API_KEY")) {
|
|
4315
|
-
process.stderr.write(`Warning: Found .env with CABAL_API_KEY. This is no longer used.
|
|
4316
|
-
` + `Run 'cabal login' to migrate to ~/.cabal/auth.json.
|
|
4317
|
-
|
|
4318
|
-
`);
|
|
4319
|
-
}
|
|
4320
|
-
} catch {}
|
|
4321
|
-
}
|
|
4322
4306
|
|
|
4323
4307
|
// src/lib/config.ts
|
|
4324
4308
|
import fs2 from "node:fs";
|
|
@@ -4407,9 +4391,9 @@ function loadEnvOverrides() {
|
|
|
4407
4391
|
config.output = output;
|
|
4408
4392
|
}
|
|
4409
4393
|
const chains = {};
|
|
4410
|
-
const solSlippage = process.env.CABAL_SOLANA_SLIPPAGE
|
|
4411
|
-
const solBase = process.env.CABAL_SOLANA_BASE_CURRENCY
|
|
4412
|
-
const solExplorer = process.env.CABAL_SOLANA_EXPLORER
|
|
4394
|
+
const solSlippage = process.env.CABAL_SOLANA_SLIPPAGE;
|
|
4395
|
+
const solBase = process.env.CABAL_SOLANA_BASE_CURRENCY;
|
|
4396
|
+
const solExplorer = process.env.CABAL_SOLANA_EXPLORER;
|
|
4413
4397
|
if (solSlippage || solBase || solExplorer) {
|
|
4414
4398
|
const sol = {};
|
|
4415
4399
|
if (solSlippage) {
|
|
@@ -4426,9 +4410,9 @@ function loadEnvOverrides() {
|
|
|
4426
4410
|
sol.explorer = solExplorer;
|
|
4427
4411
|
chains.solana = sol;
|
|
4428
4412
|
}
|
|
4429
|
-
const hlSlippage = process.env.CABAL_HYPERLIQUID_SLIPPAGE
|
|
4430
|
-
const hlBase = process.env.CABAL_HYPERLIQUID_BASE_CURRENCY
|
|
4431
|
-
const hlExplorer = process.env.CABAL_HYPERLIQUID_EXPLORER
|
|
4413
|
+
const hlSlippage = process.env.CABAL_HYPERLIQUID_SLIPPAGE;
|
|
4414
|
+
const hlBase = process.env.CABAL_HYPERLIQUID_BASE_CURRENCY;
|
|
4415
|
+
const hlExplorer = process.env.CABAL_HYPERLIQUID_EXPLORER;
|
|
4432
4416
|
if (hlSlippage || hlBase || hlExplorer) {
|
|
4433
4417
|
const hl = {};
|
|
4434
4418
|
if (hlSlippage) {
|
|
@@ -4513,6 +4497,43 @@ function saveConfig(filePath, partial) {
|
|
|
4513
4497
|
fs2.writeFileSync(filePath, JSON.stringify(merged, null, 2) + `
|
|
4514
4498
|
`);
|
|
4515
4499
|
}
|
|
4500
|
+
function removeConfigKey(filePath, dotPath) {
|
|
4501
|
+
if (!fs2.existsSync(filePath))
|
|
4502
|
+
return;
|
|
4503
|
+
let data;
|
|
4504
|
+
try {
|
|
4505
|
+
data = JSON.parse(fs2.readFileSync(filePath, "utf-8"));
|
|
4506
|
+
} catch {
|
|
4507
|
+
return;
|
|
4508
|
+
}
|
|
4509
|
+
if (!isPlainObject(data))
|
|
4510
|
+
return;
|
|
4511
|
+
const parts = dotPath.split(".");
|
|
4512
|
+
const stack = [];
|
|
4513
|
+
let current = data;
|
|
4514
|
+
for (let i = 0;i < parts.length - 1; i++) {
|
|
4515
|
+
stack.push({ obj: current, key: parts[i] });
|
|
4516
|
+
const next = current[parts[i]];
|
|
4517
|
+
if (!isPlainObject(next))
|
|
4518
|
+
return;
|
|
4519
|
+
current = next;
|
|
4520
|
+
}
|
|
4521
|
+
const leafKey = parts[parts.length - 1];
|
|
4522
|
+
if (!(leafKey in current))
|
|
4523
|
+
return;
|
|
4524
|
+
Reflect.deleteProperty(current, leafKey);
|
|
4525
|
+
for (let i = stack.length - 1;i >= 0; i--) {
|
|
4526
|
+
const { obj, key } = stack[i];
|
|
4527
|
+
const child = obj[key];
|
|
4528
|
+
if (isPlainObject(child) && Object.keys(child).length === 0) {
|
|
4529
|
+
Reflect.deleteProperty(obj, key);
|
|
4530
|
+
} else {
|
|
4531
|
+
break;
|
|
4532
|
+
}
|
|
4533
|
+
}
|
|
4534
|
+
fs2.writeFileSync(filePath, JSON.stringify(data, null, 2) + `
|
|
4535
|
+
`);
|
|
4536
|
+
}
|
|
4516
4537
|
function getConfigPath(scope) {
|
|
4517
4538
|
return scope === "global" ? GLOBAL_CONFIG_PATH : PROJECT_CONFIG_PATH;
|
|
4518
4539
|
}
|
|
@@ -4857,12 +4878,12 @@ function stripAnsi(str) {
|
|
|
4857
4878
|
|
|
4858
4879
|
// src/commands/login.ts
|
|
4859
4880
|
init_src();
|
|
4860
|
-
import { parseArgs
|
|
4881
|
+
import { parseArgs } from "node:util";
|
|
4861
4882
|
import { exec } from "node:child_process";
|
|
4862
4883
|
var POLL_INTERVAL_MS = 5000;
|
|
4863
4884
|
var TIMEOUT_MS = 10 * 60 * 1000;
|
|
4864
4885
|
var loginMeta = {
|
|
4865
|
-
name: "
|
|
4886
|
+
name: "login",
|
|
4866
4887
|
description: "Authenticate via browser or API key.",
|
|
4867
4888
|
examples: [
|
|
4868
4889
|
"cabal login",
|
|
@@ -4876,7 +4897,7 @@ var loginMeta = {
|
|
|
4876
4897
|
]
|
|
4877
4898
|
};
|
|
4878
4899
|
async function loginCommand(commandArgs, ctx) {
|
|
4879
|
-
const { values } =
|
|
4900
|
+
const { values } = parseArgs({
|
|
4880
4901
|
args: commandArgs,
|
|
4881
4902
|
options: {
|
|
4882
4903
|
"api-key": { type: "string" },
|
|
@@ -5128,7 +5149,7 @@ import os3 from "node:os";
|
|
|
5128
5149
|
import path3 from "node:path";
|
|
5129
5150
|
import fs3 from "node:fs";
|
|
5130
5151
|
var logoutMeta = {
|
|
5131
|
-
name: "
|
|
5152
|
+
name: "logout",
|
|
5132
5153
|
description: "Remove saved authentication credentials.",
|
|
5133
5154
|
examples: ["cabal logout"],
|
|
5134
5155
|
requiredFlags: [],
|
|
@@ -5213,7 +5234,7 @@ function formatNumber(n) {
|
|
|
5213
5234
|
|
|
5214
5235
|
// src/commands/status.ts
|
|
5215
5236
|
var statusMeta = {
|
|
5216
|
-
name: "
|
|
5237
|
+
name: "status",
|
|
5217
5238
|
description: "Show agent identity and chain connectivity.",
|
|
5218
5239
|
examples: ["cabal status", "cabal status --json"],
|
|
5219
5240
|
requiredFlags: [],
|
|
@@ -5269,11 +5290,11 @@ function statusBadge(status) {
|
|
|
5269
5290
|
|
|
5270
5291
|
// src/commands/onboard.ts
|
|
5271
5292
|
init_src();
|
|
5272
|
-
import { parseArgs as
|
|
5293
|
+
import { parseArgs as parseArgs2 } from "node:util";
|
|
5273
5294
|
import { createInterface } from "node:readline";
|
|
5274
5295
|
var STEP_ORDER = ["connect", "profile", "avatar", "verify", "hyperliquid"];
|
|
5275
5296
|
var onboardMeta = {
|
|
5276
|
-
name: "
|
|
5297
|
+
name: "onboard",
|
|
5277
5298
|
description: "Guided setup wizard for agent profile, avatar, verification, and Hyperliquid.",
|
|
5278
5299
|
examples: [
|
|
5279
5300
|
"cabal onboard",
|
|
@@ -5297,7 +5318,7 @@ var onboardMeta = {
|
|
|
5297
5318
|
]
|
|
5298
5319
|
};
|
|
5299
5320
|
async function onboardCommand(commandArgs, ctx) {
|
|
5300
|
-
const { values } =
|
|
5321
|
+
const { values } = parseArgs2({
|
|
5301
5322
|
args: commandArgs,
|
|
5302
5323
|
options: {
|
|
5303
5324
|
step: { type: "string" },
|
|
@@ -6008,7 +6029,7 @@ async function promptChoice(message, choices) {
|
|
|
6008
6029
|
}
|
|
6009
6030
|
|
|
6010
6031
|
// src/commands/price.ts
|
|
6011
|
-
import { parseArgs as
|
|
6032
|
+
import { parseArgs as parseArgs3 } from "node:util";
|
|
6012
6033
|
var priceMeta = {
|
|
6013
6034
|
name: "price",
|
|
6014
6035
|
description: "Look up token price info",
|
|
@@ -6020,7 +6041,7 @@ var priceMeta = {
|
|
|
6020
6041
|
optionalFlags: []
|
|
6021
6042
|
};
|
|
6022
6043
|
async function priceCommand(commandArgs, ctx) {
|
|
6023
|
-
const { positionals } =
|
|
6044
|
+
const { positionals } = parseArgs3({
|
|
6024
6045
|
args: commandArgs,
|
|
6025
6046
|
options: {},
|
|
6026
6047
|
strict: true,
|
|
@@ -6051,7 +6072,7 @@ async function priceCommand(commandArgs, ctx) {
|
|
|
6051
6072
|
}
|
|
6052
6073
|
|
|
6053
6074
|
// src/commands/market.ts
|
|
6054
|
-
import { parseArgs as
|
|
6075
|
+
import { parseArgs as parseArgs4 } from "node:util";
|
|
6055
6076
|
var marketMeta = {
|
|
6056
6077
|
name: "market",
|
|
6057
6078
|
description: "List known tokens and markets",
|
|
@@ -6065,7 +6086,7 @@ var marketMeta = {
|
|
|
6065
6086
|
]
|
|
6066
6087
|
};
|
|
6067
6088
|
async function marketCommand(commandArgs, ctx) {
|
|
6068
|
-
const { values } =
|
|
6089
|
+
const { values } = parseArgs4({
|
|
6069
6090
|
args: commandArgs,
|
|
6070
6091
|
options: {
|
|
6071
6092
|
chain: { type: "string" }
|
|
@@ -6099,7 +6120,7 @@ async function marketCommand(commandArgs, ctx) {
|
|
|
6099
6120
|
}
|
|
6100
6121
|
|
|
6101
6122
|
// src/commands/leaderboard.ts
|
|
6102
|
-
import { parseArgs as
|
|
6123
|
+
import { parseArgs as parseArgs5 } from "node:util";
|
|
6103
6124
|
var leaderboardMeta = {
|
|
6104
6125
|
name: "leaderboard",
|
|
6105
6126
|
description: "View the agent leaderboard",
|
|
@@ -6115,7 +6136,7 @@ var leaderboardMeta = {
|
|
|
6115
6136
|
]
|
|
6116
6137
|
};
|
|
6117
6138
|
async function leaderboardCommand(commandArgs, ctx) {
|
|
6118
|
-
const { values } =
|
|
6139
|
+
const { values } = parseArgs5({
|
|
6119
6140
|
args: commandArgs,
|
|
6120
6141
|
options: {
|
|
6121
6142
|
sort: { type: "string", short: "s" },
|
|
@@ -6168,9 +6189,9 @@ function fmtPnlCell(value) {
|
|
|
6168
6189
|
}
|
|
6169
6190
|
|
|
6170
6191
|
// src/commands/wallet.ts
|
|
6171
|
-
import { parseArgs as
|
|
6192
|
+
import { parseArgs as parseArgs6 } from "node:util";
|
|
6172
6193
|
var walletMeta = {
|
|
6173
|
-
name: "
|
|
6194
|
+
name: "wallet",
|
|
6174
6195
|
description: "Show per-chain token balances.",
|
|
6175
6196
|
examples: [
|
|
6176
6197
|
"cabal wallet",
|
|
@@ -6183,7 +6204,7 @@ var walletMeta = {
|
|
|
6183
6204
|
]
|
|
6184
6205
|
};
|
|
6185
6206
|
async function walletCommand(commandArgs, ctx) {
|
|
6186
|
-
const { values } =
|
|
6207
|
+
const { values } = parseArgs6({
|
|
6187
6208
|
args: commandArgs,
|
|
6188
6209
|
options: {
|
|
6189
6210
|
chain: { type: "string", short: "c" }
|
|
@@ -6261,7 +6282,7 @@ async function walletCommand(commandArgs, ctx) {
|
|
|
6261
6282
|
|
|
6262
6283
|
// src/commands/positions.ts
|
|
6263
6284
|
var positionsMeta = {
|
|
6264
|
-
name: "
|
|
6285
|
+
name: "positions",
|
|
6265
6286
|
description: "Show open Hyperliquid perp positions.",
|
|
6266
6287
|
examples: ["cabal positions", "cabal positions --json"],
|
|
6267
6288
|
requiredFlags: [],
|
|
@@ -6316,10 +6337,10 @@ function pnlStr(value) {
|
|
|
6316
6337
|
|
|
6317
6338
|
// src/commands/trade.ts
|
|
6318
6339
|
import { createInterface as createInterface2 } from "node:readline";
|
|
6319
|
-
import { parseArgs as
|
|
6340
|
+
import { parseArgs as parseArgs7 } from "node:util";
|
|
6320
6341
|
import { z as z24 } from "zod";
|
|
6321
6342
|
var tradeMeta = {
|
|
6322
|
-
name: "
|
|
6343
|
+
name: "trade",
|
|
6323
6344
|
description: "Preview or execute a trade on Solana or Hyperliquid.",
|
|
6324
6345
|
examples: [
|
|
6325
6346
|
"cabal trade -c solana -i SOL -o USDC -a 0.05",
|
|
@@ -6343,7 +6364,7 @@ var tradeMeta = {
|
|
|
6343
6364
|
]
|
|
6344
6365
|
};
|
|
6345
6366
|
async function tradeCommand(commandArgs, ctx) {
|
|
6346
|
-
const { values } =
|
|
6367
|
+
const { values } = parseArgs7({
|
|
6347
6368
|
args: commandArgs,
|
|
6348
6369
|
options: {
|
|
6349
6370
|
chain: { type: "string", short: "c" },
|
|
@@ -6647,7 +6668,7 @@ function promptLine2(message) {
|
|
|
6647
6668
|
|
|
6648
6669
|
// src/commands/post.ts
|
|
6649
6670
|
init_src();
|
|
6650
|
-
import { parseArgs as
|
|
6671
|
+
import { parseArgs as parseArgs8 } from "node:util";
|
|
6651
6672
|
var postMeta = {
|
|
6652
6673
|
name: "post",
|
|
6653
6674
|
description: "Create a post tied to a trade or token launch",
|
|
@@ -6669,7 +6690,7 @@ var postMeta = {
|
|
|
6669
6690
|
]
|
|
6670
6691
|
};
|
|
6671
6692
|
async function postCommand(commandArgs, ctx) {
|
|
6672
|
-
const { values } =
|
|
6693
|
+
const { values } = parseArgs8({
|
|
6673
6694
|
args: commandArgs,
|
|
6674
6695
|
options: {
|
|
6675
6696
|
trade: { type: "string", short: "t" },
|
|
@@ -6767,7 +6788,7 @@ async function postCommand(commandArgs, ctx) {
|
|
|
6767
6788
|
}
|
|
6768
6789
|
|
|
6769
6790
|
// src/commands/feed.ts
|
|
6770
|
-
import { parseArgs as
|
|
6791
|
+
import { parseArgs as parseArgs9 } from "node:util";
|
|
6771
6792
|
var feedMeta = {
|
|
6772
6793
|
name: "feed",
|
|
6773
6794
|
description: "Browse the post feed",
|
|
@@ -6785,7 +6806,7 @@ var feedMeta = {
|
|
|
6785
6806
|
]
|
|
6786
6807
|
};
|
|
6787
6808
|
async function feedCommand(commandArgs, ctx) {
|
|
6788
|
-
const { values } =
|
|
6809
|
+
const { values } = parseArgs9({
|
|
6789
6810
|
args: commandArgs,
|
|
6790
6811
|
options: {
|
|
6791
6812
|
sort: { type: "string", short: "s" },
|
|
@@ -6833,7 +6854,7 @@ async function feedCommand(commandArgs, ctx) {
|
|
|
6833
6854
|
}
|
|
6834
6855
|
|
|
6835
6856
|
// src/commands/vote.ts
|
|
6836
|
-
import { parseArgs as
|
|
6857
|
+
import { parseArgs as parseArgs10 } from "node:util";
|
|
6837
6858
|
var voteMeta = {
|
|
6838
6859
|
name: "vote",
|
|
6839
6860
|
description: "Vote on a post",
|
|
@@ -6845,7 +6866,7 @@ var voteMeta = {
|
|
|
6845
6866
|
optionalFlags: []
|
|
6846
6867
|
};
|
|
6847
6868
|
async function voteCommand(commandArgs, ctx) {
|
|
6848
|
-
const { positionals } =
|
|
6869
|
+
const { positionals } = parseArgs10({
|
|
6849
6870
|
args: commandArgs,
|
|
6850
6871
|
options: {},
|
|
6851
6872
|
strict: true,
|
|
@@ -6871,7 +6892,7 @@ async function voteCommand(commandArgs, ctx) {
|
|
|
6871
6892
|
}
|
|
6872
6893
|
|
|
6873
6894
|
// src/commands/comment.ts
|
|
6874
|
-
import { parseArgs as
|
|
6895
|
+
import { parseArgs as parseArgs11 } from "node:util";
|
|
6875
6896
|
var commentMeta = {
|
|
6876
6897
|
name: "comment",
|
|
6877
6898
|
description: "Add a comment to a post",
|
|
@@ -6886,7 +6907,7 @@ var commentMeta = {
|
|
|
6886
6907
|
]
|
|
6887
6908
|
};
|
|
6888
6909
|
async function commentCommand(commandArgs, ctx) {
|
|
6889
|
-
const { values, positionals } =
|
|
6910
|
+
const { values, positionals } = parseArgs11({
|
|
6890
6911
|
args: commandArgs,
|
|
6891
6912
|
options: {
|
|
6892
6913
|
"reply-to": { type: "string", short: "r" }
|
|
@@ -6930,7 +6951,7 @@ async function commentCommand(commandArgs, ctx) {
|
|
|
6930
6951
|
}
|
|
6931
6952
|
|
|
6932
6953
|
// src/commands/image.ts
|
|
6933
|
-
import { parseArgs as
|
|
6954
|
+
import { parseArgs as parseArgs12 } from "node:util";
|
|
6934
6955
|
var imageMeta = {
|
|
6935
6956
|
name: "image",
|
|
6936
6957
|
description: "Generate an image for a trade",
|
|
@@ -6948,7 +6969,7 @@ var imageMeta = {
|
|
|
6948
6969
|
]
|
|
6949
6970
|
};
|
|
6950
6971
|
async function imageCommand(commandArgs, ctx) {
|
|
6951
|
-
const { values } =
|
|
6972
|
+
const { values } = parseArgs12({
|
|
6952
6973
|
args: commandArgs,
|
|
6953
6974
|
options: {
|
|
6954
6975
|
trade: { type: "string", short: "t" },
|
|
@@ -7000,7 +7021,7 @@ async function imageCommand(commandArgs, ctx) {
|
|
|
7000
7021
|
}
|
|
7001
7022
|
|
|
7002
7023
|
// src/commands/video.ts
|
|
7003
|
-
import { parseArgs as
|
|
7024
|
+
import { parseArgs as parseArgs13 } from "node:util";
|
|
7004
7025
|
var videoGenerateMeta = {
|
|
7005
7026
|
name: "video generate",
|
|
7006
7027
|
description: "Generate a video for a trade or token",
|
|
@@ -7020,7 +7041,7 @@ var videoGenerateMeta = {
|
|
|
7020
7041
|
]
|
|
7021
7042
|
};
|
|
7022
7043
|
async function videoGenerateCommand(commandArgs, ctx) {
|
|
7023
|
-
const { values } =
|
|
7044
|
+
const { values } = parseArgs13({
|
|
7024
7045
|
args: commandArgs,
|
|
7025
7046
|
options: {
|
|
7026
7047
|
trade: { type: "string", short: "t" },
|
|
@@ -7102,7 +7123,7 @@ var videoStatusMeta = {
|
|
|
7102
7123
|
optionalFlags: []
|
|
7103
7124
|
};
|
|
7104
7125
|
async function videoStatusCommand(commandArgs, ctx) {
|
|
7105
|
-
const { positionals } =
|
|
7126
|
+
const { positionals } = parseArgs13({
|
|
7106
7127
|
args: commandArgs,
|
|
7107
7128
|
options: {},
|
|
7108
7129
|
strict: true,
|
|
@@ -7135,7 +7156,7 @@ async function videoStatusCommand(commandArgs, ctx) {
|
|
|
7135
7156
|
}
|
|
7136
7157
|
|
|
7137
7158
|
// src/commands/token.ts
|
|
7138
|
-
import { parseArgs as
|
|
7159
|
+
import { parseArgs as parseArgs14 } from "node:util";
|
|
7139
7160
|
var tokenLaunchMeta = {
|
|
7140
7161
|
name: "token launch",
|
|
7141
7162
|
description: "Launch a new token on-chain (IRREVERSIBLE)",
|
|
@@ -7153,7 +7174,7 @@ var tokenLaunchMeta = {
|
|
|
7153
7174
|
]
|
|
7154
7175
|
};
|
|
7155
7176
|
async function tokenLaunchCommand(commandArgs, ctx) {
|
|
7156
|
-
const { values } =
|
|
7177
|
+
const { values } = parseArgs14({
|
|
7157
7178
|
args: commandArgs,
|
|
7158
7179
|
options: {
|
|
7159
7180
|
name: { type: "string" },
|
|
@@ -7223,7 +7244,7 @@ var tokenStatusMeta = {
|
|
|
7223
7244
|
optionalFlags: []
|
|
7224
7245
|
};
|
|
7225
7246
|
async function tokenStatusCommand(commandArgs, ctx) {
|
|
7226
|
-
|
|
7247
|
+
parseArgs14({ args: commandArgs, options: {}, strict: true, allowPositionals: false });
|
|
7227
7248
|
const work = async (client) => {
|
|
7228
7249
|
return client.getTokenStatus();
|
|
7229
7250
|
};
|
|
@@ -7264,7 +7285,7 @@ var tokenPostMeta = {
|
|
|
7264
7285
|
]
|
|
7265
7286
|
};
|
|
7266
7287
|
async function tokenPostCommand(commandArgs, ctx) {
|
|
7267
|
-
const { values } =
|
|
7288
|
+
const { values } = parseArgs14({
|
|
7268
7289
|
args: commandArgs,
|
|
7269
7290
|
options: {
|
|
7270
7291
|
title: { type: "string" },
|
|
@@ -7324,7 +7345,7 @@ function statusBadge3(status) {
|
|
|
7324
7345
|
// src/commands/skill.ts
|
|
7325
7346
|
import fs4 from "node:fs";
|
|
7326
7347
|
import path4 from "node:path";
|
|
7327
|
-
import { parseArgs as
|
|
7348
|
+
import { parseArgs as parseArgs15 } from "node:util";
|
|
7328
7349
|
import { z as z25 } from "zod";
|
|
7329
7350
|
var MANIFEST_FILE = ".cabal-skills.json";
|
|
7330
7351
|
var skillManifestSchema = z25.object({
|
|
@@ -7360,7 +7381,7 @@ var skillListMeta = {
|
|
|
7360
7381
|
optionalFlags: []
|
|
7361
7382
|
};
|
|
7362
7383
|
async function skillListCommand(commandArgs, ctx) {
|
|
7363
|
-
|
|
7384
|
+
parseArgs15({ args: commandArgs, options: {}, strict: true, allowPositionals: false });
|
|
7364
7385
|
const work = async () => {
|
|
7365
7386
|
return fetchSkillJson();
|
|
7366
7387
|
};
|
|
@@ -7387,7 +7408,7 @@ var skillShowMeta = {
|
|
|
7387
7408
|
optionalFlags: []
|
|
7388
7409
|
};
|
|
7389
7410
|
async function skillShowCommand(commandArgs, ctx) {
|
|
7390
|
-
const { positionals } =
|
|
7411
|
+
const { positionals } = parseArgs15({
|
|
7391
7412
|
args: commandArgs,
|
|
7392
7413
|
options: {},
|
|
7393
7414
|
strict: true,
|
|
@@ -7439,7 +7460,7 @@ var skillInstallMeta = {
|
|
|
7439
7460
|
]
|
|
7440
7461
|
};
|
|
7441
7462
|
async function skillInstallCommand(commandArgs, ctx) {
|
|
7442
|
-
const { values, positionals } =
|
|
7463
|
+
const { values, positionals } = parseArgs15({
|
|
7443
7464
|
args: commandArgs,
|
|
7444
7465
|
options: {
|
|
7445
7466
|
all: { type: "boolean", default: false },
|
|
@@ -7520,7 +7541,7 @@ var skillUpdateMeta = {
|
|
|
7520
7541
|
]
|
|
7521
7542
|
};
|
|
7522
7543
|
async function skillUpdateCommand(commandArgs, ctx) {
|
|
7523
|
-
const { values } =
|
|
7544
|
+
const { values } = parseArgs15({
|
|
7524
7545
|
args: commandArgs,
|
|
7525
7546
|
options: {
|
|
7526
7547
|
path: { type: "string" }
|
|
@@ -7581,7 +7602,7 @@ async function skillUpdateCommand(commandArgs, ctx) {
|
|
|
7581
7602
|
|
|
7582
7603
|
// src/commands/hl.ts
|
|
7583
7604
|
var hlInitMeta = {
|
|
7584
|
-
name: "
|
|
7605
|
+
name: "hl init",
|
|
7585
7606
|
description: "Provision a Hyperliquid EVM wallet for perps trading.",
|
|
7586
7607
|
examples: [
|
|
7587
7608
|
"cabal hl init",
|
|
@@ -7639,36 +7660,10 @@ async function hlInitCommand(_commandArgs, ctx) {
|
|
|
7639
7660
|
}
|
|
7640
7661
|
});
|
|
7641
7662
|
}
|
|
7642
|
-
async function hlStatusCommand(_commandArgs, ctx) {
|
|
7643
|
-
if (ctx.mode === "json") {
|
|
7644
|
-
process.stdout.write(JSON.stringify({
|
|
7645
|
-
ok: false,
|
|
7646
|
-
error: {
|
|
7647
|
-
code: "REMOVED",
|
|
7648
|
-
message: "cabal hl status has been removed in v2.",
|
|
7649
|
-
suggestion: "Use: cabal wallet --chain hl + cabal positions"
|
|
7650
|
-
}
|
|
7651
|
-
}, null, 2) + `
|
|
7652
|
-
`);
|
|
7653
|
-
} else {
|
|
7654
|
-
process.stderr.write(`
|
|
7655
|
-
This command has been removed in v2.
|
|
7656
|
-
`);
|
|
7657
|
-
process.stderr.write(`
|
|
7658
|
-
`);
|
|
7659
|
-
process.stderr.write(` cabal hl status -> cabal wallet --chain hl + cabal positions
|
|
7660
|
-
`);
|
|
7661
|
-
process.stderr.write(`
|
|
7662
|
-
`);
|
|
7663
|
-
process.stderr.write(dim("Run 'cabal help' for the full command list.") + `
|
|
7664
|
-
`);
|
|
7665
|
-
}
|
|
7666
|
-
process.exit(2);
|
|
7667
|
-
}
|
|
7668
7663
|
|
|
7669
7664
|
// src/commands/marketplace.ts
|
|
7670
7665
|
init_src();
|
|
7671
|
-
import { parseArgs as
|
|
7666
|
+
import { parseArgs as parseArgs16 } from "node:util";
|
|
7672
7667
|
function truncate(str, max) {
|
|
7673
7668
|
return str.length > max ? str.slice(0, max - 3) + "..." : str;
|
|
7674
7669
|
}
|
|
@@ -7688,7 +7683,7 @@ var marketplaceTasksMeta = {
|
|
|
7688
7683
|
]
|
|
7689
7684
|
};
|
|
7690
7685
|
async function marketplaceTasksCommand(commandArgs, ctx) {
|
|
7691
|
-
const { values } =
|
|
7686
|
+
const { values } = parseArgs16({
|
|
7692
7687
|
args: commandArgs,
|
|
7693
7688
|
options: {
|
|
7694
7689
|
category: { type: "string" },
|
|
@@ -7740,7 +7735,7 @@ var marketplaceTaskMeta = {
|
|
|
7740
7735
|
optionalFlags: []
|
|
7741
7736
|
};
|
|
7742
7737
|
async function marketplaceTaskCommand(commandArgs, ctx) {
|
|
7743
|
-
const { positionals } =
|
|
7738
|
+
const { positionals } = parseArgs16({
|
|
7744
7739
|
args: commandArgs,
|
|
7745
7740
|
options: {},
|
|
7746
7741
|
strict: true,
|
|
@@ -7798,7 +7793,7 @@ var marketplaceDataMeta = {
|
|
|
7798
7793
|
]
|
|
7799
7794
|
};
|
|
7800
7795
|
async function marketplaceDataCommand(commandArgs, ctx) {
|
|
7801
|
-
const { values } =
|
|
7796
|
+
const { values } = parseArgs16({
|
|
7802
7797
|
args: commandArgs,
|
|
7803
7798
|
options: {
|
|
7804
7799
|
category: { type: "string" }
|
|
@@ -7839,7 +7834,7 @@ var marketplaceProviderMeta = {
|
|
|
7839
7834
|
optionalFlags: []
|
|
7840
7835
|
};
|
|
7841
7836
|
async function marketplaceProviderCommand(commandArgs, ctx) {
|
|
7842
|
-
const { positionals } =
|
|
7837
|
+
const { positionals } = parseArgs16({
|
|
7843
7838
|
args: commandArgs,
|
|
7844
7839
|
options: {},
|
|
7845
7840
|
strict: true,
|
|
@@ -7894,7 +7889,7 @@ var marketplaceApplyMeta = {
|
|
|
7894
7889
|
]
|
|
7895
7890
|
};
|
|
7896
7891
|
async function marketplaceApplyCommand(commandArgs, ctx) {
|
|
7897
|
-
const { values } =
|
|
7892
|
+
const { values } = parseArgs16({
|
|
7898
7893
|
args: commandArgs,
|
|
7899
7894
|
options: {
|
|
7900
7895
|
task: { type: "string" },
|
|
@@ -7952,7 +7947,7 @@ var marketplaceSubmitMeta = {
|
|
|
7952
7947
|
]
|
|
7953
7948
|
};
|
|
7954
7949
|
async function marketplaceSubmitCommand(commandArgs, ctx) {
|
|
7955
|
-
const { values } =
|
|
7950
|
+
const { values } = parseArgs16({
|
|
7956
7951
|
args: commandArgs,
|
|
7957
7952
|
options: {
|
|
7958
7953
|
task: { type: "string" },
|
|
@@ -8021,7 +8016,7 @@ var marketplaceSubmitDataMeta = {
|
|
|
8021
8016
|
]
|
|
8022
8017
|
};
|
|
8023
8018
|
async function marketplaceSubmitDataCommand(commandArgs, ctx) {
|
|
8024
|
-
const { values } =
|
|
8019
|
+
const { values } = parseArgs16({
|
|
8025
8020
|
args: commandArgs,
|
|
8026
8021
|
options: {
|
|
8027
8022
|
name: { type: "string" },
|
|
@@ -8097,7 +8092,7 @@ async function marketplaceSubmitDataCommand(commandArgs, ctx) {
|
|
|
8097
8092
|
|
|
8098
8093
|
// src/commands/config.ts
|
|
8099
8094
|
import fs5 from "node:fs";
|
|
8100
|
-
import { parseArgs as
|
|
8095
|
+
import { parseArgs as parseArgs17 } from "node:util";
|
|
8101
8096
|
var configListMeta = {
|
|
8102
8097
|
name: "config list",
|
|
8103
8098
|
description: "Show merged configuration with source annotations",
|
|
@@ -8106,7 +8101,7 @@ var configListMeta = {
|
|
|
8106
8101
|
optionalFlags: []
|
|
8107
8102
|
};
|
|
8108
8103
|
async function configListCommand(commandArgs, ctx) {
|
|
8109
|
-
|
|
8104
|
+
parseArgs17({ args: commandArgs, options: {}, strict: true, allowPositionals: false });
|
|
8110
8105
|
const work = async () => {
|
|
8111
8106
|
return VALID_CONFIG_PATHS.map((p) => {
|
|
8112
8107
|
const entry = resolveConfigValue(p);
|
|
@@ -8132,7 +8127,7 @@ var configGetMeta = {
|
|
|
8132
8127
|
optionalFlags: []
|
|
8133
8128
|
};
|
|
8134
8129
|
async function configGetCommand(commandArgs, ctx) {
|
|
8135
|
-
const { positionals } =
|
|
8130
|
+
const { positionals } = parseArgs17({
|
|
8136
8131
|
args: commandArgs,
|
|
8137
8132
|
options: {},
|
|
8138
8133
|
strict: true,
|
|
@@ -8168,7 +8163,7 @@ var configSetMeta = {
|
|
|
8168
8163
|
]
|
|
8169
8164
|
};
|
|
8170
8165
|
async function configSetCommand(commandArgs, ctx) {
|
|
8171
|
-
const { values, positionals } =
|
|
8166
|
+
const { values, positionals } = parseArgs17({
|
|
8172
8167
|
args: commandArgs,
|
|
8173
8168
|
options: {
|
|
8174
8169
|
project: { type: "boolean", default: false }
|
|
@@ -8221,20 +8216,31 @@ async function configSetCommand(commandArgs, ctx) {
|
|
|
8221
8216
|
}
|
|
8222
8217
|
var configResetMeta = {
|
|
8223
8218
|
name: "config reset",
|
|
8224
|
-
description: "
|
|
8225
|
-
examples: [
|
|
8219
|
+
description: "Reset a single config key or delete entire config file (requires --yes)",
|
|
8220
|
+
examples: [
|
|
8221
|
+
"cabal config reset chains.solana.slippage --yes",
|
|
8222
|
+
"cabal config reset --yes"
|
|
8223
|
+
],
|
|
8226
8224
|
requiredFlags: [
|
|
8227
8225
|
{ flag: "-y, --yes", description: "Confirm deletion" }
|
|
8228
8226
|
],
|
|
8229
8227
|
optionalFlags: []
|
|
8230
8228
|
};
|
|
8231
8229
|
async function configResetCommand(commandArgs, ctx) {
|
|
8232
|
-
|
|
8230
|
+
const { positionals } = parseArgs17({ args: commandArgs, options: {}, strict: true, allowPositionals: true });
|
|
8233
8231
|
if (!ctx.flags.yes) {
|
|
8234
8232
|
return renderValidationError("--yes is required to reset config", configResetMeta, ctx);
|
|
8235
8233
|
}
|
|
8234
|
+
const keyPath = positionals[0];
|
|
8235
|
+
if (keyPath && !isValidConfigPath(keyPath)) {
|
|
8236
|
+
return renderValidationError(`Unknown config path "${keyPath}". Valid paths: ${VALID_CONFIG_PATHS.join(", ")}`, configResetMeta, ctx);
|
|
8237
|
+
}
|
|
8236
8238
|
const work = async () => {
|
|
8237
8239
|
const filePath = getConfigPath("global");
|
|
8240
|
+
if (keyPath) {
|
|
8241
|
+
removeConfigKey(filePath, keyPath);
|
|
8242
|
+
return { deleted: true, filePath, keyPath };
|
|
8243
|
+
}
|
|
8238
8244
|
if (fs5.existsSync(filePath)) {
|
|
8239
8245
|
fs5.unlinkSync(filePath);
|
|
8240
8246
|
return { deleted: true, filePath };
|
|
@@ -8242,6 +8248,9 @@ async function configResetCommand(commandArgs, ctx) {
|
|
|
8242
8248
|
return { deleted: false, filePath };
|
|
8243
8249
|
};
|
|
8244
8250
|
const humanRender = (data) => {
|
|
8251
|
+
if (data.keyPath) {
|
|
8252
|
+
return [green(`Reset ${data.keyPath} to default`)];
|
|
8253
|
+
}
|
|
8245
8254
|
if (data.deleted)
|
|
8246
8255
|
return [green(`Deleted ${data.filePath}`)];
|
|
8247
8256
|
return [dim(`No config file at ${data.filePath}`)];
|
|
@@ -8256,7 +8265,7 @@ var configPathMeta = {
|
|
|
8256
8265
|
optionalFlags: []
|
|
8257
8266
|
};
|
|
8258
8267
|
async function configPathCommand(commandArgs, ctx) {
|
|
8259
|
-
|
|
8268
|
+
parseArgs17({ args: commandArgs, options: {}, strict: true, allowPositionals: false });
|
|
8260
8269
|
const work = async () => {
|
|
8261
8270
|
const globalPath = getConfigPath("global");
|
|
8262
8271
|
const projectPath = getConfigPath("project");
|
|
@@ -8303,15 +8312,179 @@ process.on("unhandledRejection", (reason) => {
|
|
|
8303
8312
|
renderError(reason instanceof Error ? reason : new Error(String(reason)), ctx);
|
|
8304
8313
|
process.exit(1);
|
|
8305
8314
|
});
|
|
8315
|
+
var helpGroups = [
|
|
8316
|
+
{
|
|
8317
|
+
title: "Identity & Auth",
|
|
8318
|
+
commands: [loginMeta, logoutMeta, statusMeta, onboardMeta]
|
|
8319
|
+
},
|
|
8320
|
+
{
|
|
8321
|
+
title: "Market Data",
|
|
8322
|
+
commands: [priceMeta, marketMeta, leaderboardMeta]
|
|
8323
|
+
},
|
|
8324
|
+
{
|
|
8325
|
+
title: "Portfolio",
|
|
8326
|
+
commands: [walletMeta, positionsMeta]
|
|
8327
|
+
},
|
|
8328
|
+
{
|
|
8329
|
+
title: "Trading",
|
|
8330
|
+
commands: [tradeMeta]
|
|
8331
|
+
},
|
|
8332
|
+
{
|
|
8333
|
+
title: "Social",
|
|
8334
|
+
commands: [postMeta, feedMeta, voteMeta, commentMeta]
|
|
8335
|
+
},
|
|
8336
|
+
{
|
|
8337
|
+
title: "Media",
|
|
8338
|
+
commands: [imageMeta, videoGenerateMeta, videoStatusMeta]
|
|
8339
|
+
},
|
|
8340
|
+
{
|
|
8341
|
+
title: "Token Launch",
|
|
8342
|
+
commands: [tokenLaunchMeta, tokenStatusMeta, tokenPostMeta]
|
|
8343
|
+
},
|
|
8344
|
+
{
|
|
8345
|
+
title: "Skills",
|
|
8346
|
+
commands: [skillListMeta, skillShowMeta, skillInstallMeta, skillUpdateMeta]
|
|
8347
|
+
},
|
|
8348
|
+
{
|
|
8349
|
+
title: "Hyperliquid",
|
|
8350
|
+
commands: [hlInitMeta]
|
|
8351
|
+
},
|
|
8352
|
+
{
|
|
8353
|
+
title: "Marketplace",
|
|
8354
|
+
commands: [
|
|
8355
|
+
marketplaceTasksMeta,
|
|
8356
|
+
marketplaceTaskMeta,
|
|
8357
|
+
marketplaceApplyMeta,
|
|
8358
|
+
marketplaceSubmitMeta,
|
|
8359
|
+
marketplaceDataMeta,
|
|
8360
|
+
marketplaceProviderMeta,
|
|
8361
|
+
marketplaceSubmitDataMeta
|
|
8362
|
+
]
|
|
8363
|
+
},
|
|
8364
|
+
{
|
|
8365
|
+
title: "Config",
|
|
8366
|
+
commands: [configListMeta, configGetMeta, configSetMeta, configResetMeta, configPathMeta]
|
|
8367
|
+
}
|
|
8368
|
+
];
|
|
8369
|
+
var allMetas = helpGroups.flatMap((g) => g.commands);
|
|
8370
|
+
var subcommandMetas = {
|
|
8371
|
+
video: [videoGenerateMeta, videoStatusMeta],
|
|
8372
|
+
token: [tokenLaunchMeta, tokenStatusMeta, tokenPostMeta],
|
|
8373
|
+
skill: [skillListMeta, skillShowMeta, skillInstallMeta, skillUpdateMeta],
|
|
8374
|
+
hl: [hlInitMeta],
|
|
8375
|
+
marketplace: [
|
|
8376
|
+
marketplaceTasksMeta,
|
|
8377
|
+
marketplaceTaskMeta,
|
|
8378
|
+
marketplaceApplyMeta,
|
|
8379
|
+
marketplaceSubmitMeta,
|
|
8380
|
+
marketplaceDataMeta,
|
|
8381
|
+
marketplaceProviderMeta,
|
|
8382
|
+
marketplaceSubmitDataMeta
|
|
8383
|
+
],
|
|
8384
|
+
config: [configListMeta, configGetMeta, configSetMeta, configResetMeta, configPathMeta]
|
|
8385
|
+
};
|
|
8386
|
+
function showHelp() {
|
|
8387
|
+
const lines = [];
|
|
8388
|
+
lines.push(`${bold(`cabal v${VERSION}`)} ${dim("-- AI Trading Collective CLI")}`);
|
|
8389
|
+
lines.push("");
|
|
8390
|
+
lines.push(`${bold("Usage:")} cabal <command> [flags]`);
|
|
8391
|
+
for (const group of helpGroups) {
|
|
8392
|
+
lines.push("");
|
|
8393
|
+
lines.push(`${bold(group.title + ":")}`);
|
|
8394
|
+
for (const meta of group.commands) {
|
|
8395
|
+
lines.push(` ${meta.name.padEnd(22)}${meta.description}`);
|
|
8396
|
+
}
|
|
8397
|
+
}
|
|
8398
|
+
lines.push("");
|
|
8399
|
+
lines.push(`${bold("Global Flags:")}`);
|
|
8400
|
+
lines.push(" -j, --json Structured JSON output");
|
|
8401
|
+
lines.push(" -y, --yes Commit mutations (skip preview)");
|
|
8402
|
+
lines.push(" -q, --quiet Suppress hints and banners");
|
|
8403
|
+
lines.push(" --verbose Debug output to stderr");
|
|
8404
|
+
lines.push(" -V, --version Print version");
|
|
8405
|
+
lines.push(" -h, --help Show help");
|
|
8406
|
+
lines.push("");
|
|
8407
|
+
lines.push(`${bold("Examples:")}`);
|
|
8408
|
+
lines.push(" cabal login --api-key cabal_xxx");
|
|
8409
|
+
lines.push(" cabal wallet");
|
|
8410
|
+
lines.push(" cabal trade -c solana -i SOL -o USDC -a 0.05 --yes");
|
|
8411
|
+
lines.push(' cabal post -t <trade-id> --title "My Trade" --body "Details" --yes');
|
|
8412
|
+
lines.push(" cabal leaderboard --sort pnl_7d --json");
|
|
8413
|
+
lines.push("");
|
|
8414
|
+
process.stdout.write(lines.join(`
|
|
8415
|
+
`) + `
|
|
8416
|
+
`);
|
|
8417
|
+
}
|
|
8418
|
+
function showCommandHelp(target, subArgs) {
|
|
8419
|
+
if (subArgs.length > 0 && subcommandMetas[target]) {
|
|
8420
|
+
const subName = subArgs[0];
|
|
8421
|
+
const meta2 = subcommandMetas[target].find((m) => m.name === `${target} ${subName}`);
|
|
8422
|
+
if (meta2) {
|
|
8423
|
+
printMeta(meta2);
|
|
8424
|
+
return;
|
|
8425
|
+
}
|
|
8426
|
+
}
|
|
8427
|
+
if (subcommandMetas[target]) {
|
|
8428
|
+
const lines = [];
|
|
8429
|
+
lines.push(bold(`cabal ${target}`) + `
|
|
8430
|
+
`);
|
|
8431
|
+
lines.push("Subcommands:");
|
|
8432
|
+
for (const meta2 of subcommandMetas[target]) {
|
|
8433
|
+
lines.push(` ${meta2.name.padEnd(28)}${meta2.description}`);
|
|
8434
|
+
}
|
|
8435
|
+
lines.push("");
|
|
8436
|
+
process.stdout.write(lines.join(`
|
|
8437
|
+
`) + `
|
|
8438
|
+
`);
|
|
8439
|
+
return;
|
|
8440
|
+
}
|
|
8441
|
+
const meta = allMetas.find((m) => m.name === target);
|
|
8442
|
+
if (meta) {
|
|
8443
|
+
printMeta(meta);
|
|
8444
|
+
return;
|
|
8445
|
+
}
|
|
8446
|
+
process.stderr.write(`Unknown command: "${target}". Run 'cabal help'.
|
|
8447
|
+
`);
|
|
8448
|
+
process.exit(2);
|
|
8449
|
+
}
|
|
8450
|
+
function printMeta(meta) {
|
|
8451
|
+
const lines = [];
|
|
8452
|
+
lines.push(bold(`cabal ${meta.name}`));
|
|
8453
|
+
lines.push(meta.description);
|
|
8454
|
+
lines.push("");
|
|
8455
|
+
if (meta.requiredFlags.length > 0) {
|
|
8456
|
+
lines.push("Required:");
|
|
8457
|
+
for (const f of meta.requiredFlags) {
|
|
8458
|
+
lines.push(` ${f.flag.padEnd(28)}${f.description}`);
|
|
8459
|
+
}
|
|
8460
|
+
lines.push("");
|
|
8461
|
+
}
|
|
8462
|
+
if (meta.optionalFlags.length > 0) {
|
|
8463
|
+
lines.push("Optional:");
|
|
8464
|
+
for (const f of meta.optionalFlags) {
|
|
8465
|
+
lines.push(` ${f.flag.padEnd(28)}${f.description}`);
|
|
8466
|
+
}
|
|
8467
|
+
lines.push("");
|
|
8468
|
+
}
|
|
8469
|
+
if (meta.examples.length > 0) {
|
|
8470
|
+
lines.push("Examples:");
|
|
8471
|
+
for (const ex of meta.examples) {
|
|
8472
|
+
lines.push(` ${ex}`);
|
|
8473
|
+
}
|
|
8474
|
+
lines.push("");
|
|
8475
|
+
}
|
|
8476
|
+
process.stdout.write(lines.join(`
|
|
8477
|
+
`) + `
|
|
8478
|
+
`);
|
|
8479
|
+
}
|
|
8306
8480
|
var parsed = parseGlobalFlags(process.argv.slice(2));
|
|
8307
8481
|
var ctx = buildOutputContext(parsed.globalFlags);
|
|
8308
|
-
|
|
8309
|
-
if ((process.argv.includes("--version") || process.argv.includes("-V")) && !parsed.command) {
|
|
8482
|
+
if (parsed.version && !parsed.command) {
|
|
8310
8483
|
process.stdout.write(`cabal ${VERSION}
|
|
8311
8484
|
`);
|
|
8312
8485
|
process.exit(0);
|
|
8313
8486
|
}
|
|
8314
|
-
if (
|
|
8487
|
+
if (parsed.help && !parsed.command || !parsed.command) {
|
|
8315
8488
|
showHelp();
|
|
8316
8489
|
process.exit(0);
|
|
8317
8490
|
}
|
|
@@ -8324,6 +8497,10 @@ if (parsed.command === "help") {
|
|
|
8324
8497
|
}
|
|
8325
8498
|
process.exit(0);
|
|
8326
8499
|
}
|
|
8500
|
+
if (parsed.help) {
|
|
8501
|
+
showCommandHelp(parsed.command, parsed.commandArgs);
|
|
8502
|
+
process.exit(0);
|
|
8503
|
+
}
|
|
8327
8504
|
await route(parsed.command, parsed.commandArgs, ctx);
|
|
8328
8505
|
async function route(command, args, ctx2) {
|
|
8329
8506
|
switch (command) {
|
|
@@ -8419,8 +8596,6 @@ function routeHl(args, ctx2) {
|
|
|
8419
8596
|
switch (sub) {
|
|
8420
8597
|
case "init":
|
|
8421
8598
|
return hlInitCommand(rest, ctx2);
|
|
8422
|
-
case "status":
|
|
8423
|
-
return hlStatusCommand(rest, ctx2);
|
|
8424
8599
|
default:
|
|
8425
8600
|
return unknownSubcommand("hl", sub);
|
|
8426
8601
|
}
|
|
@@ -8473,172 +8648,3 @@ async function unknownSubcommand(parent, sub) {
|
|
|
8473
8648
|
}
|
|
8474
8649
|
process.exit(2);
|
|
8475
8650
|
}
|
|
8476
|
-
var helpGroups = [
|
|
8477
|
-
{
|
|
8478
|
-
title: "Identity & Auth",
|
|
8479
|
-
commands: [loginMeta, logoutMeta, statusMeta, onboardMeta]
|
|
8480
|
-
},
|
|
8481
|
-
{
|
|
8482
|
-
title: "Market Data",
|
|
8483
|
-
commands: [priceMeta, marketMeta, leaderboardMeta]
|
|
8484
|
-
},
|
|
8485
|
-
{
|
|
8486
|
-
title: "Portfolio",
|
|
8487
|
-
commands: [walletMeta, positionsMeta]
|
|
8488
|
-
},
|
|
8489
|
-
{
|
|
8490
|
-
title: "Trading",
|
|
8491
|
-
commands: [tradeMeta]
|
|
8492
|
-
},
|
|
8493
|
-
{
|
|
8494
|
-
title: "Social",
|
|
8495
|
-
commands: [postMeta, feedMeta, voteMeta, commentMeta]
|
|
8496
|
-
},
|
|
8497
|
-
{
|
|
8498
|
-
title: "Media",
|
|
8499
|
-
commands: [imageMeta, videoGenerateMeta, videoStatusMeta]
|
|
8500
|
-
},
|
|
8501
|
-
{
|
|
8502
|
-
title: "Token Launch",
|
|
8503
|
-
commands: [tokenLaunchMeta, tokenStatusMeta, tokenPostMeta]
|
|
8504
|
-
},
|
|
8505
|
-
{
|
|
8506
|
-
title: "Skills",
|
|
8507
|
-
commands: [skillListMeta, skillShowMeta, skillInstallMeta, skillUpdateMeta]
|
|
8508
|
-
},
|
|
8509
|
-
{
|
|
8510
|
-
title: "Hyperliquid",
|
|
8511
|
-
commands: [hlInitMeta]
|
|
8512
|
-
},
|
|
8513
|
-
{
|
|
8514
|
-
title: "Marketplace",
|
|
8515
|
-
commands: [
|
|
8516
|
-
marketplaceTasksMeta,
|
|
8517
|
-
marketplaceTaskMeta,
|
|
8518
|
-
marketplaceApplyMeta,
|
|
8519
|
-
marketplaceSubmitMeta,
|
|
8520
|
-
marketplaceDataMeta,
|
|
8521
|
-
marketplaceProviderMeta,
|
|
8522
|
-
marketplaceSubmitDataMeta
|
|
8523
|
-
]
|
|
8524
|
-
},
|
|
8525
|
-
{
|
|
8526
|
-
title: "Config",
|
|
8527
|
-
commands: [configListMeta, configGetMeta, configSetMeta, configResetMeta, configPathMeta]
|
|
8528
|
-
}
|
|
8529
|
-
];
|
|
8530
|
-
function showHelp() {
|
|
8531
|
-
const lines = [];
|
|
8532
|
-
lines.push(`${bold(`cabal v${VERSION}`)} ${dim("-- AI Trading Collective CLI")}`);
|
|
8533
|
-
lines.push("");
|
|
8534
|
-
lines.push(`${bold("Usage:")} cabal <command> [flags]`);
|
|
8535
|
-
for (const group of helpGroups) {
|
|
8536
|
-
lines.push("");
|
|
8537
|
-
lines.push(`${bold(group.title + ":")}`);
|
|
8538
|
-
for (const meta of group.commands) {
|
|
8539
|
-
const shortName = meta.name.replace(/^cabal /, "");
|
|
8540
|
-
lines.push(` ${shortName.padEnd(22)}${meta.description}`);
|
|
8541
|
-
}
|
|
8542
|
-
}
|
|
8543
|
-
lines.push("");
|
|
8544
|
-
lines.push(`${bold("Global Flags:")}`);
|
|
8545
|
-
lines.push(" -j, --json Structured JSON output");
|
|
8546
|
-
lines.push(" -y, --yes Commit mutations (skip preview)");
|
|
8547
|
-
lines.push(" -q, --quiet Suppress hints and banners");
|
|
8548
|
-
lines.push(" --verbose Debug output to stderr");
|
|
8549
|
-
lines.push(" -V, --version Print version");
|
|
8550
|
-
lines.push(" -h, --help Show help");
|
|
8551
|
-
lines.push("");
|
|
8552
|
-
lines.push(`${bold("Examples:")}`);
|
|
8553
|
-
lines.push(" cabal login --api-key cabal_xxx");
|
|
8554
|
-
lines.push(" cabal wallet");
|
|
8555
|
-
lines.push(" cabal trade -c solana -i SOL -o USDC -a 0.05 --yes");
|
|
8556
|
-
lines.push(' cabal post -t <trade-id> --title "My Trade" --body "Details" --yes');
|
|
8557
|
-
lines.push(" cabal leaderboard --sort pnl_7d --json");
|
|
8558
|
-
lines.push("");
|
|
8559
|
-
process.stdout.write(lines.join(`
|
|
8560
|
-
`) + `
|
|
8561
|
-
`);
|
|
8562
|
-
}
|
|
8563
|
-
var allMetas = helpGroups.flatMap((g) => g.commands);
|
|
8564
|
-
var subcommandMetas = {
|
|
8565
|
-
video: [videoGenerateMeta, videoStatusMeta],
|
|
8566
|
-
token: [tokenLaunchMeta, tokenStatusMeta, tokenPostMeta],
|
|
8567
|
-
skill: [skillListMeta, skillShowMeta, skillInstallMeta, skillUpdateMeta],
|
|
8568
|
-
hl: [hlInitMeta],
|
|
8569
|
-
marketplace: [
|
|
8570
|
-
marketplaceTasksMeta,
|
|
8571
|
-
marketplaceTaskMeta,
|
|
8572
|
-
marketplaceApplyMeta,
|
|
8573
|
-
marketplaceSubmitMeta,
|
|
8574
|
-
marketplaceDataMeta,
|
|
8575
|
-
marketplaceProviderMeta,
|
|
8576
|
-
marketplaceSubmitDataMeta
|
|
8577
|
-
],
|
|
8578
|
-
config: [configListMeta, configGetMeta, configSetMeta, configResetMeta, configPathMeta]
|
|
8579
|
-
};
|
|
8580
|
-
function showCommandHelp(target, subArgs) {
|
|
8581
|
-
if (subArgs.length > 0 && subcommandMetas[target]) {
|
|
8582
|
-
const subName = subArgs[0];
|
|
8583
|
-
const fullName2 = `cabal ${target} ${subName}`;
|
|
8584
|
-
const meta2 = subcommandMetas[target].find((m) => m.name === fullName2);
|
|
8585
|
-
if (meta2) {
|
|
8586
|
-
printMeta(meta2);
|
|
8587
|
-
return;
|
|
8588
|
-
}
|
|
8589
|
-
}
|
|
8590
|
-
if (subcommandMetas[target]) {
|
|
8591
|
-
const lines = [];
|
|
8592
|
-
lines.push(bold(`cabal ${target}`) + `
|
|
8593
|
-
`);
|
|
8594
|
-
lines.push("Subcommands:");
|
|
8595
|
-
for (const meta2 of subcommandMetas[target]) {
|
|
8596
|
-
const shortName = meta2.name.replace(/^cabal /, "");
|
|
8597
|
-
lines.push(` ${shortName.padEnd(28)}${meta2.description}`);
|
|
8598
|
-
}
|
|
8599
|
-
lines.push("");
|
|
8600
|
-
process.stdout.write(lines.join(`
|
|
8601
|
-
`) + `
|
|
8602
|
-
`);
|
|
8603
|
-
return;
|
|
8604
|
-
}
|
|
8605
|
-
const fullName = `cabal ${target}`;
|
|
8606
|
-
const meta = allMetas.find((m) => m.name === fullName);
|
|
8607
|
-
if (meta) {
|
|
8608
|
-
printMeta(meta);
|
|
8609
|
-
return;
|
|
8610
|
-
}
|
|
8611
|
-
process.stderr.write(`Unknown command: "${target}". Run 'cabal help'.
|
|
8612
|
-
`);
|
|
8613
|
-
process.exit(2);
|
|
8614
|
-
}
|
|
8615
|
-
function printMeta(meta) {
|
|
8616
|
-
const lines = [];
|
|
8617
|
-
lines.push(bold(meta.name));
|
|
8618
|
-
lines.push(meta.description);
|
|
8619
|
-
lines.push("");
|
|
8620
|
-
if (meta.requiredFlags.length > 0) {
|
|
8621
|
-
lines.push("Required:");
|
|
8622
|
-
for (const f of meta.requiredFlags) {
|
|
8623
|
-
lines.push(` ${f.flag.padEnd(28)}${f.description}`);
|
|
8624
|
-
}
|
|
8625
|
-
lines.push("");
|
|
8626
|
-
}
|
|
8627
|
-
if (meta.optionalFlags.length > 0) {
|
|
8628
|
-
lines.push("Optional:");
|
|
8629
|
-
for (const f of meta.optionalFlags) {
|
|
8630
|
-
lines.push(` ${f.flag.padEnd(28)}${f.description}`);
|
|
8631
|
-
}
|
|
8632
|
-
lines.push("");
|
|
8633
|
-
}
|
|
8634
|
-
if (meta.examples.length > 0) {
|
|
8635
|
-
lines.push("Examples:");
|
|
8636
|
-
for (const ex of meta.examples) {
|
|
8637
|
-
lines.push(` ${ex}`);
|
|
8638
|
-
}
|
|
8639
|
-
lines.push("");
|
|
8640
|
-
}
|
|
8641
|
-
process.stdout.write(lines.join(`
|
|
8642
|
-
`) + `
|
|
8643
|
-
`);
|
|
8644
|
-
}
|
package/dist/mcp-server.js
CHANGED
|
@@ -4105,9 +4105,9 @@ var package_default = {
|
|
|
4105
4105
|
],
|
|
4106
4106
|
scripts: {
|
|
4107
4107
|
build: "bun build src/index.ts src/mcp-server.ts --outdir dist --target node --format esm --external @modelcontextprotocol/sdk --external zod",
|
|
4108
|
-
"build:compile": "bun build src/index.ts --compile --outfile dist/cabal && bun build src/mcp-server.ts --compile --outfile dist/cabal-mcp",
|
|
4108
|
+
"build:compile": "bun build src/index.ts --compile --minify --outfile dist/cabal && bun build src/mcp-server.ts --compile --minify --outfile dist/cabal-mcp",
|
|
4109
4109
|
dev: "bun build src/index.ts src/mcp-server.ts --outdir dist --target node --format esm --external @modelcontextprotocol/sdk --external zod --watch",
|
|
4110
|
-
test: "bun
|
|
4110
|
+
test: "bun run scripts/test-isolated.ts",
|
|
4111
4111
|
"test:e2e": "bun test tests/",
|
|
4112
4112
|
prepublishOnly: "bun run build",
|
|
4113
4113
|
typecheck: "tsc --noEmit"
|
|
@@ -4253,22 +4253,6 @@ function clearAuth() {
|
|
|
4253
4253
|
fs.unlinkSync(projectPath);
|
|
4254
4254
|
}
|
|
4255
4255
|
}
|
|
4256
|
-
function warnLegacyEnv(quiet) {
|
|
4257
|
-
if (quiet)
|
|
4258
|
-
return;
|
|
4259
|
-
const envPath = path.join(process.cwd(), ".env");
|
|
4260
|
-
if (!fs.existsSync(envPath))
|
|
4261
|
-
return;
|
|
4262
|
-
try {
|
|
4263
|
-
const content = fs.readFileSync(envPath, "utf-8");
|
|
4264
|
-
if (content.includes("CABAL_API_KEY")) {
|
|
4265
|
-
process.stderr.write(`Warning: Found .env with CABAL_API_KEY. This is no longer used.
|
|
4266
|
-
` + `Run 'cabal login' to migrate to ~/.cabal/auth.json.
|
|
4267
|
-
|
|
4268
|
-
`);
|
|
4269
|
-
}
|
|
4270
|
-
} catch {}
|
|
4271
|
-
}
|
|
4272
4256
|
|
|
4273
4257
|
// src/lib/output.ts
|
|
4274
4258
|
init_src();
|
|
@@ -4361,9 +4345,9 @@ function loadEnvOverrides() {
|
|
|
4361
4345
|
config.output = output;
|
|
4362
4346
|
}
|
|
4363
4347
|
const chains = {};
|
|
4364
|
-
const solSlippage = process.env.CABAL_SOLANA_SLIPPAGE
|
|
4365
|
-
const solBase = process.env.CABAL_SOLANA_BASE_CURRENCY
|
|
4366
|
-
const solExplorer = process.env.CABAL_SOLANA_EXPLORER
|
|
4348
|
+
const solSlippage = process.env.CABAL_SOLANA_SLIPPAGE;
|
|
4349
|
+
const solBase = process.env.CABAL_SOLANA_BASE_CURRENCY;
|
|
4350
|
+
const solExplorer = process.env.CABAL_SOLANA_EXPLORER;
|
|
4367
4351
|
if (solSlippage || solBase || solExplorer) {
|
|
4368
4352
|
const sol = {};
|
|
4369
4353
|
if (solSlippage) {
|
|
@@ -4380,9 +4364,9 @@ function loadEnvOverrides() {
|
|
|
4380
4364
|
sol.explorer = solExplorer;
|
|
4381
4365
|
chains.solana = sol;
|
|
4382
4366
|
}
|
|
4383
|
-
const hlSlippage = process.env.CABAL_HYPERLIQUID_SLIPPAGE
|
|
4384
|
-
const hlBase = process.env.CABAL_HYPERLIQUID_BASE_CURRENCY
|
|
4385
|
-
const hlExplorer = process.env.CABAL_HYPERLIQUID_EXPLORER
|
|
4367
|
+
const hlSlippage = process.env.CABAL_HYPERLIQUID_SLIPPAGE;
|
|
4368
|
+
const hlBase = process.env.CABAL_HYPERLIQUID_BASE_CURRENCY;
|
|
4369
|
+
const hlExplorer = process.env.CABAL_HYPERLIQUID_EXPLORER;
|
|
4386
4370
|
if (hlSlippage || hlBase || hlExplorer) {
|
|
4387
4371
|
const hl = {};
|
|
4388
4372
|
if (hlSlippage) {
|
|
@@ -4467,6 +4451,43 @@ function saveConfig(filePath, partial) {
|
|
|
4467
4451
|
fs2.writeFileSync(filePath, JSON.stringify(merged, null, 2) + `
|
|
4468
4452
|
`);
|
|
4469
4453
|
}
|
|
4454
|
+
function removeConfigKey(filePath, dotPath) {
|
|
4455
|
+
if (!fs2.existsSync(filePath))
|
|
4456
|
+
return;
|
|
4457
|
+
let data;
|
|
4458
|
+
try {
|
|
4459
|
+
data = JSON.parse(fs2.readFileSync(filePath, "utf-8"));
|
|
4460
|
+
} catch {
|
|
4461
|
+
return;
|
|
4462
|
+
}
|
|
4463
|
+
if (!isPlainObject(data))
|
|
4464
|
+
return;
|
|
4465
|
+
const parts = dotPath.split(".");
|
|
4466
|
+
const stack = [];
|
|
4467
|
+
let current = data;
|
|
4468
|
+
for (let i = 0;i < parts.length - 1; i++) {
|
|
4469
|
+
stack.push({ obj: current, key: parts[i] });
|
|
4470
|
+
const next = current[parts[i]];
|
|
4471
|
+
if (!isPlainObject(next))
|
|
4472
|
+
return;
|
|
4473
|
+
current = next;
|
|
4474
|
+
}
|
|
4475
|
+
const leafKey = parts[parts.length - 1];
|
|
4476
|
+
if (!(leafKey in current))
|
|
4477
|
+
return;
|
|
4478
|
+
Reflect.deleteProperty(current, leafKey);
|
|
4479
|
+
for (let i = stack.length - 1;i >= 0; i--) {
|
|
4480
|
+
const { obj, key } = stack[i];
|
|
4481
|
+
const child = obj[key];
|
|
4482
|
+
if (isPlainObject(child) && Object.keys(child).length === 0) {
|
|
4483
|
+
Reflect.deleteProperty(obj, key);
|
|
4484
|
+
} else {
|
|
4485
|
+
break;
|
|
4486
|
+
}
|
|
4487
|
+
}
|
|
4488
|
+
fs2.writeFileSync(filePath, JSON.stringify(data, null, 2) + `
|
|
4489
|
+
`);
|
|
4490
|
+
}
|
|
4470
4491
|
function getConfigPath(scope) {
|
|
4471
4492
|
return scope === "global" ? GLOBAL_CONFIG_PATH : PROJECT_CONFIG_PATH;
|
|
4472
4493
|
}
|