@otonix/cli 1.5.0 → 1.6.0
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/dist/cli.js +144 -76
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -28,7 +28,7 @@ var import_sdk = require("@otonix/sdk");
|
|
|
28
28
|
var fs = __toESM(require("fs"));
|
|
29
29
|
var path = __toESM(require("path"));
|
|
30
30
|
var readline = __toESM(require("readline"));
|
|
31
|
-
var VERSION = "1.
|
|
31
|
+
var VERSION = "1.6.0";
|
|
32
32
|
var CONFIG_DIR = path.join(process.env.HOME || "~", ".otonix");
|
|
33
33
|
var CONFIG_FILE = path.join(CONFIG_DIR, "config.json");
|
|
34
34
|
function loadConfig() {
|
|
@@ -87,71 +87,132 @@ function formatTime(dateStr) {
|
|
|
87
87
|
if (ago < 86400) return `${Math.floor(ago / 3600)}h ago`;
|
|
88
88
|
return `${Math.floor(ago / 86400)}d ago`;
|
|
89
89
|
}
|
|
90
|
-
var
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
bv7x:spawn Spawn a satellite from a BV-7X template
|
|
119
|
-
bv7x:satellites <id> List satellites of a mothership
|
|
120
|
-
bv7x:destroy <id> Destroy (terminate) a satellite
|
|
121
|
-
bv7x:report <id> Send a satellite data report
|
|
122
|
-
bv7x:fleet Show full BV-7X fleet overview
|
|
123
|
-
webhook:create Create a new webhook endpoint
|
|
124
|
-
webhook:list List registered webhooks
|
|
125
|
-
webhook:delete <id> Delete a webhook
|
|
126
|
-
webhook:test <id> Send a test delivery to a webhook
|
|
127
|
-
webhook:deliveries Show webhook delivery history
|
|
128
|
-
webhook:events List all available webhook events
|
|
129
|
-
trade:list List all service listings on marketplace
|
|
130
|
-
trade:create Create a service listing for an agent
|
|
131
|
-
trade:buy Buy a service from another agent
|
|
132
|
-
trade:orders Show trading order history
|
|
133
|
-
activity [--limit N] Show live activity feed
|
|
134
|
-
llm:init <key> Configure Bankr LLM Gateway API key
|
|
135
|
-
llm:models List available LLM models
|
|
136
|
-
llm:chat <prompt> Send a chat completion request
|
|
137
|
-
llm:usage [--days N] Show LLM usage summary
|
|
138
|
-
llm:health Check gateway health
|
|
139
|
-
whoami Show current configuration
|
|
140
|
-
version Show CLI version
|
|
141
|
-
help Show this help
|
|
142
|
-
|
|
143
|
-
Examples:
|
|
144
|
-
otonix init
|
|
145
|
-
otonix keygen my-vps-key
|
|
146
|
-
otonix register --name my-agent --model claude-opus-4-6
|
|
147
|
-
otonix heartbeat:loop
|
|
148
|
-
otonix log "Trade executed BTC/USDC" --category trading
|
|
149
|
-
otonix actions --limit 20
|
|
150
|
-
otonix llm:init bk_YOUR_API_KEY
|
|
151
|
-
otonix llm:chat "Explain smart contracts" --model claude-haiku-4.5
|
|
90
|
+
var C = {
|
|
91
|
+
reset: "\x1B[0m",
|
|
92
|
+
bold: "\x1B[1m",
|
|
93
|
+
dim: "\x1B[2m",
|
|
94
|
+
cyan: "\x1B[36m",
|
|
95
|
+
green: "\x1B[32m",
|
|
96
|
+
yellow: "\x1B[33m",
|
|
97
|
+
blue: "\x1B[34m",
|
|
98
|
+
magenta: "\x1B[35m",
|
|
99
|
+
white: "\x1B[37m",
|
|
100
|
+
gray: "\x1B[90m",
|
|
101
|
+
bgCyan: "\x1B[46m",
|
|
102
|
+
bgBlue: "\x1B[44m"
|
|
103
|
+
};
|
|
104
|
+
var BANNER = `
|
|
105
|
+
${C.cyan}${C.bold} \u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557
|
|
106
|
+
\u2551 \u2551
|
|
107
|
+
\u2551 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2557\u2588\u2588\u2557 \u2588\u2588\u2557 \u2551
|
|
108
|
+
\u2551 \u2588\u2588\u2554\u2550\u2550\u2550\u2588\u2588\u2557\u255A\u2550\u2550\u2588\u2588\u2554\u2550\u2550\u255D\u2588\u2588\u2554\u2550\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2551\u2588\u2588\u2551\u255A\u2588\u2588\u2557\u2588\u2588\u2554\u255D \u2551
|
|
109
|
+
\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2554\u2588\u2588\u2557 \u2588\u2588\u2551\u2588\u2588\u2551 \u255A\u2588\u2588\u2588\u2554\u255D \u2551
|
|
110
|
+
\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551\u255A\u2588\u2588\u2557\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2554\u2588\u2588\u2557 \u2551
|
|
111
|
+
\u2551 \u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D \u2588\u2588\u2551 \u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2551 \u255A\u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2551\u2588\u2588\u2554\u255D \u2588\u2588\u2557 \u2551
|
|
112
|
+
\u2551 \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u2550\u2550\u255D\u255A\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u255D \u2551
|
|
113
|
+
\u2551 \u2551
|
|
114
|
+
\u2551${C.reset}${C.dim} Sovereign Compute Platform for Autonomous AI Agents ${C.cyan}${C.bold} \u2551
|
|
115
|
+
\u2551${C.reset}${C.gray} v${VERSION} \u2022 Web4 \u2022 x402 \u2022 Base Chain ${C.cyan}${C.bold} \u2551
|
|
116
|
+
\u2551 \u2551
|
|
117
|
+
\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D${C.reset}
|
|
152
118
|
`;
|
|
119
|
+
function showDashboard() {
|
|
120
|
+
console.log(BANNER);
|
|
121
|
+
const config = loadConfig();
|
|
122
|
+
const connected = !!config;
|
|
123
|
+
const statusIcon = connected ? `${C.green}\u25CF${C.reset}` : `${C.yellow}\u25CB${C.reset}`;
|
|
124
|
+
const statusText = connected ? `${C.green}Connected${C.reset}` : `${C.yellow}Not configured${C.reset}`;
|
|
125
|
+
console.log(` ${C.dim}\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510${C.reset}`);
|
|
126
|
+
console.log(` ${C.dim}\u2502${C.reset} ${statusIcon} Status: ${statusText}${connected ? ` ${C.dim}\u2022${C.reset} ${C.gray}${config.endpoint}${C.reset}` : ` ${C.dim}\u2022${C.reset} ${C.gray}Run: otonix init${C.reset}`}`);
|
|
127
|
+
if (connected && config.agentName) {
|
|
128
|
+
console.log(` ${C.dim}\u2502${C.reset} Agent: ${C.bold}${config.agentName}${C.reset} ${C.dim}(${config.agentId?.slice(0, 8)}...)${C.reset}`);
|
|
129
|
+
}
|
|
130
|
+
console.log(` ${C.dim}\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518${C.reset}`);
|
|
131
|
+
console.log();
|
|
132
|
+
const section = (title, icon) => ` ${C.bold}${icon} ${title}${C.reset}`;
|
|
133
|
+
const cmd = (name, desc) => ` ${C.dim}\u2502${C.reset} ${C.cyan}${name.padEnd(24)}${C.reset}${C.gray}${desc}${C.reset}`;
|
|
134
|
+
const sep = () => ` ${C.dim}\u2502${C.reset}`;
|
|
135
|
+
console.log(section("SETUP", "\u26A1"));
|
|
136
|
+
console.log(cmd("init", "Configure API key and endpoint"));
|
|
137
|
+
console.log(cmd("keygen <name>", "Generate a new API key"));
|
|
138
|
+
console.log(cmd("whoami", "Show current configuration"));
|
|
139
|
+
console.log();
|
|
140
|
+
console.log(section("AGENT MANAGEMENT", "\u{1F916}"));
|
|
141
|
+
console.log(cmd("register", "Register an agent on this VPS"));
|
|
142
|
+
console.log(cmd("status", "Show agent status"));
|
|
143
|
+
console.log(cmd("agents", "List all connected agents"));
|
|
144
|
+
console.log(cmd("heartbeat", "Send a heartbeat ping"));
|
|
145
|
+
console.log(cmd("heartbeat:loop", "Start continuous heartbeat loop"));
|
|
146
|
+
console.log(cmd("actions [--limit N]", "Show agent action log"));
|
|
147
|
+
console.log(cmd("log <message>", "Log an agent action"));
|
|
148
|
+
console.log();
|
|
149
|
+
console.log(section("INFRASTRUCTURE", "\u2601\uFE0F"));
|
|
150
|
+
console.log(cmd("sandboxes", "List VPS sandboxes"));
|
|
151
|
+
console.log(cmd("domains", "List registered domains"));
|
|
152
|
+
console.log(cmd("engine", "Show autonomic engine status"));
|
|
153
|
+
console.log();
|
|
154
|
+
console.log(section("CREDITS & PAYMENTS", "\u{1F4B0}"));
|
|
155
|
+
console.log(cmd("credits <agentId>", "Show agent credit balance"));
|
|
156
|
+
console.log(cmd("credits:transfer", "Transfer credits between agents"));
|
|
157
|
+
console.log(cmd("credits:history <id>", "Show credit transaction history"));
|
|
158
|
+
console.log(cmd("x402", "Show x402 payment config"));
|
|
159
|
+
console.log();
|
|
160
|
+
console.log(section("TRADING MARKETPLACE", "\u{1F3EA}"));
|
|
161
|
+
console.log(cmd("trade:list", "List all service listings"));
|
|
162
|
+
console.log(cmd("trade:create", "Create a service listing"));
|
|
163
|
+
console.log(cmd("trade:buy", "Buy a service from another agent"));
|
|
164
|
+
console.log(cmd("trade:orders", "Show trading order history"));
|
|
165
|
+
console.log(cmd("marketplace", "List static marketplace services"));
|
|
166
|
+
console.log();
|
|
167
|
+
console.log(section("BV-7X FLEET", "\u{1F6F0}\uFE0F"));
|
|
168
|
+
console.log(cmd("bv7x:fleet", "Show full fleet overview"));
|
|
169
|
+
console.log(cmd("bv7x:promote <id>", "Promote agent to mothership"));
|
|
170
|
+
console.log(cmd("bv7x:spawn", "Spawn a satellite agent"));
|
|
171
|
+
console.log(cmd("bv7x:satellites <id>", "List mothership's satellites"));
|
|
172
|
+
console.log(cmd("bv7x:destroy <id>", "Destroy a satellite"));
|
|
173
|
+
console.log(cmd("bv7x:report <id>", "Send satellite data report"));
|
|
174
|
+
console.log();
|
|
175
|
+
console.log(section("TEMPLATES", "\u{1F4E6}"));
|
|
176
|
+
console.log(cmd("templates", "List available agent templates"));
|
|
177
|
+
console.log(cmd("templates:info <slug>", "Show template details"));
|
|
178
|
+
console.log(cmd("templates:deploy", "Deploy agent from a template"));
|
|
179
|
+
console.log();
|
|
180
|
+
console.log(section("WEBHOOKS", "\u{1F514}"));
|
|
181
|
+
console.log(cmd("webhook:create", "Create a new webhook"));
|
|
182
|
+
console.log(cmd("webhook:list", "List registered webhooks"));
|
|
183
|
+
console.log(cmd("webhook:delete <id>", "Delete a webhook"));
|
|
184
|
+
console.log(cmd("webhook:test <id>", "Send a test delivery"));
|
|
185
|
+
console.log(cmd("webhook:deliveries", "Show delivery history"));
|
|
186
|
+
console.log(cmd("webhook:events", "List available event types"));
|
|
187
|
+
console.log();
|
|
188
|
+
console.log(section("AI INFERENCE (Bankr LLM)", "\u{1F9E0}"));
|
|
189
|
+
console.log(cmd("llm:init <key>", "Configure Bankr API key"));
|
|
190
|
+
console.log(cmd("llm:models", "List available LLM models"));
|
|
191
|
+
console.log(cmd("llm:chat <prompt>", "Send a chat completion"));
|
|
192
|
+
console.log(cmd("llm:usage [--days N]", "Show LLM usage summary"));
|
|
193
|
+
console.log(cmd("llm:health", "Check gateway health"));
|
|
194
|
+
console.log();
|
|
195
|
+
console.log(section("ACTIVITY", "\u{1F4E1}"));
|
|
196
|
+
console.log(cmd("activity [--limit N]", "Show live activity feed"));
|
|
197
|
+
console.log();
|
|
198
|
+
console.log(` ${C.dim}\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500${C.reset}`);
|
|
199
|
+
console.log(` ${C.gray}Examples:${C.reset}`);
|
|
200
|
+
console.log(` ${C.dim}$${C.reset} ${C.white}otonix init${C.reset}`);
|
|
201
|
+
console.log(` ${C.dim}$${C.reset} ${C.white}otonix register --name my-agent --model claude-opus-4-6${C.reset}`);
|
|
202
|
+
console.log(` ${C.dim}$${C.reset} ${C.white}otonix heartbeat:loop${C.reset}`);
|
|
203
|
+
console.log(` ${C.dim}$${C.reset} ${C.white}otonix trade:list${C.reset}`);
|
|
204
|
+
console.log(` ${C.dim}$${C.reset} ${C.white}otonix llm:chat "Explain smart contracts"${C.reset}`);
|
|
205
|
+
console.log();
|
|
206
|
+
console.log(` ${C.dim}Docs: ${C.cyan}https://app.otonix.tech/docs${C.reset} ${C.dim}\u2022${C.reset} ${C.dim}npm: ${C.cyan}@otonix/cli@${VERSION}${C.reset}`);
|
|
207
|
+
console.log();
|
|
208
|
+
}
|
|
209
|
+
function showBanner() {
|
|
210
|
+
console.log(BANNER);
|
|
211
|
+
}
|
|
153
212
|
async function cmdInit() {
|
|
154
|
-
|
|
213
|
+
showBanner();
|
|
214
|
+
console.log(` ${C.bold}\u26A1 CLI Setup${C.reset}
|
|
215
|
+
`);
|
|
155
216
|
const endpoint = await prompt(" Endpoint [https://app.otonix.tech]: ") || "https://app.otonix.tech";
|
|
156
217
|
const apiKey = await prompt(" API Key (otonix_xxx): ");
|
|
157
218
|
if (!apiKey.startsWith("otonix_")) {
|
|
@@ -1211,14 +1272,17 @@ function cmdWhoami() {
|
|
|
1211
1272
|
console.log(" Not configured. Run 'otonix init' first.");
|
|
1212
1273
|
return;
|
|
1213
1274
|
}
|
|
1214
|
-
|
|
1215
|
-
Current
|
|
1216
|
-
|
|
1217
|
-
console.log(`
|
|
1218
|
-
console.log(`
|
|
1219
|
-
console.log(`
|
|
1220
|
-
console.log(`
|
|
1221
|
-
console.log(`
|
|
1275
|
+
showBanner();
|
|
1276
|
+
console.log(` ${C.bold}\u{1F511} Current Configuration${C.reset}
|
|
1277
|
+
`);
|
|
1278
|
+
console.log(` ${C.dim}\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510${C.reset}`);
|
|
1279
|
+
console.log(` ${C.dim}\u2502${C.reset} Endpoint ${C.cyan}${config.endpoint}${C.reset}`);
|
|
1280
|
+
console.log(` ${C.dim}\u2502${C.reset} API Key ${C.gray}${config.apiKey.slice(0, 12)}...${config.apiKey.slice(-4)}${C.reset}`);
|
|
1281
|
+
console.log(` ${C.dim}\u2502${C.reset} Agent ID ${config.agentId ? `${C.green}${config.agentId.slice(0, 12)}...${C.reset}` : `${C.yellow}not registered${C.reset}`}`);
|
|
1282
|
+
console.log(` ${C.dim}\u2502${C.reset} Agent ${config.agentName ? `${C.bold}${config.agentName}${C.reset}` : `${C.gray}\u2014${C.reset}`}`);
|
|
1283
|
+
console.log(` ${C.dim}\u2502${C.reset} Bankr LLM ${config.bankrApiKey ? `${C.green}${config.bankrApiKey.slice(0, 6)}...${config.bankrApiKey.slice(-4)}${C.reset}` : `${C.gray}not configured${C.reset}`}`);
|
|
1284
|
+
console.log(` ${C.dim}\u2502${C.reset} Config ${C.gray}${CONFIG_FILE}${C.reset}`);
|
|
1285
|
+
console.log(` ${C.dim}\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518${C.reset}
|
|
1222
1286
|
`);
|
|
1223
1287
|
}
|
|
1224
1288
|
async function main() {
|
|
@@ -1359,16 +1423,20 @@ async function main() {
|
|
|
1359
1423
|
case "version":
|
|
1360
1424
|
case "-v":
|
|
1361
1425
|
case "--version":
|
|
1362
|
-
|
|
1426
|
+
showBanner();
|
|
1427
|
+
console.log(` ${C.green}${C.bold}v${VERSION}${C.reset} ${C.dim}@otonix/cli${C.reset}`);
|
|
1428
|
+
console.log();
|
|
1363
1429
|
break;
|
|
1364
1430
|
case "help":
|
|
1365
1431
|
case "-h":
|
|
1366
1432
|
case "--help":
|
|
1367
|
-
|
|
1433
|
+
showDashboard();
|
|
1368
1434
|
break;
|
|
1369
1435
|
default:
|
|
1370
|
-
console.error(`
|
|
1371
|
-
|
|
1436
|
+
console.error(`
|
|
1437
|
+
${C.yellow}Unknown command: ${command}${C.reset}
|
|
1438
|
+
`);
|
|
1439
|
+
showDashboard();
|
|
1372
1440
|
process.exit(1);
|
|
1373
1441
|
}
|
|
1374
1442
|
} catch (err) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@otonix/cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.6.0",
|
|
4
4
|
"description": "CLI tool for the Otonix sovereign compute platform — initialize agents, generate API keys, register, monitor status, BV-7X fleet orchestration, webhook management, and manage infrastructure from the terminal.",
|
|
5
5
|
"main": "dist/cli.js",
|
|
6
6
|
"bin": {
|