@hoox-sh/hoox-tui 0.3.1 → 0.4.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/main.js +1400 -2764
- package/package.json +3 -8
- package/src/app.tsx +17 -15
- package/src/components/shared/shared.test.tsx +2 -2
- package/src/components/ui/connection-toasts.ts +6 -0
- package/src/components/ui/dialog-state.ts +17 -0
- package/src/components/ui/dialog.tsx +434 -172
- package/src/components/views/ai-chat.tsx +6 -1
- package/src/components/views/config-editor/code-editor.tsx +8 -6
- package/src/components/views/config-editor.test.tsx +20 -17
- package/src/components/views/config-editor.tsx +8 -6
- package/src/components/views/dashboard/model-health-section.tsx +38 -46
- package/src/components/views/dashboard/pyne-health-section.tsx +36 -41
- package/src/components/views/dashboard.tsx +25 -28
- package/src/components/views/kv-viewer.test.tsx +4 -16
- package/src/components/views/kv-viewer.tsx +9 -13
- package/src/components/views/logs-viewer.test.tsx +4 -4
- package/src/components/views/queue-depth.test.tsx +5 -7
- package/src/components/views/queue-depth.tsx +10 -14
- package/src/components/views/secrets-viewer.test.tsx +1 -1
- package/src/components/views/secrets-viewer.tsx +11 -15
- package/src/components/views/service-manager.test.tsx +8 -27
- package/src/components/views/service-manager.tsx +1 -0
- package/src/components/views/settings.test.tsx +2 -7
- package/src/components/views/settings.tsx +43 -60
- package/src/components/views/setup-wizard.test.tsx +12 -14
- package/src/components/views/setup-wizard.tsx +61 -59
- package/src/components/views/worker-detail.test.tsx +2 -2
- package/src/components/views/worker-settings.tsx +6 -6
- package/src/components/views/workers-overview.tsx +1 -1
- package/src/hooks/hooks.test.ts +10 -174
- package/src/hooks/index.ts +1 -3
- package/src/hooks/renderer-ref.ts +1 -0
- package/src/hooks/shell-overlay.ts +3 -2
- package/src/hooks/use-polling.ts +12 -0
- package/src/services/cli-bridge/index.ts +56 -12
- package/src/services/cli-bridge/standalone.ts +4 -1
- package/src/services/cli-bridge/types.ts +6 -9
- package/src/services/cli-bridge.test.ts +20 -4
- package/src/services/clipboard.ts +2 -2
- package/src/stores/service-store.test.ts +29 -26
- package/src/stores/session-restore.test.ts +2 -0
- package/src/test-setup.ts +5 -13
- package/src/test-utils.ts +4 -24
- package/src/types.ts +9 -47
- package/src/utils/colors.test.ts +8 -3
- package/src/view-registry.test.ts +2 -19
- package/src/view-registry.tsx +7 -20
- package/src/components/shared/animated-border.tsx +0 -58
- package/src/components/shared/keybinding-hint.tsx +0 -37
- package/src/components/ui/select.tsx +0 -197
- package/src/hooks/use-keyboard.ts +0 -130
- package/src/hooks/use-service-data.ts +0 -35
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hoox-sh/hoox-tui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Hoox algorithmic trading terminal operations center — OpenTUI dashboard",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/main.js",
|
|
@@ -32,8 +32,7 @@
|
|
|
32
32
|
"prepublishOnly": "bun run typecheck && bun run build"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@hoox-sh/hoox-shared": "^1.
|
|
36
|
-
"@opentui-ui/dialog": "^0.1.2",
|
|
35
|
+
"@hoox-sh/hoox-shared": "^1.6.0",
|
|
37
36
|
"@opentui/core": "0.5.1",
|
|
38
37
|
"@opentui/react": "0.5.1",
|
|
39
38
|
"immer": "^11.1.8",
|
|
@@ -41,12 +40,8 @@
|
|
|
41
40
|
"smol-toml": "^1.6.1",
|
|
42
41
|
"zustand": "^5.0.0"
|
|
43
42
|
},
|
|
44
|
-
"overrides": {
|
|
45
|
-
"@opentui/core": "0.5.1",
|
|
46
|
-
"@opentui/react": "0.5.1"
|
|
47
|
-
},
|
|
48
43
|
"devDependencies": {
|
|
49
|
-
"@cloudflare/workers-types": "^5.
|
|
44
|
+
"@cloudflare/workers-types": "^5.20261001.1",
|
|
50
45
|
"@hoox/test-utils": "^0.0.1",
|
|
51
46
|
"@types/bun": "latest",
|
|
52
47
|
"typescript": "^6.0.3"
|
package/src/app.tsx
CHANGED
|
@@ -20,8 +20,12 @@
|
|
|
20
20
|
*/
|
|
21
21
|
import { useState, useEffect, useCallback } from "react";
|
|
22
22
|
import { useKeyboard } from "@opentui/react";
|
|
23
|
-
import {
|
|
24
|
-
|
|
23
|
+
import {
|
|
24
|
+
useServiceStore,
|
|
25
|
+
useUIStore,
|
|
26
|
+
useConfigStore,
|
|
27
|
+
Colors,
|
|
28
|
+
} from "@hoox-sh/hoox-shared";
|
|
25
29
|
import { restoreSession, saveSession } from "@hoox-sh/hoox-shared";
|
|
26
30
|
import type { ViewId } from "@hoox-sh/hoox-shared";
|
|
27
31
|
|
|
@@ -42,7 +46,7 @@ import {
|
|
|
42
46
|
toastReconnectedMode,
|
|
43
47
|
} from "./components/ui/connection-toasts";
|
|
44
48
|
import { getRendererRef } from "./hooks";
|
|
45
|
-
import
|
|
49
|
+
import { DialogProvider, useDialog } from "./components/ui/dialog";
|
|
46
50
|
import {
|
|
47
51
|
getViewFactory,
|
|
48
52
|
getViewShortcutMap,
|
|
@@ -95,19 +99,14 @@ function quitApp(): void {
|
|
|
95
99
|
*/
|
|
96
100
|
export function AppRoot({ safeMode = false }: { safeMode?: boolean }) {
|
|
97
101
|
return (
|
|
98
|
-
<DialogProvider
|
|
99
|
-
size="medium"
|
|
100
|
-
backdropColor={Colors.backdrop}
|
|
101
|
-
backdropOpacity={0.35}
|
|
102
|
-
>
|
|
102
|
+
<DialogProvider>
|
|
103
103
|
<AppRootInner safeMode={safeMode} />
|
|
104
104
|
</DialogProvider>
|
|
105
105
|
);
|
|
106
106
|
}
|
|
107
107
|
|
|
108
108
|
function AppRootInner({ safeMode = false }: { safeMode?: boolean }) {
|
|
109
|
-
|
|
110
|
-
const dialog = useDialog() as unknown as DialogHandle;
|
|
109
|
+
const dialog = useDialog();
|
|
111
110
|
const [restoring, setRestoring] = useState(true);
|
|
112
111
|
const activeView = useUIStore((s) => s.activeView);
|
|
113
112
|
const commandPaletteOpen = useUIStore((s) => s.commandPaletteOpen);
|
|
@@ -134,11 +133,15 @@ function AppRootInner({ safeMode = false }: { safeMode?: boolean }) {
|
|
|
134
133
|
// Shared restoreSession validates all 16 ViewIds (unknown → dashboard).
|
|
135
134
|
useEffect(() => {
|
|
136
135
|
let cancelled = false;
|
|
137
|
-
(async () => {
|
|
136
|
+
void (async () => {
|
|
138
137
|
const session = await restoreSession();
|
|
139
138
|
if (cancelled) return;
|
|
140
139
|
|
|
141
|
-
const
|
|
140
|
+
const preferred = useConfigStore.getState().defaultView;
|
|
141
|
+
const view: ViewId =
|
|
142
|
+
!session.fromDisk && isRegisteredViewId(preferred)
|
|
143
|
+
? preferred
|
|
144
|
+
: session.activeView;
|
|
142
145
|
const expanded = session.sidebarExpanded;
|
|
143
146
|
|
|
144
147
|
if (isRegisteredViewId(view)) {
|
|
@@ -172,7 +175,7 @@ function AppRootInner({ safeMode = false }: { safeMode?: boolean }) {
|
|
|
172
175
|
}
|
|
173
176
|
let cancelled = false;
|
|
174
177
|
|
|
175
|
-
(async () => {
|
|
178
|
+
void (async () => {
|
|
176
179
|
const store = useServiceStore.getState();
|
|
177
180
|
const conn = resolveTuiConnectionEnv();
|
|
178
181
|
await tuiDevLog.info("connection", "startup data load begin", {
|
|
@@ -230,8 +233,7 @@ function AppRootInner({ safeMode = false }: { safeMode?: boolean }) {
|
|
|
230
233
|
if (result.success && result.data) {
|
|
231
234
|
const raw = result.data as Record<string, unknown>;
|
|
232
235
|
const rawWorkers = (raw.workers ?? raw.status ?? raw) as
|
|
233
|
-
| unknown
|
|
234
|
-
| Record<string, unknown>;
|
|
236
|
+
unknown[] | Record<string, unknown>;
|
|
235
237
|
const parsed = Array.isArray(rawWorkers)
|
|
236
238
|
? rawWorkers
|
|
237
239
|
: typeof rawWorkers === "object" && rawWorkers !== null
|
|
@@ -395,13 +395,13 @@ describe("Shared Components", () => {
|
|
|
395
395
|
it("filters to matching commands", () => {
|
|
396
396
|
const result = filterCommands(SAMPLE_COMMANDS, "dash");
|
|
397
397
|
expect(result.length).toBe(1);
|
|
398
|
-
expect(result[0]
|
|
398
|
+
expect(result[0]?.name).toBe("Dashboard");
|
|
399
399
|
});
|
|
400
400
|
|
|
401
401
|
it("sorts by score (best match first)", () => {
|
|
402
402
|
const result = filterCommands(SAMPLE_COMMANDS, "theme");
|
|
403
403
|
expect(result.length).toBe(2);
|
|
404
|
-
expect(result[0]
|
|
404
|
+
expect(result[0]?.name).toBe("Dark Theme"); // or Light Theme
|
|
405
405
|
});
|
|
406
406
|
|
|
407
407
|
it("deduplicates by id", () => {
|
|
@@ -17,16 +17,19 @@ import { remoteAuthMissingHint } from "../../services/tui-connection";
|
|
|
17
17
|
|
|
18
18
|
// ─── Pure message builders (testable without toast side effects) ─────────────
|
|
19
19
|
|
|
20
|
+
/** Status-bar toast copy for a successful LOCAL/REMOTE connect. */
|
|
20
21
|
export function messageConnected(mode: TuiMode, host: string): string {
|
|
21
22
|
const label = mode === "remote" ? "REMOTE" : "LOCAL";
|
|
22
23
|
return `Connected · ${label} · ${host}`;
|
|
23
24
|
}
|
|
24
25
|
|
|
26
|
+
/** Status-bar toast copy when the LOCAL/REMOTE session drops. */
|
|
25
27
|
export function messageConnectionLost(mode: TuiMode, host: string): string {
|
|
26
28
|
const label = mode === "remote" ? "REMOTE" : "LOCAL";
|
|
27
29
|
return `Connection lost · ${label} · ${host}`;
|
|
28
30
|
}
|
|
29
31
|
|
|
32
|
+
/** Status-bar toast copy after a reconnect, including downtime. */
|
|
30
33
|
export function messageReconnected(
|
|
31
34
|
mode: TuiMode,
|
|
32
35
|
host: string,
|
|
@@ -38,15 +41,18 @@ export function messageReconnected(
|
|
|
38
41
|
return `Reconnected · ${label} · ${host} · ${duration} downtime`;
|
|
39
42
|
}
|
|
40
43
|
|
|
44
|
+
/** Status-bar toast copy when auth is rejected. */
|
|
41
45
|
export function messageAuthRequired(mode: TuiMode, host: string): string {
|
|
42
46
|
const label = mode === "remote" ? "REMOTE" : "LOCAL";
|
|
43
47
|
return `Auth failed · ${label} · ${host}`;
|
|
44
48
|
}
|
|
45
49
|
|
|
50
|
+
/** Status-bar toast copy when remote mode has no API credentials. */
|
|
46
51
|
export function messageAuthMissing(host: string): string {
|
|
47
52
|
return `No API credentials · REMOTE · ${host}`;
|
|
48
53
|
}
|
|
49
54
|
|
|
55
|
+
/** Status-bar toast copy when the TUI starts without a live connection. */
|
|
50
56
|
export function messageOfflineStartup(
|
|
51
57
|
mode: TuiMode,
|
|
52
58
|
host: string,
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2026 HOOX · HOOX · jango-blockchained (hoox-sh)
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/** Module-level open count for DialogProvider (avoids React store cycles). */
|
|
7
|
+
let openDialogCount = 0;
|
|
8
|
+
|
|
9
|
+
/** Record how many Hoox dialogs are currently open (shell overlay gate). */
|
|
10
|
+
export function setOpenDialogCount(n: number): void {
|
|
11
|
+
openDialogCount = Math.max(0, n);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/** True when any in-house dialog owns the keyboard. */
|
|
15
|
+
export function isHooxDialogOpen(): boolean {
|
|
16
|
+
return openDialogCount > 0;
|
|
17
|
+
}
|