@hoox-sh/hoox-cli 0.11.1 → 0.11.2
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 +1 -1
- package/dist/index.js +143 -38
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -455,7 +455,7 @@ The CI pipeline runs in this order:
|
|
|
455
455
|
|
|
456
456
|
1. `bun run lint` — ESLint check
|
|
457
457
|
2. `bun run typecheck` — TypeScript check (`tsc --noEmit`)
|
|
458
|
-
3. `bun test packages/cli --coverage` — Run tests with coverage (80%
|
|
458
|
+
3. `bun test packages/cli --coverage` — Run tests with coverage (~80%+ overall; `src/` ~95%)
|
|
459
459
|
4. `bun run build` — TypeScript build check
|
|
460
460
|
|
|
461
461
|
## Project Structure
|
package/dist/index.js
CHANGED
|
@@ -14719,6 +14719,7 @@ var init_types = __esm(() => {
|
|
|
14719
14719
|
price: exports_external.number().positive().finite().optional(),
|
|
14720
14720
|
leverage: exports_external.number().int().positive().max(125).optional(),
|
|
14721
14721
|
test: exports_external.boolean().optional(),
|
|
14722
|
+
idempotencyKey: exports_external.string().min(1).max(512).optional(),
|
|
14722
14723
|
queuedAt: exports_external.string().min(1).max(64)
|
|
14723
14724
|
}).strict();
|
|
14724
14725
|
TradeSignalSchema = exports_external.object({
|
|
@@ -14753,7 +14754,7 @@ var init_types = __esm(() => {
|
|
|
14753
14754
|
});
|
|
14754
14755
|
|
|
14755
14756
|
// ../shared/src/kvKeys.ts
|
|
14756
|
-
var KV_TRADE_DEFAULT_LEVERAGE = "trade:default_leverage", KV_TRADE_MAX_POSITION_SIZE = "trade:max_position_size", KV_TRADE_MAX_DAILY_DRAWDOWN_PERCENT = "trade:max_daily_drawdown_percent", KV_TRADE_TRAILING_STOP_PERCENT = "trade:trailing_stop_percent", KV_TRADE_KILL_SWITCH = "trade:kill_switch", KV_TRADE_ROUTING = "trade:routing", KV_BOT_ENABLED = "bot:enabled", KV_BOT_DEFAULT_CHAT_ID = "bot:default_chat_id", KV_BOT_NOTIFY_ON_EXECUTION = "bot:notify_on_execution", KV_BOT_NOTIFY_ON_ERROR = "bot:notify_on_error", KV_WEBHOOK_IP_CHECK_ENABLED = "webhook:tradingview:ip_check_enabled", KV_WEBHOOK_ALLOWED_IPS = "webhook:tradingview:allowed_ips", KV_WEBHOOK_QUEUE_MODE = "webhook:queue_mode", KV_EMAIL_SCAN_SUBJECT = "email:scan_subject", KV_EMAIL_USE_IMAP = "email:use_imap", KV_EMAIL_COIN_PATTERN = "email:coin_pattern", KV_EMAIL_ACTION_PATTERN = "email:action_pattern", KV_EMAIL_QUANTITY_MULTIPLIER = "email:quantity_multiplier", KV_AGENT_CONFIG = "agent:config", KV_AGENT_OPENAI_KEY = "agent:openai_key", KV_AGENT_ANTHROPIC_KEY = "agent:anthropic_key", KV_AGENT_GOOGLE_KEY = "agent:google_key", KV_DASHBOARD_AI_HEALTH_SUMMARY = "dashboard:ai_health_summary", KV_HEALTH_CHECK = "health_check", KV_HOUSEKEEPING_LAST_CHECK = "housekeeping:last_check", QUEUE_MODE_FAILOVER = "queue_failover", QUEUE_MODE_EVERYWHERE = "queue_everywhere", QUEUE_MODE_DISABLED = "queue_disabled", KVKeys;
|
|
14757
|
+
var KV_TRADE_DEFAULT_LEVERAGE = "trade:default_leverage", KV_TRADE_MAX_POSITION_SIZE = "trade:max_position_size", KV_TRADE_MAX_DAILY_DRAWDOWN_PERCENT = "trade:max_daily_drawdown_percent", KV_TRADE_TRAILING_STOP_PERCENT = "trade:trailing_stop_percent", KV_TRADE_KILL_SWITCH = "trade:kill_switch", KV_TRADE_ROUTING = "trade:routing", KV_BOT_ENABLED = "bot:enabled", KV_BOT_DEFAULT_CHAT_ID = "bot:default_chat_id", KV_BOT_NOTIFY_ON_EXECUTION = "bot:notify_on_execution", KV_BOT_NOTIFY_ON_ERROR = "bot:notify_on_error", KV_WEBHOOK_IP_CHECK_ENABLED = "webhook:tradingview:ip_check_enabled", KV_WEBHOOK_ALLOWED_IPS = "webhook:tradingview:allowed_ips", KV_WEBHOOK_QUEUE_MODE = "webhook:queue_mode", KV_EMAIL_SCAN_SUBJECT = "email:scan_subject", KV_EMAIL_USE_IMAP = "email:use_imap", KV_EMAIL_COIN_PATTERN = "email:coin_pattern", KV_EMAIL_ACTION_PATTERN = "email:action_pattern", KV_EMAIL_QUANTITY_MULTIPLIER = "email:quantity_multiplier", KV_AGENT_CONFIG = "agent:config", KV_AGENT_OPENAI_KEY = "agent:openai_key", KV_AGENT_ANTHROPIC_KEY = "agent:anthropic_key", KV_AGENT_GOOGLE_KEY = "agent:google_key", KV_DASHBOARD_AI_HEALTH_SUMMARY = "dashboard:ai_health_summary", KV_GLOBAL_KILL_SWITCH = "global:kill_switch", KV_HEALTH_CHECK = "health_check", KV_HOUSEKEEPING_LAST_CHECK = "housekeeping:last_check", QUEUE_MODE_FAILOVER = "queue_failover", QUEUE_MODE_EVERYWHERE = "queue_everywhere", QUEUE_MODE_DISABLED = "queue_disabled", KVKeys;
|
|
14757
14758
|
var init_kvKeys = __esm(() => {
|
|
14758
14759
|
KVKeys = {
|
|
14759
14760
|
KV_TRADE_DEFAULT_LEVERAGE,
|
|
@@ -14779,6 +14780,7 @@ var init_kvKeys = __esm(() => {
|
|
|
14779
14780
|
KV_AGENT_ANTHROPIC_KEY,
|
|
14780
14781
|
KV_AGENT_GOOGLE_KEY,
|
|
14781
14782
|
KV_DASHBOARD_AI_HEALTH_SUMMARY,
|
|
14783
|
+
KV_GLOBAL_KILL_SWITCH,
|
|
14782
14784
|
KV_HEALTH_CHECK,
|
|
14783
14785
|
KV_HOUSEKEEPING_LAST_CHECK,
|
|
14784
14786
|
QUEUE_MODE_FAILOVER,
|
|
@@ -14787,6 +14789,54 @@ var init_kvKeys = __esm(() => {
|
|
|
14787
14789
|
};
|
|
14788
14790
|
});
|
|
14789
14791
|
|
|
14792
|
+
// ../shared/src/kill-switch.ts
|
|
14793
|
+
function isTruthyKillSwitchFlag(value) {
|
|
14794
|
+
if (value == null)
|
|
14795
|
+
return false;
|
|
14796
|
+
const v = value.trim().toLowerCase();
|
|
14797
|
+
return v === "true" || v === "1" || v === "yes" || v === "on";
|
|
14798
|
+
}
|
|
14799
|
+
async function checkKillSwitch(kv, options) {
|
|
14800
|
+
const onMissingKv = options?.onMissingKv ?? "open";
|
|
14801
|
+
const onReadError = options?.onReadError ?? "closed";
|
|
14802
|
+
if (!kv) {
|
|
14803
|
+
if (onMissingKv === "closed") {
|
|
14804
|
+
return { enabled: true, source: "missing_kv" };
|
|
14805
|
+
}
|
|
14806
|
+
return { enabled: false };
|
|
14807
|
+
}
|
|
14808
|
+
try {
|
|
14809
|
+
const values = await Promise.all(KILL_SWITCH_KEYS.map(async (key) => ({
|
|
14810
|
+
key,
|
|
14811
|
+
value: await kv.get(key)
|
|
14812
|
+
})));
|
|
14813
|
+
for (const { key, value } of values) {
|
|
14814
|
+
if (isTruthyKillSwitchFlag(value)) {
|
|
14815
|
+
return { enabled: true, source: key };
|
|
14816
|
+
}
|
|
14817
|
+
}
|
|
14818
|
+
return { enabled: false };
|
|
14819
|
+
} catch (error51) {
|
|
14820
|
+
const errorStr = String(error51);
|
|
14821
|
+
if (onReadError === "closed") {
|
|
14822
|
+
return { enabled: true, source: "read_error", error: errorStr };
|
|
14823
|
+
}
|
|
14824
|
+
return { enabled: false, error: errorStr };
|
|
14825
|
+
}
|
|
14826
|
+
}
|
|
14827
|
+
async function isTradingPaused(kv, options) {
|
|
14828
|
+
const result = await checkKillSwitch(kv, options);
|
|
14829
|
+
return result.enabled;
|
|
14830
|
+
}
|
|
14831
|
+
var KILL_SWITCH_ACTIVE_PREFIX = "KILL_SWITCH_ACTIVE", KILL_SWITCH_KEYS;
|
|
14832
|
+
var init_kill_switch = __esm(() => {
|
|
14833
|
+
init_kvKeys();
|
|
14834
|
+
KILL_SWITCH_KEYS = [
|
|
14835
|
+
KV_TRADE_KILL_SWITCH,
|
|
14836
|
+
KV_GLOBAL_KILL_SWITCH
|
|
14837
|
+
];
|
|
14838
|
+
});
|
|
14839
|
+
|
|
14790
14840
|
// ../shared/src/errors.ts
|
|
14791
14841
|
function toError(err, fallback = "Unknown error") {
|
|
14792
14842
|
if (err instanceof Error)
|
|
@@ -15908,7 +15958,11 @@ var init_config = __esm(() => {
|
|
|
15908
15958
|
|
|
15909
15959
|
// ../shared/src/operator-transport.ts
|
|
15910
15960
|
function stripTrailingSlashes(url2) {
|
|
15911
|
-
|
|
15961
|
+
let end = url2.length;
|
|
15962
|
+
while (end > 0 && url2.charCodeAt(end - 1) === 47) {
|
|
15963
|
+
end -= 1;
|
|
15964
|
+
}
|
|
15965
|
+
return end === url2.length ? url2 : url2.slice(0, end);
|
|
15912
15966
|
}
|
|
15913
15967
|
function parseTransport(raw) {
|
|
15914
15968
|
if (!raw)
|
|
@@ -15955,7 +16009,7 @@ function hasOperatorClientCredentials(profile) {
|
|
|
15955
16009
|
return Boolean(profile.accessClientId && profile.accessClientSecret);
|
|
15956
16010
|
}
|
|
15957
16011
|
function operatorUrl(profile, path2) {
|
|
15958
|
-
const base = profile.apiBase
|
|
16012
|
+
const base = stripTrailingSlashes(profile.apiBase);
|
|
15959
16013
|
const p = path2.startsWith("/") ? path2 : `/${path2}`;
|
|
15960
16014
|
return `${base}${p}`;
|
|
15961
16015
|
}
|
|
@@ -22006,6 +22060,8 @@ __export(exports_src, {
|
|
|
22006
22060
|
kvManifestFromDashboardManifests: () => kvManifestFromDashboardManifests,
|
|
22007
22061
|
isWithinHooxHome: () => isWithinHooxHome,
|
|
22008
22062
|
isUnixModeGroupOrWorldAccessible: () => isUnixModeGroupOrWorldAccessible,
|
|
22063
|
+
isTruthyKillSwitchFlag: () => isTruthyKillSwitchFlag,
|
|
22064
|
+
isTradingPaused: () => isTradingPaused,
|
|
22009
22065
|
isHooxSetupRoot: () => isHooxSetupRoot,
|
|
22010
22066
|
isDashboardSectionFlatKv: () => isDashboardSectionFlatKv,
|
|
22011
22067
|
isDashboardSectionEditable: () => isDashboardSectionEditable,
|
|
@@ -22064,6 +22120,7 @@ __export(exports_src, {
|
|
|
22064
22120
|
createJsonResponse: () => createJsonResponse,
|
|
22065
22121
|
createErrorResponse: () => createErrorResponse,
|
|
22066
22122
|
createCronHandler: () => createCronHandler,
|
|
22123
|
+
checkKillSwitch: () => checkKillSwitch,
|
|
22067
22124
|
buildOperatorAuthHeaders: () => buildOperatorAuthHeaders,
|
|
22068
22125
|
buildDashboardKvKey: () => buildDashboardKvKey,
|
|
22069
22126
|
authenticatedServiceFetch: () => authenticatedServiceFetch,
|
|
@@ -22090,6 +22147,8 @@ __export(exports_src, {
|
|
|
22090
22147
|
PRESETS: () => PRESETS,
|
|
22091
22148
|
LogLevelColor: () => LogLevelColor,
|
|
22092
22149
|
KVKeys: () => KVKeys,
|
|
22150
|
+
KILL_SWITCH_KEYS: () => KILL_SWITCH_KEYS,
|
|
22151
|
+
KILL_SWITCH_ACTIVE_PREFIX: () => KILL_SWITCH_ACTIVE_PREFIX,
|
|
22093
22152
|
InternalAuthKeyFields: () => InternalAuthKeyFields,
|
|
22094
22153
|
INTEGRATIONS: () => INTEGRATIONS,
|
|
22095
22154
|
HOOX_DIR_MODE: () => HOOX_DIR_MODE,
|
|
@@ -22127,6 +22186,7 @@ var init_src = __esm(() => {
|
|
|
22127
22186
|
init_legal();
|
|
22128
22187
|
init_types();
|
|
22129
22188
|
init_kvKeys();
|
|
22189
|
+
init_kill_switch();
|
|
22130
22190
|
init_errors3();
|
|
22131
22191
|
init_exchanges();
|
|
22132
22192
|
init_kvUtils();
|
|
@@ -29255,18 +29315,20 @@ async function runInitCommand(options, globalOpts, isNonInteractive) {
|
|
|
29255
29315
|
engine = new WizardEngine;
|
|
29256
29316
|
}
|
|
29257
29317
|
const skipRiskWarning = options.acceptRisk;
|
|
29258
|
-
if (
|
|
29259
|
-
|
|
29260
|
-
|
|
29261
|
-
|
|
29262
|
-
|
|
29263
|
-
|
|
29264
|
-
|
|
29265
|
-
|
|
29266
|
-
|
|
29267
|
-
|
|
29268
|
-
|
|
29269
|
-
|
|
29318
|
+
if (engine.getCurrentStep().id === "PREREQUISITES") {
|
|
29319
|
+
if (!skipRiskWarning) {
|
|
29320
|
+
const accepted = await confirm({
|
|
29321
|
+
message: "Hoox connects to live trading exchanges and can execute real trades with real money. By continuing, you acknowledge that you are solely responsible for all trading activity and accept the risk of financial loss. Do you accept these terms?",
|
|
29322
|
+
initialValue: false
|
|
29323
|
+
});
|
|
29324
|
+
if (isCancel(accepted)) {
|
|
29325
|
+
cancel("Setup cancelled.");
|
|
29326
|
+
process.exitCode = 0;
|
|
29327
|
+
}
|
|
29328
|
+
if (!accepted) {
|
|
29329
|
+
outro("Setup cancelled. See DISCLAIMER.md for full terms.");
|
|
29330
|
+
process.exitCode = 0;
|
|
29331
|
+
}
|
|
29270
29332
|
}
|
|
29271
29333
|
engine.execute({ checksPassed: true });
|
|
29272
29334
|
await saveState(engine);
|
|
@@ -38529,7 +38591,31 @@ function sanitizeErrorMessage(message, secrets) {
|
|
|
38529
38591
|
out = out.replace(/([?&]key=)[^&\s]+/gi, "$1[redacted]");
|
|
38530
38592
|
return out;
|
|
38531
38593
|
}
|
|
38594
|
+
var PROBE_ALLOWED_HOSTS = new Set([
|
|
38595
|
+
"api.cloudflare.com",
|
|
38596
|
+
"api.openai.com",
|
|
38597
|
+
"api.anthropic.com",
|
|
38598
|
+
"generativelanguage.googleapis.com",
|
|
38599
|
+
"api.cognitive.microsoft.com"
|
|
38600
|
+
]);
|
|
38601
|
+
function assertProbeUrl(url2) {
|
|
38602
|
+
let parsed;
|
|
38603
|
+
try {
|
|
38604
|
+
parsed = new URL(url2);
|
|
38605
|
+
} catch {
|
|
38606
|
+
throw new Error(`Invalid probe URL: ${url2}`);
|
|
38607
|
+
}
|
|
38608
|
+
if (parsed.protocol !== "https:") {
|
|
38609
|
+
throw new Error(`Probe URL must be https: ${url2}`);
|
|
38610
|
+
}
|
|
38611
|
+
const host = parsed.hostname.toLowerCase();
|
|
38612
|
+
const allowed = PROBE_ALLOWED_HOSTS.has(host) || host.endsWith(".openai.azure.com") || host.endsWith(".cognitiveservices.azure.com");
|
|
38613
|
+
if (!allowed) {
|
|
38614
|
+
throw new Error(`Probe URL host not allowlisted: ${host}`);
|
|
38615
|
+
}
|
|
38616
|
+
}
|
|
38532
38617
|
async function timedFetch(url2, init, timeoutMs) {
|
|
38618
|
+
assertProbeUrl(url2);
|
|
38533
38619
|
const start = performance.now();
|
|
38534
38620
|
const response = await fetch(url2, {
|
|
38535
38621
|
...init,
|
|
@@ -38638,9 +38724,8 @@ async function probeAnthropic(apiKey, timeoutMs) {
|
|
|
38638
38724
|
return { status: "online", latencyMs };
|
|
38639
38725
|
}
|
|
38640
38726
|
if (response.status === 404) {
|
|
38641
|
-
const start = performance.now();
|
|
38642
38727
|
try {
|
|
38643
|
-
const msgRes = await
|
|
38728
|
+
const { response: msgRes, latencyMs: lat } = await timedFetch("https://api.anthropic.com/v1/messages", {
|
|
38644
38729
|
method: "POST",
|
|
38645
38730
|
headers: {
|
|
38646
38731
|
"x-api-key": apiKey,
|
|
@@ -38651,10 +38736,8 @@ async function probeAnthropic(apiKey, timeoutMs) {
|
|
|
38651
38736
|
model: "claude-sonnet-4-20250514",
|
|
38652
38737
|
max_tokens: 1,
|
|
38653
38738
|
messages: [{ role: "user", content: "ping" }]
|
|
38654
|
-
})
|
|
38655
|
-
|
|
38656
|
-
});
|
|
38657
|
-
const lat = Math.round(performance.now() - start);
|
|
38739
|
+
})
|
|
38740
|
+
}, timeoutMs);
|
|
38658
38741
|
if (msgRes.ok)
|
|
38659
38742
|
return { status: "online", latencyMs: lat };
|
|
38660
38743
|
if (msgRes.status === 401 || msgRes.status === 403) {
|
|
@@ -38730,7 +38813,9 @@ async function probeAzure(apiKey, timeoutMs) {
|
|
|
38730
38813
|
error: "AZURE_ENDPOINT missing"
|
|
38731
38814
|
};
|
|
38732
38815
|
}
|
|
38733
|
-
|
|
38816
|
+
let base = endpoint;
|
|
38817
|
+
while (base.endsWith("/"))
|
|
38818
|
+
base = base.slice(0, -1);
|
|
38734
38819
|
const url2 = `${base}/openai/models?api-version=2024-02-01`;
|
|
38735
38820
|
try {
|
|
38736
38821
|
const { response, latencyMs } = await timedFetch(url2, {
|
|
@@ -38988,15 +39073,18 @@ init_config2();
|
|
|
38988
39073
|
import { existsSync as existsSync13, readFileSync as readFileSync8 } from "fs";
|
|
38989
39074
|
import { resolve as resolve7 } from "path";
|
|
38990
39075
|
init_errors4();
|
|
38991
|
-
var PYNE_WORKER_DIR = resolve7(process.cwd(), "workers/pyne-worker");
|
|
38992
39076
|
var DEFAULT_TIMEOUT_MS = 30000;
|
|
39077
|
+
function getPyneWorkerDir() {
|
|
39078
|
+
return resolve7(process.cwd(), "workers/pyne-worker");
|
|
39079
|
+
}
|
|
38993
39080
|
function requirePyneDir() {
|
|
38994
|
-
|
|
38995
|
-
|
|
39081
|
+
const dir = getPyneWorkerDir();
|
|
39082
|
+
if (!existsSync13(dir)) {
|
|
39083
|
+
throw new CLIError(`pyne-worker directory not found: ${dir}
|
|
38996
39084
|
` + ` Clone it with: hoox clone pyne-worker
|
|
38997
39085
|
` + ` Or: git submodule update --init workers/pyne-worker`, 1 /* ERROR */);
|
|
38998
39086
|
}
|
|
38999
|
-
return
|
|
39087
|
+
return dir;
|
|
39000
39088
|
}
|
|
39001
39089
|
function loadDevVars(workerDir) {
|
|
39002
39090
|
const out = {};
|
|
@@ -39064,11 +39152,33 @@ function resolveApiKey(explicit, workerDir) {
|
|
|
39064
39152
|
}
|
|
39065
39153
|
return null;
|
|
39066
39154
|
}
|
|
39155
|
+
function normalizeBaseUrl(url2) {
|
|
39156
|
+
let end = url2.length;
|
|
39157
|
+
while (end > 0 && url2.charCodeAt(end - 1) === 47) {
|
|
39158
|
+
end -= 1;
|
|
39159
|
+
}
|
|
39160
|
+
return end === url2.length ? url2 : url2.slice(0, end);
|
|
39161
|
+
}
|
|
39162
|
+
function buildPyneRequestUrl(baseUrl, path6) {
|
|
39163
|
+
const base = normalizeBaseUrl(baseUrl);
|
|
39164
|
+
let parsed;
|
|
39165
|
+
try {
|
|
39166
|
+
parsed = new URL(base);
|
|
39167
|
+
} catch {
|
|
39168
|
+
throw new CLIError(`Invalid pyne-worker URL: ${baseUrl}`, 1 /* ERROR */);
|
|
39169
|
+
}
|
|
39170
|
+
if (parsed.protocol !== "https:" && parsed.protocol !== "http:") {
|
|
39171
|
+
throw new CLIError(`pyne-worker URL must be http(s): ${baseUrl}`, 1 /* ERROR */);
|
|
39172
|
+
}
|
|
39173
|
+
const suffix = path6.startsWith("/") ? path6 : `/${path6}`;
|
|
39174
|
+
return `${parsed.origin}${parsed.pathname === "/" ? "" : parsed.pathname}${suffix}`;
|
|
39175
|
+
}
|
|
39067
39176
|
async function pyneFetch(baseUrl, path6, options = {}) {
|
|
39068
39177
|
const method = options.method ?? "GET";
|
|
39069
39178
|
const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
39070
39179
|
const controller = new AbortController;
|
|
39071
39180
|
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
39181
|
+
const requestUrl = buildPyneRequestUrl(baseUrl, path6);
|
|
39072
39182
|
const headers = {
|
|
39073
39183
|
Accept: "application/json"
|
|
39074
39184
|
};
|
|
@@ -39081,7 +39191,7 @@ async function pyneFetch(baseUrl, path6, options = {}) {
|
|
|
39081
39191
|
body = JSON.stringify(options.body);
|
|
39082
39192
|
}
|
|
39083
39193
|
try {
|
|
39084
|
-
const res = await fetch(
|
|
39194
|
+
const res = await fetch(requestUrl, {
|
|
39085
39195
|
method,
|
|
39086
39196
|
headers,
|
|
39087
39197
|
body,
|
|
@@ -39101,8 +39211,7 @@ async function pyneFetch(baseUrl, path6, options = {}) {
|
|
|
39101
39211
|
}
|
|
39102
39212
|
function printResult(data, fmt) {
|
|
39103
39213
|
if (fmt.json) {
|
|
39104
|
-
|
|
39105
|
-
`);
|
|
39214
|
+
formatJson(data, fmt);
|
|
39106
39215
|
return;
|
|
39107
39216
|
}
|
|
39108
39217
|
if (typeof data === "string") {
|
|
@@ -39111,8 +39220,7 @@ function printResult(data, fmt) {
|
|
|
39111
39220
|
`));
|
|
39112
39221
|
return;
|
|
39113
39222
|
}
|
|
39114
|
-
|
|
39115
|
-
`);
|
|
39223
|
+
formatJson(data, fmt);
|
|
39116
39224
|
}
|
|
39117
39225
|
async function spawnInPyneDir(cmd, cwd) {
|
|
39118
39226
|
const proc = Bun.spawn(cmd, {
|
|
@@ -39164,27 +39272,24 @@ EXAMPLES:
|
|
|
39164
39272
|
if (!res.ok)
|
|
39165
39273
|
process.exitCode = 1 /* ERROR */;
|
|
39166
39274
|
if (fmt.json) {
|
|
39167
|
-
|
|
39168
|
-
`);
|
|
39275
|
+
formatJson(payload, fmt);
|
|
39169
39276
|
} else {
|
|
39170
39277
|
const icon = res.ok ? "ok" : "fail";
|
|
39171
39278
|
formatSuccess(`pyne-worker ${icon} \u2014 HTTP ${res.status} in ${latencyMs}ms (${baseUrl})`, fmt);
|
|
39172
39279
|
if (res.json) {
|
|
39173
|
-
|
|
39174
|
-
`);
|
|
39280
|
+
formatJson(res.json, fmt);
|
|
39175
39281
|
}
|
|
39176
39282
|
}
|
|
39177
39283
|
} catch (err) {
|
|
39178
39284
|
process.exitCode = 1 /* ERROR */;
|
|
39179
39285
|
const message = err instanceof Error ? err.message : String(err);
|
|
39180
39286
|
if (fmt.json) {
|
|
39181
|
-
|
|
39287
|
+
formatJson({
|
|
39182
39288
|
worker: "pyne-worker",
|
|
39183
39289
|
url: `${baseUrl}/health`,
|
|
39184
39290
|
status: "down",
|
|
39185
39291
|
error: message
|
|
39186
|
-
})
|
|
39187
|
-
`);
|
|
39292
|
+
}, fmt);
|
|
39188
39293
|
} else {
|
|
39189
39294
|
throw new CLIError(`pyne-worker health failed: ${message}`, 1 /* ERROR */);
|
|
39190
39295
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hoox-sh/hoox-cli",
|
|
3
|
-
"version": "0.11.
|
|
3
|
+
"version": "0.11.2",
|
|
4
4
|
"description": "Hoox CLI — manage Cloudflare Workers, infrastructure, secrets, and deployments (@hoox-sh/hoox-cli)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"@hoox-sh/hoox-tui": "workspace:*"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
|
-
"@hoox-sh/hoox-shared": "^1.2.
|
|
29
|
+
"@hoox-sh/hoox-shared": "^1.2.1",
|
|
30
30
|
"@types/node": "^26.1.1",
|
|
31
31
|
"bun-types": "^1.3.14",
|
|
32
32
|
"typescript": "^6.0.3"
|