@hoox-sh/hoox-shared 1.2.0 → 1.3.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/agent-config-fields.js +2 -0
- package/dist/api-client.js +6 -2
- package/dist/index.d.ts +4 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +282 -61
- package/dist/kill-switch.d.ts +47 -0
- package/dist/kill-switch.d.ts.map +1 -0
- package/dist/kill-switch.js +130 -0
- package/dist/kvKeys.d.ts +2 -0
- package/dist/kvKeys.d.ts.map +1 -1
- package/dist/kvKeys.js +3 -0
- package/dist/operator-transport.d.ts.map +1 -1
- package/dist/operator-transport.js +6 -2
- package/dist/path-utils.d.ts +35 -4
- package/dist/path-utils.d.ts.map +1 -1
- package/dist/path-utils.js +72 -5
- package/dist/service-bindings.d.ts +1 -1
- package/dist/service-bindings.d.ts.map +1 -1
- package/dist/session.js +69 -5
- package/dist/sse.js +6 -2
- package/dist/stores/config-store.d.ts +2 -0
- package/dist/stores/config-store.d.ts.map +1 -1
- package/dist/stores/config-store.js +267 -16
- package/dist/stores/service-store.d.ts +12 -0
- package/dist/stores/service-store.d.ts.map +1 -1
- package/dist/stores/service-store.js +106 -41
- package/dist/stores/ui-store.d.ts +14 -0
- package/dist/stores/ui-store.d.ts.map +1 -1
- package/dist/stores/ui-store.js +8 -1
- package/dist/types.d.ts +1 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +1 -0
- package/package.json +1 -1
|
@@ -39,6 +39,7 @@ var KV_AGENT_OPENAI_KEY = "agent:openai_key";
|
|
|
39
39
|
var KV_AGENT_ANTHROPIC_KEY = "agent:anthropic_key";
|
|
40
40
|
var KV_AGENT_GOOGLE_KEY = "agent:google_key";
|
|
41
41
|
var KV_DASHBOARD_AI_HEALTH_SUMMARY = "dashboard:ai_health_summary";
|
|
42
|
+
var KV_GLOBAL_KILL_SWITCH = "global:kill_switch";
|
|
42
43
|
var KV_HEALTH_CHECK = "health_check";
|
|
43
44
|
var KV_HOUSEKEEPING_LAST_CHECK = "housekeeping:last_check";
|
|
44
45
|
var QUEUE_MODE_FAILOVER = "queue_failover";
|
|
@@ -68,6 +69,7 @@ var KVKeys = {
|
|
|
68
69
|
KV_AGENT_ANTHROPIC_KEY,
|
|
69
70
|
KV_AGENT_GOOGLE_KEY,
|
|
70
71
|
KV_DASHBOARD_AI_HEALTH_SUMMARY,
|
|
72
|
+
KV_GLOBAL_KILL_SWITCH,
|
|
71
73
|
KV_HEALTH_CHECK,
|
|
72
74
|
KV_HOUSEKEEPING_LAST_CHECK,
|
|
73
75
|
QUEUE_MODE_FAILOVER,
|
package/dist/api-client.js
CHANGED
|
@@ -17,7 +17,11 @@ var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
|
17
17
|
|
|
18
18
|
// src/operator-transport.ts
|
|
19
19
|
function stripTrailingSlashes(url) {
|
|
20
|
-
|
|
20
|
+
let end = url.length;
|
|
21
|
+
while (end > 0 && url.charCodeAt(end - 1) === 47) {
|
|
22
|
+
end -= 1;
|
|
23
|
+
}
|
|
24
|
+
return end === url.length ? url : url.slice(0, end);
|
|
21
25
|
}
|
|
22
26
|
function parseTransport(raw) {
|
|
23
27
|
if (!raw)
|
|
@@ -64,7 +68,7 @@ function hasOperatorClientCredentials(profile) {
|
|
|
64
68
|
return Boolean(profile.accessClientId && profile.accessClientSecret);
|
|
65
69
|
}
|
|
66
70
|
function operatorUrl(profile, path) {
|
|
67
|
-
const base = profile.apiBase
|
|
71
|
+
const base = stripTrailingSlashes(profile.apiBase);
|
|
68
72
|
const p = path.startsWith("/") ? path : `/${path}`;
|
|
69
73
|
return `${base}${p}`;
|
|
70
74
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -18,6 +18,8 @@ export type { StandardResponse, ApiSuccessResponse, ApiErrorResponse, ApiRespons
|
|
|
18
18
|
export { TradeActionSchema, WebhookPayloadSchema, TradeQueueMessageSchema, TradeSignalSchema, PositionSchema, BalanceSchema, } from "./types";
|
|
19
19
|
export type { TradeAction, WebhookPayload, TradeQueueMessage, TradeSignal, } from "./types";
|
|
20
20
|
export { KVKeys } from "./kvKeys";
|
|
21
|
+
export { KILL_SWITCH_KEYS, KILL_SWITCH_ACTIVE_PREFIX, isTruthyKillSwitchFlag, checkKillSwitch, isTradingPaused, } from "./kill-switch";
|
|
22
|
+
export type { KillSwitchFailMode, KillSwitchResult, CheckKillSwitchOptions, KillSwitchKv, } from "./kill-switch";
|
|
21
23
|
export { toError, Errors, createJsonResponse, createSuccessResponse, createErrorResponse, } from "./errors";
|
|
22
24
|
export { ExchangeRouter } from "./exchange-client";
|
|
23
25
|
export type { ExchangeName, ExchangeConfig, TradeParams, OrderResponse, Position, IExchangeProvider, ClientCreateOptions, } from "./exchange-client";
|
|
@@ -53,8 +55,8 @@ export { restoreSession, saveSession } from "./session";
|
|
|
53
55
|
export type { SessionState } from "./session";
|
|
54
56
|
export { formatRelativeTime as formatRelativeTimeFromTime } from "./format-time";
|
|
55
57
|
export type { ViewId, ModalState, WorkerStatus, WorkerInfo, TradeSide, Trade, AlertSeverity, Alert, LogLevel, LogEntry, SystemMetrics, ConnectionStatus, LogFilter, NotificationPreferences, CliErrorType, CliErrorDetails, } from "./types";
|
|
56
|
-
export { getHooxHome, resolveHooxPath, isWithinHooxHome, getRelativeHooxPath, getHooxRepoPath, getHooxConfigDir, getHooxDataDir, getHooxWranglerPath, getHooxStatePath, isHooxSetupRoot, findHooxSetupRoot, resolveHooxRuntimeRoot, getTuiEntryCandidates, } from "./path-utils";
|
|
57
|
-
export type { HooxPath, RuntimeRootSource, RuntimeRootResult, } from "./path-utils";
|
|
58
|
+
export { getHooxHome, resolveHooxPath, isWithinHooxHome, getRelativeHooxPath, getHooxRepoPath, getHooxConfigDir, getHooxDataDir, getHooxWranglerPath, getHooxStatePath, isHooxSetupRoot, findHooxSetupRoot, resolveHooxRuntimeRoot, getTuiEntryCandidates, getRememberedMonorepoPath, getRememberedMonorepoRoot, rememberMonorepoRoot, } from "./path-utils";
|
|
59
|
+
export type { HooxPath, RuntimeRootSource, RuntimeRootResult, RememberedMonorepo, } from "./path-utils";
|
|
58
60
|
export { DASHBOARD_WORKER_PREFIX, DASHBOARD_SECTION_PREFIX, DASHBOARD_FIELD_KV_OVERRIDES, DASHBOARD_SECTIONS_NOT_FLAT_KV, DASHBOARD_SECTIONS_UI_SKIP, DASHBOARD_WORKER_IDS, buildDashboardKvKey, isDashboardSectionFlatKv, isDashboardSectionEditable, stripJsonc, parseDashboardManifest, dashboardWorkerDir, kvManifestFromDashboardManifests, loadDashboardKvManifestFromRoot, loadDashboardManifestsFromRoot, } from "./dashboard-manifest";
|
|
59
61
|
export type { DashboardFieldType, DashboardFieldKind, DashboardFieldOption, DashboardSettingField, DashboardSection, WorkerDashboardManifest, DashboardWorkerId, DashboardKvManifestKey, DashboardKvManifest, } from "./dashboard-manifest";
|
|
60
62
|
export { AGENT_CONFIG_KV_KEY, AGENT_CONFIG_EMBEDDED_FIELDS, DASHBOARD_SECTIONS_AGENT_CONFIG, isAgentConfigEmbeddedField, isAgentConfigSection, parseAgentConfigJson, serializeAgentConfigForKv, getAgentConfigEmbeddedValue, setAgentConfigEmbeddedValue, expandAgentConfigToFieldMap, applyAgentConfigFieldUpdates, } from "./agent-config-fields";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -17,7 +17,11 @@ var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
|
17
17
|
|
|
18
18
|
// src/operator-transport.ts
|
|
19
19
|
function stripTrailingSlashes(url) {
|
|
20
|
-
|
|
20
|
+
let end = url.length;
|
|
21
|
+
while (end > 0 && url.charCodeAt(end - 1) === 47) {
|
|
22
|
+
end -= 1;
|
|
23
|
+
}
|
|
24
|
+
return end === url.length ? url : url.slice(0, end);
|
|
21
25
|
}
|
|
22
26
|
function parseTransport(raw) {
|
|
23
27
|
if (!raw)
|
|
@@ -64,7 +68,7 @@ function hasOperatorClientCredentials(profile) {
|
|
|
64
68
|
return Boolean(profile.accessClientId && profile.accessClientSecret);
|
|
65
69
|
}
|
|
66
70
|
function operatorUrl(profile, path) {
|
|
67
|
-
const base = profile.apiBase
|
|
71
|
+
const base = stripTrailingSlashes(profile.apiBase);
|
|
68
72
|
const p = path.startsWith("/") ? path : `/${path}`;
|
|
69
73
|
return `${base}${p}`;
|
|
70
74
|
}
|
|
@@ -278,6 +282,7 @@ var KV_AGENT_OPENAI_KEY = "agent:openai_key";
|
|
|
278
282
|
var KV_AGENT_ANTHROPIC_KEY = "agent:anthropic_key";
|
|
279
283
|
var KV_AGENT_GOOGLE_KEY = "agent:google_key";
|
|
280
284
|
var KV_DASHBOARD_AI_HEALTH_SUMMARY = "dashboard:ai_health_summary";
|
|
285
|
+
var KV_GLOBAL_KILL_SWITCH = "global:kill_switch";
|
|
281
286
|
var KV_HEALTH_CHECK = "health_check";
|
|
282
287
|
var KV_HOUSEKEEPING_LAST_CHECK = "housekeeping:last_check";
|
|
283
288
|
var QUEUE_MODE_FAILOVER = "queue_failover";
|
|
@@ -307,6 +312,7 @@ var KVKeys = {
|
|
|
307
312
|
KV_AGENT_ANTHROPIC_KEY,
|
|
308
313
|
KV_AGENT_GOOGLE_KEY,
|
|
309
314
|
KV_DASHBOARD_AI_HEALTH_SUMMARY,
|
|
315
|
+
KV_GLOBAL_KILL_SWITCH,
|
|
310
316
|
KV_HEALTH_CHECK,
|
|
311
317
|
KV_HOUSEKEEPING_LAST_CHECK,
|
|
312
318
|
QUEUE_MODE_FAILOVER,
|
|
@@ -1786,6 +1792,7 @@ var TradeQueueMessageSchema = z2.object({
|
|
|
1786
1792
|
price: z2.number().positive().finite().optional(),
|
|
1787
1793
|
leverage: z2.number().int().positive().max(125).optional(),
|
|
1788
1794
|
test: z2.boolean().optional(),
|
|
1795
|
+
idempotencyKey: z2.string().min(1).max(512).optional(),
|
|
1789
1796
|
queuedAt: z2.string().min(1).max(64)
|
|
1790
1797
|
}).strict();
|
|
1791
1798
|
var TradeSignalSchema = z2.object({
|
|
@@ -1818,6 +1825,51 @@ var BalanceSchema = z2.object({
|
|
|
1818
1825
|
timestamp: z2.number().int().positive()
|
|
1819
1826
|
}).strict();
|
|
1820
1827
|
|
|
1828
|
+
// src/kill-switch.ts
|
|
1829
|
+
var KILL_SWITCH_ACTIVE_PREFIX = "KILL_SWITCH_ACTIVE";
|
|
1830
|
+
var KILL_SWITCH_KEYS = [
|
|
1831
|
+
KV_TRADE_KILL_SWITCH,
|
|
1832
|
+
KV_GLOBAL_KILL_SWITCH
|
|
1833
|
+
];
|
|
1834
|
+
function isTruthyKillSwitchFlag(value) {
|
|
1835
|
+
if (value == null)
|
|
1836
|
+
return false;
|
|
1837
|
+
const v = value.trim().toLowerCase();
|
|
1838
|
+
return v === "true" || v === "1" || v === "yes" || v === "on";
|
|
1839
|
+
}
|
|
1840
|
+
async function checkKillSwitch(kv, options) {
|
|
1841
|
+
const onMissingKv = options?.onMissingKv ?? "open";
|
|
1842
|
+
const onReadError = options?.onReadError ?? "closed";
|
|
1843
|
+
if (!kv) {
|
|
1844
|
+
if (onMissingKv === "closed") {
|
|
1845
|
+
return { enabled: true, source: "missing_kv" };
|
|
1846
|
+
}
|
|
1847
|
+
return { enabled: false };
|
|
1848
|
+
}
|
|
1849
|
+
try {
|
|
1850
|
+
const values = await Promise.all(KILL_SWITCH_KEYS.map(async (key) => ({
|
|
1851
|
+
key,
|
|
1852
|
+
value: await kv.get(key)
|
|
1853
|
+
})));
|
|
1854
|
+
for (const { key, value } of values) {
|
|
1855
|
+
if (isTruthyKillSwitchFlag(value)) {
|
|
1856
|
+
return { enabled: true, source: key };
|
|
1857
|
+
}
|
|
1858
|
+
}
|
|
1859
|
+
return { enabled: false };
|
|
1860
|
+
} catch (error) {
|
|
1861
|
+
const errorStr = String(error);
|
|
1862
|
+
if (onReadError === "closed") {
|
|
1863
|
+
return { enabled: true, source: "read_error", error: errorStr };
|
|
1864
|
+
}
|
|
1865
|
+
return { enabled: false, error: errorStr };
|
|
1866
|
+
}
|
|
1867
|
+
}
|
|
1868
|
+
async function isTradingPaused(kv, options) {
|
|
1869
|
+
const result = await checkKillSwitch(kv, options);
|
|
1870
|
+
return result.enabled;
|
|
1871
|
+
}
|
|
1872
|
+
|
|
1821
1873
|
// src/kvUtils.ts
|
|
1822
1874
|
async function logKvTimestamp(env, prefix = "timestamp") {
|
|
1823
1875
|
const timestamp = new Date().toISOString();
|
|
@@ -2184,7 +2236,13 @@ function createMockEnv(overrides) {
|
|
|
2184
2236
|
}
|
|
2185
2237
|
|
|
2186
2238
|
// src/path-utils.ts
|
|
2187
|
-
import {
|
|
2239
|
+
import {
|
|
2240
|
+
existsSync as existsSync3,
|
|
2241
|
+
mkdirSync as mkdirSync2,
|
|
2242
|
+
readFileSync as readFileSync3,
|
|
2243
|
+
writeFileSync as writeFileSync2,
|
|
2244
|
+
chmodSync as chmodSync2
|
|
2245
|
+
} from "fs";
|
|
2188
2246
|
import { homedir as homedir2 } from "os";
|
|
2189
2247
|
import { dirname, join as join3, resolve } from "path";
|
|
2190
2248
|
function createHooxPath(path) {
|
|
@@ -2210,7 +2268,55 @@ function isHooxSetupRoot(dir) {
|
|
|
2210
2268
|
return false;
|
|
2211
2269
|
try {
|
|
2212
2270
|
const root = resolve(dir);
|
|
2213
|
-
|
|
2271
|
+
if (!existsSync3(join3(root, "packages", "cli", "package.json"))) {
|
|
2272
|
+
return false;
|
|
2273
|
+
}
|
|
2274
|
+
return existsSync3(join3(root, "wrangler.jsonc")) || existsSync3(join3(root, "wrangler.jsonc.example")) || existsSync3(join3(root, "workers")) || existsSync3(join3(root, ".gitmodules"));
|
|
2275
|
+
} catch {
|
|
2276
|
+
return false;
|
|
2277
|
+
}
|
|
2278
|
+
}
|
|
2279
|
+
function getRememberedMonorepoPath() {
|
|
2280
|
+
return resolveHooxPath("config/monorepo.json");
|
|
2281
|
+
}
|
|
2282
|
+
function getRememberedMonorepoRoot() {
|
|
2283
|
+
try {
|
|
2284
|
+
const path = getRememberedMonorepoPath();
|
|
2285
|
+
if (!existsSync3(path))
|
|
2286
|
+
return null;
|
|
2287
|
+
const raw = readFileSync3(path, "utf-8");
|
|
2288
|
+
const data = JSON.parse(raw);
|
|
2289
|
+
if (!data.root || typeof data.root !== "string")
|
|
2290
|
+
return null;
|
|
2291
|
+
const resolved = resolve(data.root);
|
|
2292
|
+
return isHooxSetupRoot(resolved) ? resolved : null;
|
|
2293
|
+
} catch {
|
|
2294
|
+
return null;
|
|
2295
|
+
}
|
|
2296
|
+
}
|
|
2297
|
+
function rememberMonorepoRoot(root) {
|
|
2298
|
+
try {
|
|
2299
|
+
const resolved = resolve(root);
|
|
2300
|
+
if (!isHooxSetupRoot(resolved))
|
|
2301
|
+
return false;
|
|
2302
|
+
const configDir = getHooxConfigDir();
|
|
2303
|
+
mkdirSync2(configDir, { recursive: true, mode: 448 });
|
|
2304
|
+
try {
|
|
2305
|
+
chmodSync2(configDir, 448);
|
|
2306
|
+
} catch {}
|
|
2307
|
+
const payload = {
|
|
2308
|
+
root: resolved,
|
|
2309
|
+
updatedAt: new Date().toISOString()
|
|
2310
|
+
};
|
|
2311
|
+
const path = getRememberedMonorepoPath();
|
|
2312
|
+
writeFileSync2(path, JSON.stringify(payload, null, 2) + `
|
|
2313
|
+
`, {
|
|
2314
|
+
mode: 384
|
|
2315
|
+
});
|
|
2316
|
+
try {
|
|
2317
|
+
chmodSync2(path, 384);
|
|
2318
|
+
} catch {}
|
|
2319
|
+
return true;
|
|
2214
2320
|
} catch {
|
|
2215
2321
|
return false;
|
|
2216
2322
|
}
|
|
@@ -2230,6 +2336,7 @@ function resolveHooxRuntimeRoot(options) {
|
|
|
2230
2336
|
const env = options?.env ?? process.env;
|
|
2231
2337
|
const cwd = resolve(options?.cwd ?? process.cwd());
|
|
2232
2338
|
const globalRepo = getHooxRepoPath();
|
|
2339
|
+
const remembered = options?.skipRemembered ? null : getRememberedMonorepoRoot();
|
|
2233
2340
|
const envRepo = env.HOOX_REPO?.trim();
|
|
2234
2341
|
if (envRepo) {
|
|
2235
2342
|
const resolved = resolve(envRepo);
|
|
@@ -2240,6 +2347,7 @@ function resolveHooxRuntimeRoot(options) {
|
|
|
2240
2347
|
checked: {
|
|
2241
2348
|
env: resolved,
|
|
2242
2349
|
cwd: findHooxSetupRoot(cwd),
|
|
2350
|
+
remembered,
|
|
2243
2351
|
global: globalRepo
|
|
2244
2352
|
}
|
|
2245
2353
|
};
|
|
@@ -2250,6 +2358,7 @@ function resolveHooxRuntimeRoot(options) {
|
|
|
2250
2358
|
checked: {
|
|
2251
2359
|
env: resolved,
|
|
2252
2360
|
cwd: findHooxSetupRoot(cwd),
|
|
2361
|
+
remembered,
|
|
2253
2362
|
global: globalRepo
|
|
2254
2363
|
}
|
|
2255
2364
|
};
|
|
@@ -2259,20 +2368,27 @@ function resolveHooxRuntimeRoot(options) {
|
|
|
2259
2368
|
return {
|
|
2260
2369
|
root: local,
|
|
2261
2370
|
source: "cwd",
|
|
2262
|
-
checked: { cwd: local, global: globalRepo }
|
|
2371
|
+
checked: { cwd: local, remembered, global: globalRepo }
|
|
2372
|
+
};
|
|
2373
|
+
}
|
|
2374
|
+
if (remembered) {
|
|
2375
|
+
return {
|
|
2376
|
+
root: remembered,
|
|
2377
|
+
source: "remembered",
|
|
2378
|
+
checked: { cwd: null, remembered, global: globalRepo }
|
|
2263
2379
|
};
|
|
2264
2380
|
}
|
|
2265
2381
|
if (isHooxSetupRoot(globalRepo)) {
|
|
2266
2382
|
return {
|
|
2267
2383
|
root: globalRepo,
|
|
2268
2384
|
source: "global",
|
|
2269
|
-
checked: { cwd: null, global: globalRepo }
|
|
2385
|
+
checked: { cwd: null, remembered: null, global: globalRepo }
|
|
2270
2386
|
};
|
|
2271
2387
|
}
|
|
2272
2388
|
return {
|
|
2273
2389
|
root: null,
|
|
2274
2390
|
source: "none",
|
|
2275
|
-
checked: { cwd: null, global: globalRepo }
|
|
2391
|
+
checked: { cwd: null, remembered: null, global: globalRepo }
|
|
2276
2392
|
};
|
|
2277
2393
|
}
|
|
2278
2394
|
function getTuiEntryCandidates(runtimeRoot) {
|
|
@@ -3625,7 +3741,8 @@ var initialState = {
|
|
|
3625
3741
|
sidebarExpanded: true,
|
|
3626
3742
|
modal: null,
|
|
3627
3743
|
commandPaletteOpen: false,
|
|
3628
|
-
previousView: null
|
|
3744
|
+
previousView: null,
|
|
3745
|
+
statusErrorExpanded: false
|
|
3629
3746
|
};
|
|
3630
3747
|
var useUIStore = create()(immer((set) => ({
|
|
3631
3748
|
...initialState,
|
|
@@ -3656,6 +3773,12 @@ var useUIStore = create()(immer((set) => ({
|
|
|
3656
3773
|
state.activeView = state.previousView;
|
|
3657
3774
|
state.previousView = null;
|
|
3658
3775
|
}
|
|
3776
|
+
}),
|
|
3777
|
+
toggleStatusErrorExpanded: () => set((state) => {
|
|
3778
|
+
state.statusErrorExpanded = !state.statusErrorExpanded;
|
|
3779
|
+
}),
|
|
3780
|
+
setStatusErrorExpanded: (expanded) => set((state) => {
|
|
3781
|
+
state.statusErrorExpanded = expanded;
|
|
3659
3782
|
})
|
|
3660
3783
|
})));
|
|
3661
3784
|
|
|
@@ -3678,6 +3801,23 @@ function ringPush(arr, item, max) {
|
|
|
3678
3801
|
var tradeStreamAbort = null;
|
|
3679
3802
|
var logStreamAbort = null;
|
|
3680
3803
|
var fetchWorkersGeneration = 0;
|
|
3804
|
+
var reconnectTimer = null;
|
|
3805
|
+
function clearReconnectTimer() {
|
|
3806
|
+
if (reconnectTimer !== null) {
|
|
3807
|
+
clearTimeout(reconnectTimer);
|
|
3808
|
+
reconnectTimer = null;
|
|
3809
|
+
}
|
|
3810
|
+
}
|
|
3811
|
+
function scheduleReconnect(delayMs) {
|
|
3812
|
+
clearReconnectTimer();
|
|
3813
|
+
if (delayMs < 0)
|
|
3814
|
+
return;
|
|
3815
|
+
reconnectTimer = setTimeout(() => {
|
|
3816
|
+
reconnectTimer = null;
|
|
3817
|
+
scheduledReconnectTick();
|
|
3818
|
+
}, delayMs);
|
|
3819
|
+
}
|
|
3820
|
+
var scheduledReconnectTick = async () => {};
|
|
3681
3821
|
var MAX_TRADES = 500;
|
|
3682
3822
|
var MAX_ALERTS = 100;
|
|
3683
3823
|
var MAX_LOGS = 1000;
|
|
@@ -3712,6 +3852,7 @@ var useServiceStore = create2()(immer2((set, get) => ({
|
|
|
3712
3852
|
const data = await hooxFetch2("/v1/workers");
|
|
3713
3853
|
if (gen !== fetchWorkersGeneration)
|
|
3714
3854
|
return;
|
|
3855
|
+
clearReconnectTimer();
|
|
3715
3856
|
set((state) => {
|
|
3716
3857
|
state.workers = data;
|
|
3717
3858
|
state.lastUpdated = Date.now();
|
|
@@ -3737,6 +3878,7 @@ var useServiceStore = create2()(immer2((set, get) => ({
|
|
|
3737
3878
|
timestamp: Date.now(),
|
|
3738
3879
|
acknowledged: false
|
|
3739
3880
|
});
|
|
3881
|
+
let nextDelay = 0;
|
|
3740
3882
|
set((state) => {
|
|
3741
3883
|
state.lastError = msg;
|
|
3742
3884
|
state.disconnectedAt = state.disconnectedAt ?? Date.now();
|
|
@@ -3745,21 +3887,26 @@ var useServiceStore = create2()(immer2((set, get) => ({
|
|
|
3745
3887
|
state.retryCount = state.retryCount + 1;
|
|
3746
3888
|
if (state.retryCount >= MAX_RETRIES2) {
|
|
3747
3889
|
state.connectionStatus = "offline";
|
|
3748
|
-
state.lastError =
|
|
3890
|
+
state.lastError = `${msg} (gave up after ${MAX_RETRIES2} retries)`;
|
|
3891
|
+
state.reconnectDelay = 0;
|
|
3749
3892
|
} else {
|
|
3750
3893
|
state.reconnectDelay = getBackoffDelay(state.retryCount);
|
|
3894
|
+
nextDelay = state.reconnectDelay;
|
|
3751
3895
|
}
|
|
3752
3896
|
} else if (state.connectionStatus === "reconnecting") {
|
|
3753
3897
|
state.retryCount = state.retryCount + 1;
|
|
3754
3898
|
if (state.retryCount >= MAX_RETRIES2) {
|
|
3755
3899
|
state.connectionStatus = "offline";
|
|
3756
|
-
state.lastError =
|
|
3900
|
+
state.lastError = `${msg} (gave up after ${MAX_RETRIES2} retries)`;
|
|
3757
3901
|
state.reconnectDelay = 0;
|
|
3758
3902
|
} else {
|
|
3759
3903
|
state.reconnectDelay = getBackoffDelay(state.retryCount);
|
|
3904
|
+
nextDelay = state.reconnectDelay;
|
|
3760
3905
|
}
|
|
3761
3906
|
}
|
|
3762
3907
|
});
|
|
3908
|
+
if (nextDelay > 0)
|
|
3909
|
+
scheduleReconnect(nextDelay);
|
|
3763
3910
|
}
|
|
3764
3911
|
},
|
|
3765
3912
|
streamTrades: async () => {
|
|
@@ -3821,6 +3968,17 @@ var useServiceStore = create2()(immer2((set, get) => ({
|
|
|
3821
3968
|
const merged = [...state.alerts, ...alerts];
|
|
3822
3969
|
state.alerts = merged.length > MAX_ALERTS ? merged.slice(merged.length - MAX_ALERTS) : merged;
|
|
3823
3970
|
}),
|
|
3971
|
+
acknowledgeAlert: (id) => set((state) => {
|
|
3972
|
+
const hit = state.alerts.find((a) => a.id === id);
|
|
3973
|
+
if (hit)
|
|
3974
|
+
hit.acknowledged = true;
|
|
3975
|
+
}),
|
|
3976
|
+
dismissAlert: (id) => set((state) => {
|
|
3977
|
+
state.alerts = state.alerts.filter((a) => a.id !== id);
|
|
3978
|
+
}),
|
|
3979
|
+
clearLogs: () => set((state) => {
|
|
3980
|
+
state.logs = [];
|
|
3981
|
+
}),
|
|
3824
3982
|
setConnectionStatus: (status) => set((state) => {
|
|
3825
3983
|
if (status === "connected") {
|
|
3826
3984
|
state.retryCount = 0;
|
|
@@ -3851,49 +4009,69 @@ var useServiceStore = create2()(immer2((set, get) => ({
|
|
|
3851
4009
|
state.metrics = metrics;
|
|
3852
4010
|
state.lastUpdated = metrics.lastUpdated;
|
|
3853
4011
|
}),
|
|
3854
|
-
handleConnectionSuccess: () =>
|
|
3855
|
-
|
|
3856
|
-
state
|
|
3857
|
-
|
|
3858
|
-
|
|
3859
|
-
|
|
3860
|
-
|
|
3861
|
-
|
|
3862
|
-
|
|
3863
|
-
|
|
3864
|
-
|
|
3865
|
-
|
|
3866
|
-
|
|
3867
|
-
|
|
3868
|
-
|
|
3869
|
-
state.
|
|
3870
|
-
|
|
3871
|
-
state.
|
|
3872
|
-
|
|
3873
|
-
state.
|
|
3874
|
-
state.
|
|
3875
|
-
state.reconnectDelay
|
|
3876
|
-
} else {
|
|
3877
|
-
state.
|
|
4012
|
+
handleConnectionSuccess: () => {
|
|
4013
|
+
clearReconnectTimer();
|
|
4014
|
+
set((state) => {
|
|
4015
|
+
state.lastSuccessfulFetch = Date.now();
|
|
4016
|
+
state.retryCount = 0;
|
|
4017
|
+
state.lastError = null;
|
|
4018
|
+
state.lastErrorDetails = null;
|
|
4019
|
+
state.reconnectDelay = 0;
|
|
4020
|
+
state.disconnectedAt = null;
|
|
4021
|
+
state.connectionStatus = "connected";
|
|
4022
|
+
});
|
|
4023
|
+
},
|
|
4024
|
+
handleConnectionFailure: (errorMessage) => {
|
|
4025
|
+
let nextDelay = 0;
|
|
4026
|
+
set((state) => {
|
|
4027
|
+
state.lastError = errorMessage;
|
|
4028
|
+
state.disconnectedAt = state.disconnectedAt ?? Date.now();
|
|
4029
|
+
if (state.connectionStatus === "connected" || state.connectionStatus === "polling") {
|
|
4030
|
+
state.connectionStatus = "reconnecting";
|
|
4031
|
+
state.retryCount = 1;
|
|
4032
|
+
state.reconnectDelay = getBackoffDelay(1);
|
|
4033
|
+
nextDelay = state.reconnectDelay;
|
|
4034
|
+
} else if (state.connectionStatus === "reconnecting") {
|
|
4035
|
+
state.retryCount = state.retryCount + 1;
|
|
4036
|
+
if (state.retryCount >= MAX_RETRIES2) {
|
|
4037
|
+
state.connectionStatus = "offline";
|
|
4038
|
+
state.lastError = `${errorMessage} (gave up after ${MAX_RETRIES2} retries)`;
|
|
4039
|
+
state.reconnectDelay = 0;
|
|
4040
|
+
} else {
|
|
4041
|
+
state.reconnectDelay = getBackoffDelay(state.retryCount);
|
|
4042
|
+
nextDelay = state.reconnectDelay;
|
|
4043
|
+
}
|
|
3878
4044
|
}
|
|
3879
|
-
}
|
|
3880
|
-
|
|
3881
|
-
|
|
3882
|
-
|
|
3883
|
-
|
|
3884
|
-
|
|
3885
|
-
state
|
|
3886
|
-
state.disconnectedAt = null;
|
|
3887
|
-
}),
|
|
3888
|
-
forceRetry: () => set((state) => {
|
|
3889
|
-
if (state.connectionStatus === "offline") {
|
|
3890
|
-
state.connectionStatus = "polling";
|
|
4045
|
+
});
|
|
4046
|
+
if (nextDelay > 0)
|
|
4047
|
+
scheduleReconnect(nextDelay);
|
|
4048
|
+
},
|
|
4049
|
+
resetRetries: () => {
|
|
4050
|
+
clearReconnectTimer();
|
|
4051
|
+
set((state) => {
|
|
3891
4052
|
state.retryCount = 0;
|
|
3892
4053
|
state.lastError = null;
|
|
3893
4054
|
state.lastErrorDetails = null;
|
|
3894
4055
|
state.reconnectDelay = 0;
|
|
4056
|
+
state.disconnectedAt = null;
|
|
4057
|
+
});
|
|
4058
|
+
},
|
|
4059
|
+
forceRetry: () => {
|
|
4060
|
+
clearReconnectTimer();
|
|
4061
|
+
const wasOffline = get().connectionStatus === "offline";
|
|
4062
|
+
set((state) => {
|
|
4063
|
+
if (state.connectionStatus === "offline") {
|
|
4064
|
+
state.connectionStatus = "polling";
|
|
4065
|
+
state.retryCount = 0;
|
|
4066
|
+
state.lastError = null;
|
|
4067
|
+
state.lastErrorDetails = null;
|
|
4068
|
+
state.reconnectDelay = 0;
|
|
4069
|
+
}
|
|
4070
|
+
});
|
|
4071
|
+
if (wasOffline) {
|
|
4072
|
+
scheduleReconnect(0);
|
|
3895
4073
|
}
|
|
3896
|
-
}
|
|
4074
|
+
},
|
|
3897
4075
|
setLastErrorDetails: (details) => set((state) => {
|
|
3898
4076
|
state.lastErrorDetails = details;
|
|
3899
4077
|
state.lastError = details === null ? null : summarizeCliError(details);
|
|
@@ -3916,38 +4094,73 @@ var useServiceStore = create2()(immer2((set, get) => ({
|
|
|
3916
4094
|
}, MAX_ALERTS);
|
|
3917
4095
|
})
|
|
3918
4096
|
})));
|
|
4097
|
+
scheduledReconnectTick = async () => {
|
|
4098
|
+
const status = useServiceStore.getState().connectionStatus;
|
|
4099
|
+
if (status === "reconnecting" || status === "polling") {
|
|
4100
|
+
await useServiceStore.getState().fetchWorkers();
|
|
4101
|
+
}
|
|
4102
|
+
};
|
|
3919
4103
|
|
|
3920
4104
|
// src/stores/config-store.ts
|
|
3921
4105
|
import { create as create3 } from "zustand";
|
|
3922
4106
|
import { immer as immer3 } from "zustand/middleware/immer";
|
|
3923
4107
|
import { persist, createJSONStorage } from "zustand/middleware";
|
|
3924
|
-
import { chmodSync as
|
|
3925
|
-
import { homedir as homedir3 } from "os";
|
|
4108
|
+
import { chmodSync as chmodSync3, mkdirSync as mkdirSync3, existsSync as existsSync4, readFileSync as readFileSync4 } from "fs";
|
|
3926
4109
|
import { join as join4 } from "path";
|
|
4110
|
+
function getTuiPreferencesPath() {
|
|
4111
|
+
return join4(getHooxHome(), ".tui-state", "preferences.json");
|
|
4112
|
+
}
|
|
4113
|
+
function getLegacyConfigJsonPath() {
|
|
4114
|
+
return join4(getHooxHome(), "config.json");
|
|
4115
|
+
}
|
|
4116
|
+
function extractZustandPrefsPayload(raw) {
|
|
4117
|
+
try {
|
|
4118
|
+
const parsed = JSON.parse(raw);
|
|
4119
|
+
if (parsed && typeof parsed === "object" && parsed.state && typeof parsed.state === "object" && !Array.isArray(parsed.state) && (("theme" in parsed.state) || ("refreshIntervalMs" in parsed.state)) && !("apiToken" in parsed)) {
|
|
4120
|
+
return raw;
|
|
4121
|
+
}
|
|
4122
|
+
} catch {}
|
|
4123
|
+
return null;
|
|
4124
|
+
}
|
|
3927
4125
|
var bunConfigStorage = {
|
|
3928
4126
|
getItem: async (_name) => {
|
|
3929
4127
|
try {
|
|
3930
|
-
const
|
|
3931
|
-
const
|
|
3932
|
-
if (
|
|
3933
|
-
return
|
|
3934
|
-
|
|
4128
|
+
const prefsPath = getTuiPreferencesPath();
|
|
4129
|
+
const prefsFile = Bun.file(prefsPath);
|
|
4130
|
+
if (await prefsFile.exists()) {
|
|
4131
|
+
return await prefsFile.text();
|
|
4132
|
+
}
|
|
4133
|
+
const legacyPath = getLegacyConfigJsonPath();
|
|
4134
|
+
if (existsSync4(legacyPath)) {
|
|
4135
|
+
const legacyRaw = readFileSync4(legacyPath, "utf-8");
|
|
4136
|
+
const envelope = extractZustandPrefsPayload(legacyRaw);
|
|
4137
|
+
if (envelope) {
|
|
4138
|
+
await bunConfigStorage.setItem(_name, envelope);
|
|
4139
|
+
return envelope;
|
|
4140
|
+
}
|
|
4141
|
+
}
|
|
4142
|
+
return null;
|
|
3935
4143
|
} catch {
|
|
3936
4144
|
return null;
|
|
3937
4145
|
}
|
|
3938
4146
|
},
|
|
3939
4147
|
setItem: async (_name, value) => {
|
|
3940
|
-
const
|
|
3941
|
-
|
|
3942
|
-
|
|
4148
|
+
const home = getHooxHome();
|
|
4149
|
+
const stateDir = join4(home, ".tui-state");
|
|
4150
|
+
if (!existsSync4(home)) {
|
|
4151
|
+
mkdirSync3(home, { recursive: true, mode: HOOX_DIR_MODE });
|
|
4152
|
+
}
|
|
4153
|
+
if (!existsSync4(stateDir)) {
|
|
4154
|
+
mkdirSync3(stateDir, { recursive: true, mode: HOOX_DIR_MODE });
|
|
3943
4155
|
}
|
|
3944
4156
|
try {
|
|
3945
|
-
|
|
4157
|
+
chmodSync3(home, HOOX_DIR_MODE);
|
|
4158
|
+
chmodSync3(stateDir, HOOX_DIR_MODE);
|
|
3946
4159
|
} catch {}
|
|
3947
|
-
const filePath =
|
|
4160
|
+
const filePath = getTuiPreferencesPath();
|
|
3948
4161
|
await Bun.write(filePath, value);
|
|
3949
4162
|
try {
|
|
3950
|
-
|
|
4163
|
+
chmodSync3(filePath, HOOX_CONFIG_FILE_MODE);
|
|
3951
4164
|
} catch {}
|
|
3952
4165
|
},
|
|
3953
4166
|
removeItem: async (_name) => {}
|
|
@@ -4019,7 +4232,7 @@ var useConfigStore = create3()(persist(immer3((set) => ({
|
|
|
4019
4232
|
state.notifications[channel] = !state.notifications[channel];
|
|
4020
4233
|
})
|
|
4021
4234
|
})), {
|
|
4022
|
-
name: "hoox-
|
|
4235
|
+
name: "hoox-tui-prefs",
|
|
4023
4236
|
storage: createJSONStorage(() => bunConfigStorage),
|
|
4024
4237
|
partialize: (state) => ({
|
|
4025
4238
|
theme: state.theme,
|
|
@@ -4068,6 +4281,7 @@ export {
|
|
|
4068
4281
|
resolveHooxRuntimeRoot,
|
|
4069
4282
|
resolveHooxPath,
|
|
4070
4283
|
resolveDependencies,
|
|
4284
|
+
rememberMonorepoRoot,
|
|
4071
4285
|
readConfigSync,
|
|
4072
4286
|
readConfig,
|
|
4073
4287
|
parseDashboardManifest,
|
|
@@ -4079,6 +4293,8 @@ export {
|
|
|
4079
4293
|
kvManifestFromDashboardManifests,
|
|
4080
4294
|
isWithinHooxHome,
|
|
4081
4295
|
isUnixModeGroupOrWorldAccessible,
|
|
4296
|
+
isTruthyKillSwitchFlag,
|
|
4297
|
+
isTradingPaused,
|
|
4082
4298
|
isHooxSetupRoot,
|
|
4083
4299
|
isDashboardSectionFlatKv,
|
|
4084
4300
|
isDashboardSectionEditable,
|
|
@@ -4090,6 +4306,8 @@ export {
|
|
|
4090
4306
|
headersToObject,
|
|
4091
4307
|
hasOperatorClientCredentials,
|
|
4092
4308
|
getTuiEntryCandidates,
|
|
4309
|
+
getRememberedMonorepoRoot,
|
|
4310
|
+
getRememberedMonorepoPath,
|
|
4093
4311
|
getRelativeHooxPath,
|
|
4094
4312
|
getHooxWranglerPath,
|
|
4095
4313
|
getHooxStatePath,
|
|
@@ -4137,6 +4355,7 @@ export {
|
|
|
4137
4355
|
createJsonResponse,
|
|
4138
4356
|
createErrorResponse,
|
|
4139
4357
|
createCronHandler,
|
|
4358
|
+
checkKillSwitch,
|
|
4140
4359
|
buildOperatorAuthHeaders,
|
|
4141
4360
|
buildDashboardKvKey,
|
|
4142
4361
|
authenticatedServiceFetch,
|
|
@@ -4163,6 +4382,8 @@ export {
|
|
|
4163
4382
|
PRESETS,
|
|
4164
4383
|
LogLevelColor,
|
|
4165
4384
|
KVKeys,
|
|
4385
|
+
KILL_SWITCH_KEYS,
|
|
4386
|
+
KILL_SWITCH_ACTIVE_PREFIX,
|
|
4166
4387
|
InternalAuthKeyFields,
|
|
4167
4388
|
INTEGRATIONS,
|
|
4168
4389
|
HOOX_DIR_MODE,
|