vigthoria-cli 1.10.47 → 1.10.49
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/commands/agent-session-menu.js +2 -8
- package/dist/commands/auth.js +51 -68
- package/dist/commands/bridge.js +42 -22
- package/dist/commands/cancel.js +15 -22
- package/dist/commands/chat.d.ts +3 -0
- package/dist/commands/chat.js +326 -295
- package/dist/commands/config.js +33 -73
- package/dist/commands/deploy.js +83 -123
- package/dist/commands/device.js +21 -61
- package/dist/commands/edit.js +32 -39
- package/dist/commands/explain.js +18 -25
- package/dist/commands/fork.d.ts +17 -0
- package/dist/commands/fork.js +164 -0
- package/dist/commands/generate.js +37 -44
- package/dist/commands/history.d.ts +17 -0
- package/dist/commands/history.js +113 -0
- package/dist/commands/hub.js +95 -102
- package/dist/commands/index.js +41 -46
- package/dist/commands/legion.js +146 -186
- package/dist/commands/preview.d.ts +55 -0
- package/dist/commands/preview.js +467 -0
- package/dist/commands/replay.d.ts +18 -0
- package/dist/commands/replay.js +156 -0
- package/dist/commands/repo.d.ts +97 -0
- package/dist/commands/repo.js +773 -0
- package/dist/commands/review.js +29 -36
- package/dist/commands/security.js +5 -12
- package/dist/commands/update.d.ts +9 -0
- package/dist/commands/update.js +201 -0
- package/dist/commands/wallet.js +28 -35
- package/dist/commands/workflow.js +13 -20
- package/dist/index.d.ts +21 -0
- package/dist/index.js +1652 -0
- package/dist/utils/api.d.ts +544 -0
- package/dist/utils/api.js +5486 -0
- package/dist/utils/brain-hub-client.js +1 -5
- package/dist/utils/bridge-client.js +11 -52
- package/dist/utils/cli-state.d.ts +54 -0
- package/dist/utils/cli-state.js +185 -0
- package/dist/utils/codebase-indexer.js +4 -41
- package/dist/utils/config.d.ts +82 -0
- package/dist/utils/config.js +269 -0
- package/dist/utils/context-ranker.js +15 -21
- package/dist/utils/desktop-bridge-client.d.ts +12 -0
- package/dist/utils/desktop-bridge-client.js +30 -0
- package/dist/utils/files.js +5 -42
- package/dist/utils/logger.js +42 -50
- package/dist/utils/persona.js +3 -8
- package/dist/utils/post-write-validator.js +26 -33
- package/dist/utils/project-memory.js +16 -23
- package/dist/utils/session.d.ts +118 -0
- package/dist/utils/session.js +423 -0
- package/dist/utils/task-display.js +13 -20
- package/dist/utils/tools.d.ts +269 -0
- package/dist/utils/tools.js +3450 -0
- package/dist/utils/workspace-brain-service.js +8 -45
- package/dist/utils/workspace-cache.js +18 -26
- package/dist/utils/workspace-stream.js +21 -63
- package/package.json +2 -1
- package/scripts/release/validate-no-go-gates.sh +7 -4
package/dist/commands/legion.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
"use strict";
|
|
2
1
|
/**
|
|
3
2
|
* Vigthoria CLI - Legion Parallel Orchestration
|
|
4
3
|
*
|
|
@@ -9,52 +8,14 @@
|
|
|
9
8
|
* vigthoria legion --workers List available Legion workers
|
|
10
9
|
* vigthoria legion --status Show Legion infrastructure status
|
|
11
10
|
*/
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
if (k2 === undefined) k2 = k;
|
|
21
|
-
o[k2] = m[k];
|
|
22
|
-
}));
|
|
23
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
24
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
25
|
-
}) : function(o, v) {
|
|
26
|
-
o["default"] = v;
|
|
27
|
-
});
|
|
28
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
29
|
-
var ownKeys = function(o) {
|
|
30
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
31
|
-
var ar = [];
|
|
32
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
33
|
-
return ar;
|
|
34
|
-
};
|
|
35
|
-
return ownKeys(o);
|
|
36
|
-
};
|
|
37
|
-
return function (mod) {
|
|
38
|
-
if (mod && mod.__esModule) return mod;
|
|
39
|
-
var result = {};
|
|
40
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
41
|
-
__setModuleDefault(result, mod);
|
|
42
|
-
return result;
|
|
43
|
-
};
|
|
44
|
-
})();
|
|
45
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
46
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
47
|
-
};
|
|
48
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
49
|
-
exports.LegionCommand = void 0;
|
|
50
|
-
const chalk_1 = __importDefault(require("chalk"));
|
|
51
|
-
const fs = __importStar(require("fs"));
|
|
52
|
-
const path = __importStar(require("path"));
|
|
53
|
-
const readline = __importStar(require("readline/promises"));
|
|
54
|
-
const node_child_process_1 = require("node:child_process");
|
|
55
|
-
const node_util_1 = require("node:util");
|
|
56
|
-
const logger_js_1 = require("../utils/logger.js");
|
|
57
|
-
const api_js_1 = require("../utils/api.js");
|
|
11
|
+
import chalk from 'chalk';
|
|
12
|
+
import * as fs from 'fs';
|
|
13
|
+
import * as path from 'path';
|
|
14
|
+
import * as readline from 'readline/promises';
|
|
15
|
+
import { exec as execCallback } from 'node:child_process';
|
|
16
|
+
import { promisify } from 'node:util';
|
|
17
|
+
import { createSpinner, CH } from '../utils/logger.js';
|
|
18
|
+
import { describeUpstreamStatus, isServerRuntime, propagateError } from '../utils/api.js';
|
|
58
19
|
// Hyper Loop / Legion runs on the Vigthoria backend only. Local user installs
|
|
59
20
|
// must never even attempt these endpoints, because fetch errors include the
|
|
60
21
|
// URL we tried (would leak internal infra to the user's terminal).
|
|
@@ -70,15 +31,15 @@ function buildServerHyperloopUrls() {
|
|
|
70
31
|
`http://${internalHost}:${port}${apiPath}`,
|
|
71
32
|
];
|
|
72
33
|
}
|
|
73
|
-
const HYPERLOOP_URLS =
|
|
34
|
+
const HYPERLOOP_URLS = isServerRuntime()
|
|
74
35
|
? buildServerHyperloopUrls()
|
|
75
36
|
: (process.env.VIGTHORIA_HYPERLOOP_URL ? [process.env.VIGTHORIA_HYPERLOOP_URL] : []);
|
|
76
37
|
const CORTEX_WARN_BUDGET_USD = 3.5;
|
|
77
38
|
const CORTEX_HARD_BUDGET_USD = 5.0;
|
|
78
39
|
const CORTEX_MAX_ROUNDS = 2;
|
|
79
40
|
const CORTEX_PLATFORM_FEE_PCT = 10;
|
|
80
|
-
const execAsync =
|
|
81
|
-
class LegionCommand {
|
|
41
|
+
const execAsync = promisify(execCallback);
|
|
42
|
+
export class LegionCommand {
|
|
82
43
|
config;
|
|
83
44
|
logger;
|
|
84
45
|
constructor(config, logger) {
|
|
@@ -95,7 +56,7 @@ class LegionCommand {
|
|
|
95
56
|
if (envUrl) {
|
|
96
57
|
urls.add(envUrl);
|
|
97
58
|
}
|
|
98
|
-
if (
|
|
59
|
+
if (isServerRuntime()) {
|
|
99
60
|
for (const internal of buildServerHyperloopUrls()) {
|
|
100
61
|
urls.add(internal.replace(/\/$/, ''));
|
|
101
62
|
}
|
|
@@ -120,7 +81,7 @@ class LegionCommand {
|
|
|
120
81
|
return await response.json();
|
|
121
82
|
}
|
|
122
83
|
catch (err) {
|
|
123
|
-
|
|
84
|
+
propagateError({
|
|
124
85
|
...((err && typeof err === 'object') ? err : { message: String(err) }),
|
|
125
86
|
message: `${context} returned invalid JSON: ${err?.message || String(err)}`,
|
|
126
87
|
statusCode: response.status,
|
|
@@ -138,7 +99,7 @@ class LegionCommand {
|
|
|
138
99
|
}
|
|
139
100
|
propagateLegionApiError(context, endpoint, err) {
|
|
140
101
|
const original = err && typeof err === 'object' ? err : { message: String(err) };
|
|
141
|
-
|
|
102
|
+
propagateError({
|
|
142
103
|
...original,
|
|
143
104
|
commandName: 'legion',
|
|
144
105
|
endpoint: original.endpoint || original?.config?.url || original?.details?.endpoint || endpoint || context,
|
|
@@ -164,27 +125,27 @@ class LegionCommand {
|
|
|
164
125
|
return;
|
|
165
126
|
}
|
|
166
127
|
if (!request) {
|
|
167
|
-
console.log(
|
|
168
|
-
console.log(
|
|
169
|
-
console.log(
|
|
170
|
-
console.log(
|
|
128
|
+
console.log(chalk.yellow('Usage: vigthoria legion "<task description>"'));
|
|
129
|
+
console.log(chalk.gray(' --workers List available Legion workers'));
|
|
130
|
+
console.log(chalk.gray(' --status Show Legion infrastructure status'));
|
|
131
|
+
console.log(chalk.gray(' --cortex Vigthoria Cortex: maximum intelligence execution'));
|
|
171
132
|
return;
|
|
172
133
|
}
|
|
173
134
|
await this.planAndExecute(request, options);
|
|
174
135
|
}
|
|
175
136
|
async runCortex(request, options) {
|
|
176
137
|
if (!request) {
|
|
177
|
-
console.log(
|
|
178
|
-
console.log(
|
|
179
|
-
console.log(
|
|
180
|
-
console.log(
|
|
181
|
-
console.log(
|
|
182
|
-
console.log(
|
|
183
|
-
console.log(
|
|
184
|
-
console.log(
|
|
185
|
-
console.log(
|
|
186
|
-
console.log(
|
|
187
|
-
console.log(
|
|
138
|
+
console.log(chalk.yellow('Usage: vigthoria legion --cortex "<task description>"'));
|
|
139
|
+
console.log(chalk.gray(' --plan-only Run calculator only (no execution)'));
|
|
140
|
+
console.log(chalk.gray(' --force-budget Allow execution above hard safe-stop budget'));
|
|
141
|
+
console.log(chalk.gray(' --ignore-preflight Bypass mandatory preflight checks (no warranty)'));
|
|
142
|
+
console.log(chalk.gray(' --speed Speed mode: optional role skip on convergence'));
|
|
143
|
+
console.log(chalk.gray(' --tier heavy|lite Model tier: heavy=strongest LLMs (default), lite=efficient+affordable'));
|
|
144
|
+
console.log(chalk.gray(' --repro-cmd <cmd> Run a local reproducibility command before spend'));
|
|
145
|
+
console.log(chalk.gray(' --expect-repro-fail Require repro command to fail before execution'));
|
|
146
|
+
console.log(chalk.gray(' --approve Skip initial confirmation prompt and execute'));
|
|
147
|
+
console.log(chalk.gray(' --auto-charge Attempt direct VigCoin top-up when balance is low'));
|
|
148
|
+
console.log(chalk.gray(' --timeout <sec> Abort remote execution if no result within timeout (default: 120)'));
|
|
188
149
|
return;
|
|
189
150
|
}
|
|
190
151
|
const workspace = options.project || process.cwd();
|
|
@@ -192,38 +153,38 @@ class LegionCommand {
|
|
|
192
153
|
if (!options.ignorePreflight) {
|
|
193
154
|
const preflight = await this.runMandatoryPreflight(workspace, options.reproCmd, options.expectReproFail === true);
|
|
194
155
|
if (!preflight.ok) {
|
|
195
|
-
console.log(
|
|
196
|
-
console.log(
|
|
197
|
-
console.log(
|
|
156
|
+
console.log(chalk.red('Cortex preflight failed.'));
|
|
157
|
+
console.log(chalk.red(` ${preflight.reason}`));
|
|
158
|
+
console.log(chalk.yellow('Execution halted before any cloud spend. Use --ignore-preflight to override (no warranty).'));
|
|
198
159
|
return;
|
|
199
160
|
}
|
|
200
|
-
console.log(
|
|
161
|
+
console.log(chalk.green('Preflight passed.'));
|
|
201
162
|
}
|
|
202
163
|
else {
|
|
203
|
-
console.log(
|
|
164
|
+
console.log(chalk.yellow('Preflight bypassed by --ignore-preflight (no warranty).'));
|
|
204
165
|
}
|
|
205
166
|
const tier = (options.tier === 'lite') ? 'lite' : 'heavy';
|
|
206
167
|
const selectedModels = this.resolveModelProfiles(options.models, tier);
|
|
207
168
|
const quote = this.buildRoleQuote(scan, selectedModels, tier);
|
|
208
169
|
const billingQuote = this.buildBillingQuote(quote, tier);
|
|
209
170
|
if (billingQuote.retryAdjustedUsd > CORTEX_WARN_BUDGET_USD) {
|
|
210
|
-
console.log(
|
|
171
|
+
console.log(chalk.yellow(`Estimated spend exceeds warning threshold ($${CORTEX_WARN_BUDGET_USD.toFixed(2)}).`));
|
|
211
172
|
}
|
|
212
173
|
let billingGate = await this.evaluateBillingGate(billingQuote);
|
|
213
174
|
this.printCortexQuote(workspace, scan, quote, billingQuote, billingGate);
|
|
214
175
|
if (billingQuote.retryAdjustedUsd > CORTEX_HARD_BUDGET_USD && !options.forceBudget && !billingGate.masterAdminFree) {
|
|
215
|
-
console.log(
|
|
216
|
-
console.log(
|
|
176
|
+
console.log(chalk.red(`Estimated spend exceeds hard budget ceiling (${CORTEX_HARD_BUDGET_USD.toFixed(2)}).`));
|
|
177
|
+
console.log(chalk.yellow('Re-run with --force-budget to continue.'));
|
|
217
178
|
return;
|
|
218
179
|
}
|
|
219
180
|
if (options.planOnly) {
|
|
220
|
-
console.log(
|
|
181
|
+
console.log(chalk.green('Cortex estimator complete (plan-only).'));
|
|
221
182
|
return;
|
|
222
183
|
}
|
|
223
184
|
const autoApprove = options.approve === true && options.noApprove !== true;
|
|
224
185
|
const approved = autoApprove ? true : await this.confirmExecution();
|
|
225
186
|
if (!approved) {
|
|
226
|
-
console.log(
|
|
187
|
+
console.log(chalk.yellow('Cortex cancelled by user.'));
|
|
227
188
|
return;
|
|
228
189
|
}
|
|
229
190
|
let round = 1;
|
|
@@ -234,19 +195,19 @@ class LegionCommand {
|
|
|
234
195
|
if (!billingGate.canProceed) {
|
|
235
196
|
const resolved = await this.resolveBillingInsufficientFunds(currentQuote, billingGate, options);
|
|
236
197
|
if (!resolved) {
|
|
237
|
-
console.log(
|
|
198
|
+
console.log(chalk.yellow('Cortex cancelled due to insufficient VigCoin balance.'));
|
|
238
199
|
return;
|
|
239
200
|
}
|
|
240
201
|
billingGate = await this.evaluateBillingGate(currentQuote);
|
|
241
202
|
if (!billingGate.canProceed) {
|
|
242
203
|
this.printBillingGateSummary(currentQuote, billingGate);
|
|
243
|
-
console.log(
|
|
204
|
+
console.log(chalk.red('Billing gate still blocked after charge attempt.'));
|
|
244
205
|
return;
|
|
245
206
|
}
|
|
246
207
|
}
|
|
247
208
|
const charged = await this.collectExecutionCharge(currentQuote, billingGate);
|
|
248
209
|
if (!charged) {
|
|
249
|
-
console.log(
|
|
210
|
+
console.log(chalk.yellow('Cortex cancelled because wallet charge was not completed.'));
|
|
250
211
|
return;
|
|
251
212
|
}
|
|
252
213
|
cumulativeUsd += currentQuote.finalUsd;
|
|
@@ -273,27 +234,27 @@ class LegionCommand {
|
|
|
273
234
|
}
|
|
274
235
|
const failedRole = String(execution.failedStepId || '').toLowerCase();
|
|
275
236
|
if (this.isCriticalRoleFailure(failedRole)) {
|
|
276
|
-
console.log(
|
|
237
|
+
console.log(chalk.red(`Fail-fast: critical role '${failedRole || 'unknown'}' failed. Manual correction required.`));
|
|
277
238
|
return;
|
|
278
239
|
}
|
|
279
240
|
if (!this.isOptionalRepairRoleFailure(failedRole)) {
|
|
280
|
-
console.log(
|
|
241
|
+
console.log(chalk.red('Execution failed and is not eligible for automatic optional-role repair.'));
|
|
281
242
|
return;
|
|
282
243
|
}
|
|
283
244
|
if (round >= CORTEX_MAX_ROUNDS) {
|
|
284
|
-
console.log(
|
|
245
|
+
console.log(chalk.red('Optional-role auto-repair budget exhausted.'));
|
|
285
246
|
return;
|
|
286
247
|
}
|
|
287
248
|
const nextQuote = this.estimateAdditionalLoopQuote(currentQuote, execution);
|
|
288
249
|
const projectedTotal = cumulativeUsd + nextQuote.retryAdjustedUsd;
|
|
289
250
|
if (projectedTotal > CORTEX_HARD_BUDGET_USD && !options.forceBudget) {
|
|
290
|
-
console.log(
|
|
291
|
-
console.log(
|
|
251
|
+
console.log(chalk.red(`Additional loop would exceed hard budget ceiling ($${CORTEX_HARD_BUDGET_USD.toFixed(2)}).`));
|
|
252
|
+
console.log(chalk.yellow('Re-run with --force-budget to allow paid continuation.'));
|
|
292
253
|
return;
|
|
293
254
|
}
|
|
294
255
|
const continueApproved = await this.confirmAdditionalLoopCharge(nextQuote, round + 1, execution);
|
|
295
256
|
if (!continueApproved) {
|
|
296
|
-
console.log(
|
|
257
|
+
console.log(chalk.yellow('Termination: user declined additional budget for next round.'));
|
|
297
258
|
return;
|
|
298
259
|
}
|
|
299
260
|
currentQuote = nextQuote;
|
|
@@ -336,10 +297,10 @@ class LegionCommand {
|
|
|
336
297
|
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
337
298
|
try {
|
|
338
299
|
console.log();
|
|
339
|
-
console.log(
|
|
340
|
-
console.log(
|
|
341
|
-
console.log(
|
|
342
|
-
console.log(
|
|
300
|
+
console.log(chalk.yellow('Budget depleted for current round. Additional paid loop required.'));
|
|
301
|
+
console.log(chalk.gray(` Next round: ${nextRound}`));
|
|
302
|
+
console.log(chalk.gray(` Failed step: ${execution.failedStepId || 'unknown'} (${execution.failedWorker || 'unknown'})`));
|
|
303
|
+
console.log(chalk.gray(` Additional estimate: $${nextQuote.finalUsd.toFixed(4)} / ${nextQuote.vigcoinRequired.toFixed(3)} VIG`));
|
|
343
304
|
const answer = (await rl.question('Confirm additional VigCoin deduction and continue? (y/N): ')).trim().toLowerCase();
|
|
344
305
|
return answer === 'y' || answer === 'yes';
|
|
345
306
|
}
|
|
@@ -1001,42 +962,42 @@ class LegionCommand {
|
|
|
1001
962
|
if (gate.masterAdminFree) {
|
|
1002
963
|
return true;
|
|
1003
964
|
}
|
|
1004
|
-
const spinner =
|
|
965
|
+
const spinner = createSpinner('Charging VigCoin wallet for Cortex execution...').start();
|
|
1005
966
|
const result = await this.attemptDirectCharge(billingQuote.vigcoinRequired);
|
|
1006
967
|
spinner.stop();
|
|
1007
968
|
if (!result.ok) {
|
|
1008
|
-
console.log(
|
|
1009
|
-
console.log(
|
|
969
|
+
console.log(chalk.red(result.note || 'Wallet charge failed.'));
|
|
970
|
+
console.log(chalk.yellow(`Complete purchase first: ${result.checkoutUrl || `${this.getBillingBaseUrl()}/music/store#vigcoins`}`));
|
|
1010
971
|
return false;
|
|
1011
972
|
}
|
|
1012
|
-
console.log(
|
|
973
|
+
console.log(chalk.green('Wallet charged for Cortex execution.'));
|
|
1013
974
|
return true;
|
|
1014
975
|
}
|
|
1015
976
|
async resolveBillingInsufficientFunds(billingQuote, gate, options) {
|
|
1016
977
|
this.printBillingGateSummary(billingQuote, gate);
|
|
1017
978
|
if (!gate.wallet.available) {
|
|
1018
|
-
console.log(
|
|
979
|
+
console.log(chalk.red('Unable to verify wallet balance from server. Execution is blocked.'));
|
|
1019
980
|
if (gate.wallet.purchaseUrl) {
|
|
1020
|
-
console.log(
|
|
981
|
+
console.log(chalk.gray(`Open billing portal: ${gate.wallet.purchaseUrl}`));
|
|
1021
982
|
}
|
|
1022
983
|
return false;
|
|
1023
984
|
}
|
|
1024
985
|
if (options.autoCharge) {
|
|
1025
|
-
const spinner =
|
|
986
|
+
const spinner = createSpinner('Attempting direct wallet charge...').start();
|
|
1026
987
|
const result = await this.attemptDirectCharge(billingQuote.vigcoinRequired - (gate.wallet.vigcoinBalance || 0));
|
|
1027
988
|
spinner.stop();
|
|
1028
989
|
if (result.ok) {
|
|
1029
|
-
console.log(
|
|
990
|
+
console.log(chalk.green('Direct charge succeeded. Re-checking wallet balance...'));
|
|
1030
991
|
return true;
|
|
1031
992
|
}
|
|
1032
|
-
console.log(
|
|
1033
|
-
console.log(
|
|
993
|
+
console.log(chalk.yellow(result.note || 'Direct charge did not complete.'));
|
|
994
|
+
console.log(chalk.yellow(`Complete purchase first: ${result.checkoutUrl || gate.wallet.purchaseUrl || `${this.getBillingBaseUrl()}/billing`}`));
|
|
1034
995
|
return false;
|
|
1035
996
|
}
|
|
1036
997
|
if (!process.stdin.isTTY || !process.stdout.isTTY) {
|
|
1037
|
-
console.log(
|
|
998
|
+
console.log(chalk.yellow('Low balance detected in non-interactive mode. Re-run with --auto-charge or top up first.'));
|
|
1038
999
|
if (gate.wallet.purchaseUrl) {
|
|
1039
|
-
console.log(
|
|
1000
|
+
console.log(chalk.gray(`Billing portal: ${gate.wallet.purchaseUrl}`));
|
|
1040
1001
|
}
|
|
1041
1002
|
return false;
|
|
1042
1003
|
}
|
|
@@ -1044,19 +1005,19 @@ class LegionCommand {
|
|
|
1044
1005
|
try {
|
|
1045
1006
|
const answer = (await rl.question('VigCoin low. Choose action: [c]harge now, [p]urchase first, [n] cancel: ')).trim().toLowerCase();
|
|
1046
1007
|
if (answer === 'c' || answer === 'charge') {
|
|
1047
|
-
const spinner =
|
|
1008
|
+
const spinner = createSpinner('Attempting direct wallet charge...').start();
|
|
1048
1009
|
const result = await this.attemptDirectCharge(billingQuote.vigcoinRequired - (gate.wallet.vigcoinBalance || 0));
|
|
1049
1010
|
spinner.stop();
|
|
1050
1011
|
if (result.ok) {
|
|
1051
|
-
console.log(
|
|
1012
|
+
console.log(chalk.green('Direct charge succeeded. Re-checking wallet balance...'));
|
|
1052
1013
|
return true;
|
|
1053
1014
|
}
|
|
1054
|
-
console.log(
|
|
1055
|
-
console.log(
|
|
1015
|
+
console.log(chalk.yellow(result.note || 'Direct charge did not complete.'));
|
|
1016
|
+
console.log(chalk.yellow(`Complete purchase first: ${result.checkoutUrl || gate.wallet.purchaseUrl || `${this.getBillingBaseUrl()}/billing`}`));
|
|
1056
1017
|
return false;
|
|
1057
1018
|
}
|
|
1058
1019
|
if (answer === 'p' || answer === 'purchase') {
|
|
1059
|
-
console.log(
|
|
1020
|
+
console.log(chalk.yellow(`Purchase VigCoin first: ${gate.wallet.purchaseUrl || `${this.getBillingBaseUrl()}/billing`}`));
|
|
1060
1021
|
return false;
|
|
1061
1022
|
}
|
|
1062
1023
|
return false;
|
|
@@ -1066,68 +1027,68 @@ class LegionCommand {
|
|
|
1066
1027
|
}
|
|
1067
1028
|
}
|
|
1068
1029
|
printBillingGateSummary(billingQuote, gate) {
|
|
1069
|
-
console.log(
|
|
1070
|
-
console.log(
|
|
1030
|
+
console.log(chalk.white(' Billing gate:'));
|
|
1031
|
+
console.log(chalk.gray(` Plan: ${gate.plan}`));
|
|
1071
1032
|
if (gate.masterAdminFree) {
|
|
1072
|
-
console.log(
|
|
1033
|
+
console.log(chalk.green(' Free tier override applied (Master Admin).'));
|
|
1073
1034
|
return;
|
|
1074
1035
|
}
|
|
1075
|
-
console.log(
|
|
1076
|
-
console.log(
|
|
1077
|
-
console.log(
|
|
1078
|
-
console.log(
|
|
1036
|
+
console.log(chalk.gray(` Estimated total (USD): $${billingQuote.retryAdjustedUsd.toFixed(4)}`) + chalk.gray(' (retry-adjusted expected)'));
|
|
1037
|
+
console.log(chalk.gray(` Platform fee: +${billingQuote.platformFeePct.toFixed(0)}% (already included in all estimates)`));
|
|
1038
|
+
console.log(chalk.gray(` VigCoin rate: 1 VIG = $${billingQuote.vigcoinRateUsd.toFixed(4)}`));
|
|
1039
|
+
console.log(chalk.gray(` VigCoin required: ${billingQuote.vigcoinRequired.toFixed(3)}`));
|
|
1079
1040
|
if (gate.wallet.vigcoinBalance !== null) {
|
|
1080
|
-
const color = gate.wallet.vigcoinBalance >= billingQuote.vigcoinRequired ?
|
|
1081
|
-
console.log(
|
|
1041
|
+
const color = gate.wallet.vigcoinBalance >= billingQuote.vigcoinRequired ? chalk.green : chalk.red;
|
|
1042
|
+
console.log(chalk.gray(' Wallet balance: ') + color(gate.wallet.vigcoinBalance.toFixed(3)) + (gate.wallet.source ? chalk.gray(` (source: ${gate.wallet.source})`) : ''));
|
|
1082
1043
|
}
|
|
1083
1044
|
else {
|
|
1084
|
-
console.log(
|
|
1045
|
+
console.log(chalk.red(` Wallet balance: unavailable${gate.wallet.error ? ` (${gate.wallet.error})` : ''}`));
|
|
1085
1046
|
}
|
|
1086
1047
|
if (gate.wallet.purchaseUrl) {
|
|
1087
|
-
console.log(
|
|
1048
|
+
console.log(chalk.gray(` Purchase URL: ${gate.wallet.purchaseUrl}`));
|
|
1088
1049
|
}
|
|
1089
1050
|
}
|
|
1090
1051
|
printCortexQuote(workspace, scan, quote, billingQuote, gate) {
|
|
1091
1052
|
const tierLabel = billingQuote.tier === 'lite'
|
|
1092
|
-
?
|
|
1093
|
-
:
|
|
1053
|
+
? chalk.cyan('LITE') + chalk.gray(' — efficient (claude-sonnet/haiku, o4-mini, gemini-flash, deepseek-v3)')
|
|
1054
|
+
: chalk.magenta('HEAVY') + chalk.gray(' — strongest LLMs (gpt-5.5, opus-4.7, o3, gemini-2.5-pro)');
|
|
1094
1055
|
console.log();
|
|
1095
|
-
console.log(
|
|
1056
|
+
console.log(chalk.bold.white(` ${CH.hLine.repeat(3)} Vigthoria Cortex Estimator ${CH.hLine.repeat(31)}`));
|
|
1096
1057
|
console.log();
|
|
1097
|
-
console.log(
|
|
1098
|
-
console.log(
|
|
1099
|
-
console.log(
|
|
1100
|
-
console.log(
|
|
1101
|
-
console.log(
|
|
1058
|
+
console.log(chalk.gray(' Workspace: ') + chalk.white(workspace));
|
|
1059
|
+
console.log(chalk.gray(' Tier: ') + tierLabel);
|
|
1060
|
+
console.log(chalk.gray(' Files scanned: ') + chalk.white(String(scan.files)));
|
|
1061
|
+
console.log(chalk.gray(' Lines scanned: ') + chalk.white(String(scan.lines)));
|
|
1062
|
+
console.log(chalk.gray(' Dependency edges: ') + chalk.white(String(scan.importEdges)));
|
|
1102
1063
|
if (scan.topFiles.length > 0) {
|
|
1103
1064
|
console.log();
|
|
1104
|
-
console.log(
|
|
1065
|
+
console.log(chalk.white(' Top context files:'));
|
|
1105
1066
|
for (const f of scan.topFiles) {
|
|
1106
|
-
console.log(
|
|
1067
|
+
console.log(chalk.gray(` ${CH.bullet} ${f.file} (${f.lines} lines, ${f.imports} imports)`));
|
|
1107
1068
|
}
|
|
1108
1069
|
}
|
|
1109
1070
|
console.log();
|
|
1110
|
-
console.log(
|
|
1071
|
+
console.log(chalk.white(' Role assignment and estimated cost:'));
|
|
1111
1072
|
for (const row of quote) {
|
|
1112
1073
|
const publicModelLabel = row.requestedModel || row.model.replace(/^openrouter:/i, '').split('/').pop() || 'managed-model';
|
|
1113
1074
|
const roleEstWithFee = row.estCostUsd * (1 + (billingQuote.platformFeePct / 100));
|
|
1114
|
-
console.log(
|
|
1075
|
+
console.log(chalk.gray(` ${CH.bullet} ${row.role.padEnd(11)} ${publicModelLabel} $${roleEstWithFee.toFixed(4)}`));
|
|
1115
1076
|
}
|
|
1116
1077
|
console.log();
|
|
1117
|
-
console.log(
|
|
1118
|
-
console.log(
|
|
1119
|
-
console.log(
|
|
1120
|
-
console.log(
|
|
1121
|
-
console.log(
|
|
1122
|
-
console.log(
|
|
1123
|
-
console.log(
|
|
1078
|
+
console.log(chalk.yellow(` Cost range (single-pass best case): $${billingQuote.rangeMinUsd.toFixed(4)}`));
|
|
1079
|
+
console.log(chalk.yellow(` Cost range (expected with retries): $${billingQuote.retryAdjustedUsd.toFixed(4)}`) + chalk.gray(' ← use this for budget planning'));
|
|
1080
|
+
console.log(chalk.yellow(` Cost range (worst case, all retries): $${billingQuote.rangeMaxUsd.toFixed(4)}`));
|
|
1081
|
+
console.log(chalk.gray(' Retry model: 45% chance per critical role triggers quality-gate (+40% iterations per retry).'));
|
|
1082
|
+
console.log(chalk.gray(' A mid-run checkpoint will appear when 70% of the expected estimate is consumed.'));
|
|
1083
|
+
console.log(chalk.gray(' Flow: Estimate -> Isolation -> Parallel Attack -> Synthesis'));
|
|
1084
|
+
console.log(chalk.gray(` All displayed costs include platform fee (+${billingQuote.platformFeePct.toFixed(0)}%).`));
|
|
1124
1085
|
console.log();
|
|
1125
1086
|
this.printBillingGateSummary(billingQuote, gate);
|
|
1126
1087
|
console.log();
|
|
1127
1088
|
}
|
|
1128
1089
|
async confirmExecution() {
|
|
1129
1090
|
if (!process.stdin.isTTY || !process.stdout.isTTY) {
|
|
1130
|
-
console.log(
|
|
1091
|
+
console.log(chalk.yellow('Non-interactive terminal detected. Re-run with --approve to continue execution.'));
|
|
1131
1092
|
return false;
|
|
1132
1093
|
}
|
|
1133
1094
|
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
@@ -1186,7 +1147,7 @@ class LegionCommand {
|
|
|
1186
1147
|
headers['Cookie'] = `vigthoria-auth-token=${token}`;
|
|
1187
1148
|
}
|
|
1188
1149
|
}
|
|
1189
|
-
const spinner =
|
|
1150
|
+
const spinner = createSpinner('Connecting to Legion SSE stream...').start();
|
|
1190
1151
|
const startTime = Date.now();
|
|
1191
1152
|
let response;
|
|
1192
1153
|
try {
|
|
@@ -1204,7 +1165,7 @@ class LegionCommand {
|
|
|
1204
1165
|
if (!response.ok) {
|
|
1205
1166
|
spinner.stop();
|
|
1206
1167
|
const errBody = await response.text().catch(() => '');
|
|
1207
|
-
this.logger.error(`Legion stream ${response.status}: ${
|
|
1168
|
+
this.logger.error(`Legion stream ${response.status}: ${describeUpstreamStatus(response.status)} — ${errBody.slice(0, 200)}`);
|
|
1208
1169
|
return { status: 'failed', plannedSteps: 0, completedSteps: 0 };
|
|
1209
1170
|
}
|
|
1210
1171
|
if (!response.body) {
|
|
@@ -1214,7 +1175,7 @@ class LegionCommand {
|
|
|
1214
1175
|
}
|
|
1215
1176
|
spinner.stop();
|
|
1216
1177
|
console.log();
|
|
1217
|
-
console.log(
|
|
1178
|
+
console.log(chalk.bold.white(` ${CH.hLine.repeat(3)} Legion Execution Report ${CH.hLine.repeat(34)}`));
|
|
1218
1179
|
console.log();
|
|
1219
1180
|
const decoder = new TextDecoder();
|
|
1220
1181
|
let buffer = '';
|
|
@@ -1264,18 +1225,18 @@ class LegionCommand {
|
|
|
1264
1225
|
switch (evt.event) {
|
|
1265
1226
|
case 'plan':
|
|
1266
1227
|
stepsTotal = evt.steps_total || 0;
|
|
1267
|
-
console.log(
|
|
1228
|
+
console.log(chalk.gray(` Planned workers: ${stepsTotal} steps queued`));
|
|
1268
1229
|
console.log();
|
|
1269
1230
|
break;
|
|
1270
1231
|
case 'batch_start':
|
|
1271
|
-
console.log(
|
|
1232
|
+
console.log(chalk.gray(` ▶ Running: ${evt.workers.join(', ')} (${evt.steps_done}/${evt.steps_total})`));
|
|
1272
1233
|
break;
|
|
1273
1234
|
case 'step_complete': {
|
|
1274
1235
|
stepsDone = Number(evt.steps_done) || 0;
|
|
1275
|
-
const icon = evt.status === 'completed' ?
|
|
1236
|
+
const icon = evt.status === 'completed' ? chalk.green(CH.success) : chalk.red(CH.error);
|
|
1276
1237
|
const stepSummaryRaw = String(evt.summary || '');
|
|
1277
|
-
const summarySnip = stepSummaryRaw ?
|
|
1278
|
-
console.log(` ${icon} ${
|
|
1238
|
+
const summarySnip = stepSummaryRaw ? chalk.gray(` — ${stepSummaryRaw.slice(0, 120)}`) : '';
|
|
1239
|
+
console.log(` ${icon} ${chalk.white(String(evt.step_id))} ${chalk.gray('[' + evt.worker + ']')}${summarySnip}`);
|
|
1279
1240
|
if (evt.status !== 'completed' && !failedStepId) {
|
|
1280
1241
|
failedStepId = String(evt.step_id || '');
|
|
1281
1242
|
failedWorker = String(evt.worker || '');
|
|
@@ -1298,18 +1259,18 @@ class LegionCommand {
|
|
|
1298
1259
|
.filter((q) => remainingRoles.includes(q.role))
|
|
1299
1260
|
.reduce((s, q) => s + (q.estCostUsd * (1 + CORTEX_PLATFORM_FEE_PCT / 100)), 0);
|
|
1300
1261
|
console.log();
|
|
1301
|
-
console.log(
|
|
1302
|
-
console.log(
|
|
1303
|
-
console.log(
|
|
1262
|
+
console.log(chalk.bold.yellow(' ━━━ Mid-Run Budget Checkpoint ━━━'));
|
|
1263
|
+
console.log(chalk.gray(` Consumed so far (estimated): $${accumulatedEstUsd.toFixed(4)}`));
|
|
1264
|
+
console.log(chalk.gray(` Estimated remaining: $${remainingEstUsd.toFixed(4)}`));
|
|
1304
1265
|
console.log();
|
|
1305
|
-
console.log(
|
|
1266
|
+
console.log(chalk.white(' Roles completed:'));
|
|
1306
1267
|
for (const c of completedRoleSummaries) {
|
|
1307
|
-
const roleIcon = c.status === 'completed' ?
|
|
1268
|
+
const roleIcon = c.status === 'completed' ? chalk.green('✔') : chalk.red('✘');
|
|
1308
1269
|
const roleSumSnip = c.summary ? ` — ${c.summary.slice(0, 100)}` : '';
|
|
1309
|
-
console.log(
|
|
1270
|
+
console.log(chalk.gray(` ${roleIcon} ${c.role.padEnd(11)}${roleSumSnip}`));
|
|
1310
1271
|
}
|
|
1311
1272
|
console.log();
|
|
1312
|
-
console.log(
|
|
1273
|
+
console.log(chalk.white(' Remaining roles: ') + chalk.gray(remainingRoles.join(', ') || 'none'));
|
|
1313
1274
|
console.log();
|
|
1314
1275
|
const checkpointRl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
1315
1276
|
let continueRun = false;
|
|
@@ -1321,14 +1282,14 @@ class LegionCommand {
|
|
|
1321
1282
|
checkpointRl.close();
|
|
1322
1283
|
}
|
|
1323
1284
|
if (!continueRun) {
|
|
1324
|
-
console.log(
|
|
1325
|
-
console.log(
|
|
1285
|
+
console.log(chalk.yellow(' Cortex stopped by user at budget checkpoint.'));
|
|
1286
|
+
console.log(chalk.gray(` State: ${stepsDone} of ${stepsTotal} steps completed.`));
|
|
1326
1287
|
finalStatus = 'failed';
|
|
1327
1288
|
failedStepId = failedStepId || 'user_checkpoint_stop';
|
|
1328
1289
|
// Break out of the for-of lines loop; the outer while(true) will end when reader.read() drains.
|
|
1329
1290
|
break;
|
|
1330
1291
|
}
|
|
1331
|
-
console.log(
|
|
1292
|
+
console.log(chalk.green(' Continuing execution…'));
|
|
1332
1293
|
console.log();
|
|
1333
1294
|
}
|
|
1334
1295
|
break;
|
|
@@ -1350,19 +1311,19 @@ class LegionCommand {
|
|
|
1350
1311
|
if (evt.status === 'completed') {
|
|
1351
1312
|
finalStatus = 'completed';
|
|
1352
1313
|
console.log();
|
|
1353
|
-
console.log(
|
|
1314
|
+
console.log(chalk.green(` ${CH.success} Legion completed successfully`));
|
|
1354
1315
|
}
|
|
1355
1316
|
else if (evt.status === 'failed') {
|
|
1356
1317
|
finalStatus = 'failed';
|
|
1357
1318
|
console.log();
|
|
1358
|
-
console.log(
|
|
1319
|
+
console.log(chalk.red(` ${CH.error} Legion execution failed`));
|
|
1359
1320
|
if (evt.error)
|
|
1360
|
-
console.log(
|
|
1321
|
+
console.log(chalk.red(` Error: ${String(evt.error).slice(0, 300)}`));
|
|
1361
1322
|
}
|
|
1362
1323
|
break;
|
|
1363
1324
|
case 'error':
|
|
1364
1325
|
finalStatus = 'failed';
|
|
1365
|
-
console.log(
|
|
1326
|
+
console.log(chalk.red(` ${CH.error} Stream error: ${String(evt.error).slice(0, 300)}`));
|
|
1366
1327
|
break;
|
|
1367
1328
|
}
|
|
1368
1329
|
}
|
|
@@ -1374,16 +1335,16 @@ class LegionCommand {
|
|
|
1374
1335
|
}
|
|
1375
1336
|
const elapsedSec = ((Date.now() - startTime) / 1000).toFixed(1);
|
|
1376
1337
|
if (stepsTotal > 0 && stepsDone < stepsTotal) {
|
|
1377
|
-
console.log(
|
|
1338
|
+
console.log(chalk.yellow(` ${CH.warn} Legion stream ended after ${stepsDone}/${stepsTotal} steps`));
|
|
1378
1339
|
}
|
|
1379
1340
|
console.log();
|
|
1380
|
-
console.log(
|
|
1341
|
+
console.log(chalk.gray(` Time: ${elapsedSec}s`));
|
|
1381
1342
|
const lastStepResult = finalResult?.final_output;
|
|
1382
1343
|
const summary = String(lastStepResult?.result?.summary || lastStepResult?.summary || '');
|
|
1383
1344
|
if (summary) {
|
|
1384
1345
|
console.log();
|
|
1385
|
-
console.log(
|
|
1386
|
-
console.log(
|
|
1346
|
+
console.log(chalk.white(' Final output:'));
|
|
1347
|
+
console.log(chalk.gray(` ${summary.slice(0, 600)}`));
|
|
1387
1348
|
}
|
|
1388
1349
|
if (cortexExecution) {
|
|
1389
1350
|
const report = this.buildCortexRunReport({
|
|
@@ -1399,8 +1360,8 @@ class LegionCommand {
|
|
|
1399
1360
|
finalSummary: summary,
|
|
1400
1361
|
}, streamEvents);
|
|
1401
1362
|
const files = this.writeCortexSummaryReport(report);
|
|
1402
|
-
console.log(
|
|
1403
|
-
console.log(
|
|
1363
|
+
console.log(chalk.gray(' Cortex summary: ' + files.markdownPath));
|
|
1364
|
+
console.log(chalk.gray(' Cortex report JSON: ' + files.jsonPath));
|
|
1404
1365
|
}
|
|
1405
1366
|
console.log();
|
|
1406
1367
|
return {
|
|
@@ -1486,7 +1447,7 @@ class LegionCommand {
|
|
|
1486
1447
|
return `${context} failed: ${message}${cause}`;
|
|
1487
1448
|
}
|
|
1488
1449
|
async showWorkers() {
|
|
1489
|
-
const spinner =
|
|
1450
|
+
const spinner = createSpinner('Fetching Legion worker catalog...').start();
|
|
1490
1451
|
let lastError = null;
|
|
1491
1452
|
for (const baseUrl of this.getHyperloopUrls()) {
|
|
1492
1453
|
try {
|
|
@@ -1499,34 +1460,34 @@ class LegionCommand {
|
|
|
1499
1460
|
this.logger.warn(this.formatLegionError(`worker catalog error body at ${baseUrl}`, err));
|
|
1500
1461
|
return '';
|
|
1501
1462
|
});
|
|
1502
|
-
lastError = `Legion worker catalog request at ${baseUrl} failed: ${response.status} ${
|
|
1463
|
+
lastError = `Legion worker catalog request at ${baseUrl} failed: ${response.status} ${describeUpstreamStatus(response.status)}${errBody ? ` — ${errBody.slice(0, 200)}` : ''}`;
|
|
1503
1464
|
continue;
|
|
1504
1465
|
}
|
|
1505
1466
|
const data = await this.readJsonResponse(response, `worker catalog request at ${baseUrl}`);
|
|
1506
1467
|
spinner.stop();
|
|
1507
1468
|
console.log();
|
|
1508
|
-
console.log(
|
|
1469
|
+
console.log(chalk.bold.white(` ${CH.hLine.repeat(3)} Legion Worker Catalog ${CH.hLine.repeat(37)}`));
|
|
1509
1470
|
console.log();
|
|
1510
1471
|
const workers = data.workers || data.catalog || data;
|
|
1511
1472
|
if (Array.isArray(workers)) {
|
|
1512
1473
|
for (const w of workers) {
|
|
1513
1474
|
const wObj = w;
|
|
1514
|
-
const statusColor = wObj.status === 'active' ?
|
|
1515
|
-
console.log(` ${statusColor(
|
|
1475
|
+
const statusColor = wObj.status === 'active' ? chalk.green : chalk.yellow;
|
|
1476
|
+
console.log(` ${statusColor(CH.bullet)} ${chalk.white(wObj.name || wObj.worker || 'unknown')} ${chalk.gray(wObj.description || '')}`);
|
|
1516
1477
|
if (wObj.status) {
|
|
1517
|
-
console.log(
|
|
1478
|
+
console.log(chalk.gray(` Status: ${wObj.status}`));
|
|
1518
1479
|
}
|
|
1519
1480
|
}
|
|
1520
1481
|
}
|
|
1521
1482
|
else if (typeof workers === 'object') {
|
|
1522
1483
|
for (const [name, info] of Object.entries(workers)) {
|
|
1523
1484
|
const infoObj = info;
|
|
1524
|
-
const statusColor = infoObj.maturity === 'active' ?
|
|
1525
|
-
console.log(` ${statusColor(
|
|
1485
|
+
const statusColor = infoObj.maturity === 'active' ? chalk.green : chalk.yellow;
|
|
1486
|
+
console.log(` ${statusColor(CH.bullet)} ${chalk.white(name)} ${chalk.gray(infoObj.description || '')}`);
|
|
1526
1487
|
if (infoObj.maturity)
|
|
1527
|
-
console.log(
|
|
1488
|
+
console.log(chalk.gray(` Maturity: ${infoObj.maturity}`));
|
|
1528
1489
|
if (infoObj.domains)
|
|
1529
|
-
console.log(
|
|
1490
|
+
console.log(chalk.gray(` Domains: ${Array.isArray(infoObj.domains) ? infoObj.domains.join(', ') : infoObj.domains}`));
|
|
1530
1491
|
}
|
|
1531
1492
|
}
|
|
1532
1493
|
console.log();
|
|
@@ -1541,7 +1502,7 @@ class LegionCommand {
|
|
|
1541
1502
|
this.logger.error(lastError || 'Could not reach Hyper Loop. Is vigthoria-hyper-loop running?');
|
|
1542
1503
|
}
|
|
1543
1504
|
async showStatus() {
|
|
1544
|
-
const spinner =
|
|
1505
|
+
const spinner = createSpinner('Checking Legion infrastructure...').start();
|
|
1545
1506
|
let lastError = null;
|
|
1546
1507
|
for (const baseUrl of this.getHyperloopUrls()) {
|
|
1547
1508
|
try {
|
|
@@ -1550,25 +1511,25 @@ class LegionCommand {
|
|
|
1550
1511
|
headers: this.getHeaders(),
|
|
1551
1512
|
});
|
|
1552
1513
|
if (!response.ok) {
|
|
1553
|
-
lastError = `Legion status check at ${baseUrl} failed: ${response.status} ${
|
|
1514
|
+
lastError = `Legion status check at ${baseUrl} failed: ${response.status} ${describeUpstreamStatus(response.status)}`;
|
|
1554
1515
|
continue;
|
|
1555
1516
|
}
|
|
1556
1517
|
const data = await this.readJsonResponse(response, `status check at ${baseUrl}`);
|
|
1557
1518
|
spinner.stop();
|
|
1558
1519
|
console.log();
|
|
1559
|
-
console.log(
|
|
1520
|
+
console.log(chalk.bold.white(` ${CH.hLine.repeat(3)} Legion Infrastructure ${CH.hLine.repeat(37)}`));
|
|
1560
1521
|
console.log();
|
|
1561
|
-
console.log(
|
|
1522
|
+
console.log(chalk.gray(` Hyper Loop: `) + chalk.green('online'));
|
|
1562
1523
|
if (data.workers || data.active_workers) {
|
|
1563
1524
|
const count = data.workers || data.active_workers;
|
|
1564
|
-
console.log(
|
|
1525
|
+
console.log(chalk.gray(` Active workers: `) + chalk.white(String(typeof count === 'number' ? count : Object.keys(count).length)));
|
|
1565
1526
|
}
|
|
1566
1527
|
if (data.remotes || data.infrastructure) {
|
|
1567
1528
|
const remotes = data.remotes || data.infrastructure;
|
|
1568
1529
|
if (typeof remotes === 'object') {
|
|
1569
1530
|
for (const [name, status] of Object.entries(remotes)) {
|
|
1570
|
-
const icon = status?.reachable ?
|
|
1571
|
-
console.log(` ${icon} ${
|
|
1531
|
+
const icon = status?.reachable ? chalk.green(CH.success) : chalk.red(CH.error);
|
|
1532
|
+
console.log(` ${icon} ${chalk.white(name)}`);
|
|
1572
1533
|
}
|
|
1573
1534
|
}
|
|
1574
1535
|
}
|
|
@@ -1582,11 +1543,10 @@ class LegionCommand {
|
|
|
1582
1543
|
}
|
|
1583
1544
|
spinner.stop();
|
|
1584
1545
|
console.log();
|
|
1585
|
-
console.log(
|
|
1546
|
+
console.log(chalk.gray(' Hyper Loop: ') + chalk.red('offline'));
|
|
1586
1547
|
if (lastError) {
|
|
1587
1548
|
this.logger.error(lastError);
|
|
1588
1549
|
}
|
|
1589
1550
|
console.log();
|
|
1590
1551
|
}
|
|
1591
1552
|
}
|
|
1592
|
-
exports.LegionCommand = LegionCommand;
|