@hoox-sh/hoox-tui 0.3.1 → 0.3.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/dist/main.js +586 -285
- package/package.json +1 -6
- package/src/app.tsx +7 -9
- package/src/components/ui/dialog-state.ts +15 -0
- package/src/components/ui/dialog.tsx +447 -172
- package/src/components/ui/select.tsx +10 -158
- package/src/components/views/service-manager.test.tsx +8 -27
- package/src/hooks/shell-overlay.ts +3 -2
package/dist/main.js
CHANGED
|
@@ -4316,9 +4316,8 @@ import { createRoot } from "@opentui/react";
|
|
|
4316
4316
|
// src/app.tsx
|
|
4317
4317
|
init_src();
|
|
4318
4318
|
init_src();
|
|
4319
|
-
import { useState as useState23, useEffect as
|
|
4320
|
-
import { useKeyboard as
|
|
4321
|
-
import { DialogProvider, useDialog } from "@opentui-ui/dialog/react";
|
|
4319
|
+
import { useState as useState23, useEffect as useEffect25, useCallback as useCallback18 } from "react";
|
|
4320
|
+
import { useKeyboard as useKeyboard8 } from "@opentui/react";
|
|
4322
4321
|
|
|
4323
4322
|
// src/services/cli-bridge/index.ts
|
|
4324
4323
|
init_src();
|
|
@@ -5888,9 +5887,20 @@ init_src();
|
|
|
5888
5887
|
// src/hooks/shell-overlay.ts
|
|
5889
5888
|
init_src();
|
|
5890
5889
|
import { useKeyboard } from "@opentui/react";
|
|
5890
|
+
|
|
5891
|
+
// src/components/ui/dialog-state.ts
|
|
5892
|
+
var openDialogCount = 0;
|
|
5893
|
+
function setOpenDialogCount(n) {
|
|
5894
|
+
openDialogCount = Math.max(0, n);
|
|
5895
|
+
}
|
|
5896
|
+
function isHooxDialogOpen() {
|
|
5897
|
+
return openDialogCount > 0;
|
|
5898
|
+
}
|
|
5899
|
+
|
|
5900
|
+
// src/hooks/shell-overlay.ts
|
|
5891
5901
|
function isShellOverlayOpen() {
|
|
5892
5902
|
const s = useUIStore.getState();
|
|
5893
|
-
return Boolean(s.commandPaletteOpen || s.modal);
|
|
5903
|
+
return Boolean(s.commandPaletteOpen || s.modal || isHooxDialogOpen());
|
|
5894
5904
|
}
|
|
5895
5905
|
function useViewKeyboard(handler) {
|
|
5896
5906
|
useKeyboard((key) => {
|
|
@@ -5899,15 +5909,365 @@ function useViewKeyboard(handler) {
|
|
|
5899
5909
|
handler(key);
|
|
5900
5910
|
});
|
|
5901
5911
|
}
|
|
5912
|
+
// src/components/ui/dialog.tsx
|
|
5913
|
+
init_src();
|
|
5914
|
+
import {
|
|
5915
|
+
createContext,
|
|
5916
|
+
useCallback,
|
|
5917
|
+
useContext,
|
|
5918
|
+
useEffect as useEffect3,
|
|
5919
|
+
useMemo,
|
|
5920
|
+
useState
|
|
5921
|
+
} from "react";
|
|
5922
|
+
import { useKeyboard as useKeyboard3 } from "@opentui/react";
|
|
5923
|
+
import { jsxDEV } from "@opentui/react/jsx-dev-runtime";
|
|
5924
|
+
var nextId2 = 1;
|
|
5925
|
+
var DialogCtx = createContext(null);
|
|
5926
|
+
function ConfirmOverlay({
|
|
5927
|
+
entry,
|
|
5928
|
+
onResolve
|
|
5929
|
+
}) {
|
|
5930
|
+
useKeyboard3((key) => {
|
|
5931
|
+
const name = String(key.name ?? "").toLowerCase();
|
|
5932
|
+
if (name === "return" || name === "enter" || name === "y") {
|
|
5933
|
+
onResolve(true);
|
|
5934
|
+
return;
|
|
5935
|
+
}
|
|
5936
|
+
if (name === "escape" || name === "n") {
|
|
5937
|
+
onResolve(false);
|
|
5938
|
+
}
|
|
5939
|
+
});
|
|
5940
|
+
return /* @__PURE__ */ jsxDEV("box", {
|
|
5941
|
+
position: "absolute",
|
|
5942
|
+
left: 0,
|
|
5943
|
+
top: 0,
|
|
5944
|
+
width: "100%",
|
|
5945
|
+
height: "100%",
|
|
5946
|
+
justifyContent: "center",
|
|
5947
|
+
alignItems: "center",
|
|
5948
|
+
backgroundColor: Colors.backdrop,
|
|
5949
|
+
onMouseUp: entry.closeOnClickOutside ? () => onResolve(false) : undefined,
|
|
5950
|
+
children: /* @__PURE__ */ jsxDEV("box", {
|
|
5951
|
+
flexDirection: "column",
|
|
5952
|
+
gap: 1,
|
|
5953
|
+
padding: 2,
|
|
5954
|
+
border: true,
|
|
5955
|
+
borderStyle: "double",
|
|
5956
|
+
borderColor: Colors.accent,
|
|
5957
|
+
backgroundColor: Colors.card,
|
|
5958
|
+
minWidth: 44,
|
|
5959
|
+
onMouseUp: (e) => {
|
|
5960
|
+
e?.stopPropagation?.();
|
|
5961
|
+
},
|
|
5962
|
+
children: [
|
|
5963
|
+
/* @__PURE__ */ jsxDEV("text", {
|
|
5964
|
+
fg: Colors.accent,
|
|
5965
|
+
bold: true,
|
|
5966
|
+
children: entry.title
|
|
5967
|
+
}, undefined, false, undefined, this),
|
|
5968
|
+
/* @__PURE__ */ jsxDEV("text", {
|
|
5969
|
+
fg: Colors.foreground,
|
|
5970
|
+
children: entry.message
|
|
5971
|
+
}, undefined, false, undefined, this),
|
|
5972
|
+
/* @__PURE__ */ jsxDEV("box", {
|
|
5973
|
+
flexDirection: "row",
|
|
5974
|
+
gap: 2,
|
|
5975
|
+
paddingTop: 1,
|
|
5976
|
+
children: [
|
|
5977
|
+
/* @__PURE__ */ jsxDEV("text", {
|
|
5978
|
+
fg: Colors.accent,
|
|
5979
|
+
bg: Colors.card,
|
|
5980
|
+
bold: true,
|
|
5981
|
+
onMouseUp: () => onResolve(true),
|
|
5982
|
+
children: ` [Y/Enter] ${entry.confirmLabel} `
|
|
5983
|
+
}, undefined, false, undefined, this),
|
|
5984
|
+
/* @__PURE__ */ jsxDEV("text", {
|
|
5985
|
+
fg: Colors.muted,
|
|
5986
|
+
onMouseUp: () => onResolve(false),
|
|
5987
|
+
children: ` [N/Esc] ${entry.cancelLabel} `
|
|
5988
|
+
}, undefined, false, undefined, this)
|
|
5989
|
+
]
|
|
5990
|
+
}, undefined, true, undefined, this)
|
|
5991
|
+
]
|
|
5992
|
+
}, undefined, true, undefined, this)
|
|
5993
|
+
}, undefined, false, undefined, this);
|
|
5994
|
+
}
|
|
5995
|
+
function ChoiceOverlay({
|
|
5996
|
+
entry,
|
|
5997
|
+
onResolve
|
|
5998
|
+
}) {
|
|
5999
|
+
const [selectedIndex, setSelectedIndex] = useState(0);
|
|
6000
|
+
useKeyboard3((key) => {
|
|
6001
|
+
const name = String(key.name ?? "").toLowerCase();
|
|
6002
|
+
if (name === "down" || name === "j") {
|
|
6003
|
+
setSelectedIndex((prev) => prev < entry.choices.length - 1 ? prev + 1 : 0);
|
|
6004
|
+
return;
|
|
6005
|
+
}
|
|
6006
|
+
if (name === "up" || name === "k") {
|
|
6007
|
+
setSelectedIndex((prev) => prev > 0 ? prev - 1 : entry.choices.length - 1);
|
|
6008
|
+
return;
|
|
6009
|
+
}
|
|
6010
|
+
if (name === "return" || name === "enter") {
|
|
6011
|
+
const choice = entry.choices[selectedIndex];
|
|
6012
|
+
if (choice)
|
|
6013
|
+
onResolve(choice.key);
|
|
6014
|
+
return;
|
|
6015
|
+
}
|
|
6016
|
+
if (name === "escape") {
|
|
6017
|
+
onResolve(entry.fallback);
|
|
6018
|
+
}
|
|
6019
|
+
});
|
|
6020
|
+
return /* @__PURE__ */ jsxDEV("box", {
|
|
6021
|
+
position: "absolute",
|
|
6022
|
+
left: 0,
|
|
6023
|
+
top: 0,
|
|
6024
|
+
width: "100%",
|
|
6025
|
+
height: "100%",
|
|
6026
|
+
justifyContent: "center",
|
|
6027
|
+
alignItems: "center",
|
|
6028
|
+
backgroundColor: Colors.backdrop,
|
|
6029
|
+
onMouseUp: entry.closeOnClickOutside ? () => onResolve(entry.fallback) : undefined,
|
|
6030
|
+
children: /* @__PURE__ */ jsxDEV("box", {
|
|
6031
|
+
flexDirection: "column",
|
|
6032
|
+
gap: 1,
|
|
6033
|
+
padding: 2,
|
|
6034
|
+
border: true,
|
|
6035
|
+
borderStyle: "double",
|
|
6036
|
+
borderColor: Colors.accent,
|
|
6037
|
+
backgroundColor: Colors.card,
|
|
6038
|
+
minWidth: 48,
|
|
6039
|
+
children: [
|
|
6040
|
+
/* @__PURE__ */ jsxDEV("text", {
|
|
6041
|
+
fg: Colors.accent,
|
|
6042
|
+
bold: true,
|
|
6043
|
+
children: entry.title
|
|
6044
|
+
}, undefined, false, undefined, this),
|
|
6045
|
+
/* @__PURE__ */ jsxDEV("text", {
|
|
6046
|
+
dim: true,
|
|
6047
|
+
fg: Colors.muted,
|
|
6048
|
+
children: "Use \u2191\u2193 to navigate, Enter to select, Esc to cancel"
|
|
6049
|
+
}, undefined, false, undefined, this),
|
|
6050
|
+
/* @__PURE__ */ jsxDEV("box", {
|
|
6051
|
+
flexDirection: "column",
|
|
6052
|
+
gap: 0,
|
|
6053
|
+
paddingTop: 1,
|
|
6054
|
+
children: entry.choices.map((choice, idx) => /* @__PURE__ */ jsxDEV("box", {
|
|
6055
|
+
flexDirection: "row",
|
|
6056
|
+
gap: 2,
|
|
6057
|
+
paddingLeft: 1,
|
|
6058
|
+
paddingRight: 1,
|
|
6059
|
+
children: [
|
|
6060
|
+
/* @__PURE__ */ jsxDEV("text", {
|
|
6061
|
+
fg: idx === selectedIndex ? Colors.accent : Colors.muted,
|
|
6062
|
+
children: idx === selectedIndex ? "\u25B6" : " "
|
|
6063
|
+
}, undefined, false, undefined, this),
|
|
6064
|
+
/* @__PURE__ */ jsxDEV("text", {
|
|
6065
|
+
fg: idx === selectedIndex ? Colors.foreground : Colors.muted,
|
|
6066
|
+
bg: idx === selectedIndex ? Colors.card : undefined,
|
|
6067
|
+
onMouseUp: () => onResolve(choice.key),
|
|
6068
|
+
children: choice.label
|
|
6069
|
+
}, undefined, false, undefined, this),
|
|
6070
|
+
choice.description ? /* @__PURE__ */ jsxDEV("text", {
|
|
6071
|
+
dim: true,
|
|
6072
|
+
fg: Colors.muted,
|
|
6073
|
+
children: [
|
|
6074
|
+
"\u2014 ",
|
|
6075
|
+
choice.description
|
|
6076
|
+
]
|
|
6077
|
+
}, undefined, true, undefined, this) : null
|
|
6078
|
+
]
|
|
6079
|
+
}, choice.key, true, undefined, this))
|
|
6080
|
+
}, undefined, false, undefined, this),
|
|
6081
|
+
/* @__PURE__ */ jsxDEV("box", {
|
|
6082
|
+
flexDirection: "row",
|
|
6083
|
+
justifyContent: "flex-end",
|
|
6084
|
+
paddingTop: 1,
|
|
6085
|
+
children: /* @__PURE__ */ jsxDEV("text", {
|
|
6086
|
+
fg: Colors.muted,
|
|
6087
|
+
onMouseUp: () => onResolve(entry.fallback),
|
|
6088
|
+
children: " Cancel "
|
|
6089
|
+
}, undefined, false, undefined, this)
|
|
6090
|
+
}, undefined, false, undefined, this)
|
|
6091
|
+
]
|
|
6092
|
+
}, undefined, true, undefined, this)
|
|
6093
|
+
}, undefined, false, undefined, this);
|
|
6094
|
+
}
|
|
6095
|
+
function LoadingOverlay({ message }) {
|
|
6096
|
+
return /* @__PURE__ */ jsxDEV("box", {
|
|
6097
|
+
position: "absolute",
|
|
6098
|
+
left: 0,
|
|
6099
|
+
top: 0,
|
|
6100
|
+
width: "100%",
|
|
6101
|
+
height: "100%",
|
|
6102
|
+
justifyContent: "center",
|
|
6103
|
+
alignItems: "center",
|
|
6104
|
+
backgroundColor: Colors.backdrop,
|
|
6105
|
+
children: /* @__PURE__ */ jsxDEV("box", {
|
|
6106
|
+
flexDirection: "column",
|
|
6107
|
+
padding: 2,
|
|
6108
|
+
gap: 1,
|
|
6109
|
+
border: true,
|
|
6110
|
+
borderStyle: "single",
|
|
6111
|
+
borderColor: Colors.border,
|
|
6112
|
+
backgroundColor: Colors.card,
|
|
6113
|
+
justifyContent: "center",
|
|
6114
|
+
alignItems: "center",
|
|
6115
|
+
children: [
|
|
6116
|
+
/* @__PURE__ */ jsxDEV("text", {
|
|
6117
|
+
fg: Colors.accent,
|
|
6118
|
+
children: message
|
|
6119
|
+
}, undefined, false, undefined, this),
|
|
6120
|
+
/* @__PURE__ */ jsxDEV("text", {
|
|
6121
|
+
dim: true,
|
|
6122
|
+
fg: Colors.muted,
|
|
6123
|
+
children: "Please wait..."
|
|
6124
|
+
}, undefined, false, undefined, this)
|
|
6125
|
+
]
|
|
6126
|
+
}, undefined, true, undefined, this)
|
|
6127
|
+
}, undefined, false, undefined, this);
|
|
6128
|
+
}
|
|
6129
|
+
function DialogProvider({ children }) {
|
|
6130
|
+
const [stack, setStack] = useState([]);
|
|
6131
|
+
useEffect3(() => {
|
|
6132
|
+
setOpenDialogCount(stack.length);
|
|
6133
|
+
return () => setOpenDialogCount(0);
|
|
6134
|
+
}, [stack.length]);
|
|
6135
|
+
const popId = useCallback((id) => {
|
|
6136
|
+
setStack((s) => s.filter((e) => e.id !== id));
|
|
6137
|
+
}, []);
|
|
6138
|
+
const handle = useMemo(() => {
|
|
6139
|
+
const confirmSimple = (options) => new Promise((resolve3) => {
|
|
6140
|
+
const id = nextId2++;
|
|
6141
|
+
setStack((s) => [
|
|
6142
|
+
...s,
|
|
6143
|
+
{
|
|
6144
|
+
kind: "confirm",
|
|
6145
|
+
id,
|
|
6146
|
+
title: options.title,
|
|
6147
|
+
message: options.message,
|
|
6148
|
+
confirmLabel: options.confirmLabel ?? "Confirm",
|
|
6149
|
+
cancelLabel: options.cancelLabel ?? "Cancel",
|
|
6150
|
+
closeOnClickOutside: options.closeOnClickOutside ?? true,
|
|
6151
|
+
resolve: (value) => {
|
|
6152
|
+
popId(id);
|
|
6153
|
+
resolve3(value);
|
|
6154
|
+
}
|
|
6155
|
+
}
|
|
6156
|
+
]);
|
|
6157
|
+
});
|
|
6158
|
+
const choiceSimple = (options) => new Promise((resolve3) => {
|
|
6159
|
+
const id = nextId2++;
|
|
6160
|
+
setStack((s) => [
|
|
6161
|
+
...s,
|
|
6162
|
+
{
|
|
6163
|
+
kind: "choice",
|
|
6164
|
+
id,
|
|
6165
|
+
title: options.title,
|
|
6166
|
+
choices: options.choices,
|
|
6167
|
+
fallback: options.fallback,
|
|
6168
|
+
closeOnClickOutside: options.closeOnClickOutside ?? true,
|
|
6169
|
+
resolve: (value) => {
|
|
6170
|
+
popId(id);
|
|
6171
|
+
resolve3(value);
|
|
6172
|
+
}
|
|
6173
|
+
}
|
|
6174
|
+
]);
|
|
6175
|
+
});
|
|
6176
|
+
return {
|
|
6177
|
+
confirmSimple,
|
|
6178
|
+
choiceSimple,
|
|
6179
|
+
confirm: (options) => {
|
|
6180
|
+
const title = options.title ?? (typeof options.content === "function" ? "Confirm" : "Confirm");
|
|
6181
|
+
const message = options.message ?? "Continue?";
|
|
6182
|
+
return confirmSimple({
|
|
6183
|
+
title,
|
|
6184
|
+
message,
|
|
6185
|
+
confirmLabel: options.confirmLabel,
|
|
6186
|
+
cancelLabel: options.cancelLabel,
|
|
6187
|
+
closeOnClickOutside: options.closeOnClickOutside
|
|
6188
|
+
});
|
|
6189
|
+
},
|
|
6190
|
+
choice: (options) => {
|
|
6191
|
+
return choiceSimple({
|
|
6192
|
+
title: options.title ?? "Select",
|
|
6193
|
+
choices: options.choices ?? [],
|
|
6194
|
+
fallback: options.fallback,
|
|
6195
|
+
closeOnClickOutside: options.closeOnClickOutside
|
|
6196
|
+
});
|
|
6197
|
+
},
|
|
6198
|
+
show: (options) => {
|
|
6199
|
+
const id = nextId2++;
|
|
6200
|
+
setStack((s) => [
|
|
6201
|
+
...s,
|
|
6202
|
+
{
|
|
6203
|
+
kind: "loading",
|
|
6204
|
+
id,
|
|
6205
|
+
message: options.message ?? "Loading\u2026"
|
|
6206
|
+
}
|
|
6207
|
+
]);
|
|
6208
|
+
return id;
|
|
6209
|
+
},
|
|
6210
|
+
close: (id) => {
|
|
6211
|
+
if (id == null) {
|
|
6212
|
+
setStack([]);
|
|
6213
|
+
return;
|
|
6214
|
+
}
|
|
6215
|
+
popId(Number(id));
|
|
6216
|
+
}
|
|
6217
|
+
};
|
|
6218
|
+
}, [popId]);
|
|
6219
|
+
const top = stack[stack.length - 1] ?? null;
|
|
6220
|
+
return /* @__PURE__ */ jsxDEV(DialogCtx.Provider, {
|
|
6221
|
+
value: handle,
|
|
6222
|
+
children: [
|
|
6223
|
+
children,
|
|
6224
|
+
top?.kind === "confirm" ? /* @__PURE__ */ jsxDEV(ConfirmOverlay, {
|
|
6225
|
+
entry: top,
|
|
6226
|
+
onResolve: (v) => {
|
|
6227
|
+
top.resolve(v);
|
|
6228
|
+
}
|
|
6229
|
+
}, undefined, false, undefined, this) : null,
|
|
6230
|
+
top?.kind === "choice" ? /* @__PURE__ */ jsxDEV(ChoiceOverlay, {
|
|
6231
|
+
entry: top,
|
|
6232
|
+
onResolve: (v) => {
|
|
6233
|
+
top.resolve(v);
|
|
6234
|
+
}
|
|
6235
|
+
}, undefined, false, undefined, this) : null,
|
|
6236
|
+
top?.kind === "loading" ? /* @__PURE__ */ jsxDEV(LoadingOverlay, {
|
|
6237
|
+
message: top.message
|
|
6238
|
+
}, undefined, false, undefined, this) : null
|
|
6239
|
+
]
|
|
6240
|
+
}, undefined, true, undefined, this);
|
|
6241
|
+
}
|
|
6242
|
+
function useDialog() {
|
|
6243
|
+
const ctx = useContext(DialogCtx);
|
|
6244
|
+
if (!ctx) {
|
|
6245
|
+
throw new Error("useDialog must be used within <DialogProvider>");
|
|
6246
|
+
}
|
|
6247
|
+
return ctx;
|
|
6248
|
+
}
|
|
6249
|
+
async function showConfirm(dialog, options) {
|
|
6250
|
+
if (typeof dialog.confirmSimple === "function") {
|
|
6251
|
+
return dialog.confirmSimple(options);
|
|
6252
|
+
}
|
|
6253
|
+
return dialog.confirm({
|
|
6254
|
+
title: options.title,
|
|
6255
|
+
message: options.message,
|
|
6256
|
+
confirmLabel: options.confirmLabel,
|
|
6257
|
+
cancelLabel: options.cancelLabel,
|
|
6258
|
+
closeOnClickOutside: options.closeOnClickOutside
|
|
6259
|
+
});
|
|
6260
|
+
}
|
|
6261
|
+
|
|
5902
6262
|
// src/components/views/dashboard.tsx
|
|
5903
6263
|
init_src();
|
|
5904
|
-
import { useEffect as
|
|
6264
|
+
import { useEffect as useEffect8, useMemo as useMemo4, useState as useState6, useCallback as useCallback3, useRef as useRef3 } from "react";
|
|
5905
6265
|
|
|
5906
6266
|
// src/components/shared/error-boundary.tsx
|
|
5907
6267
|
init_src();
|
|
5908
6268
|
import { Component } from "react";
|
|
5909
|
-
import { useKeyboard as
|
|
5910
|
-
import { jsxDEV } from "@opentui/react/jsx-dev-runtime";
|
|
6269
|
+
import { useKeyboard as useKeyboard4 } from "@opentui/react";
|
|
6270
|
+
import { jsxDEV as jsxDEV2 } from "@opentui/react/jsx-dev-runtime";
|
|
5911
6271
|
function formatBoundaryErrorMessage(error, maxLen = 160) {
|
|
5912
6272
|
const first = (error.message || "Unknown error").split(`
|
|
5913
6273
|
`)[0] ?? "";
|
|
@@ -5919,13 +6279,13 @@ function ErrorRecoveryPanel({
|
|
|
5919
6279
|
message,
|
|
5920
6280
|
onRetry
|
|
5921
6281
|
}) {
|
|
5922
|
-
|
|
6282
|
+
useKeyboard4((key) => {
|
|
5923
6283
|
const name = String(key.name ?? "").toLowerCase();
|
|
5924
6284
|
if (name === "return" || name === "enter" || name === "r") {
|
|
5925
6285
|
onRetry();
|
|
5926
6286
|
}
|
|
5927
6287
|
});
|
|
5928
|
-
return /* @__PURE__ */
|
|
6288
|
+
return /* @__PURE__ */ jsxDEV2("box", {
|
|
5929
6289
|
flexDirection: "column",
|
|
5930
6290
|
padding: 2,
|
|
5931
6291
|
gap: 1,
|
|
@@ -5934,16 +6294,16 @@ function ErrorRecoveryPanel({
|
|
|
5934
6294
|
borderColor: Colors.border,
|
|
5935
6295
|
backgroundColor: Colors.card,
|
|
5936
6296
|
children: [
|
|
5937
|
-
/* @__PURE__ */
|
|
6297
|
+
/* @__PURE__ */ jsxDEV2("box", {
|
|
5938
6298
|
flexDirection: "row",
|
|
5939
6299
|
gap: 1,
|
|
5940
6300
|
children: [
|
|
5941
|
-
/* @__PURE__ */
|
|
6301
|
+
/* @__PURE__ */ jsxDEV2("text", {
|
|
5942
6302
|
fg: Colors.error,
|
|
5943
6303
|
bold: true,
|
|
5944
6304
|
children: "\u26A0"
|
|
5945
6305
|
}, undefined, false, undefined, this),
|
|
5946
|
-
/* @__PURE__ */
|
|
6306
|
+
/* @__PURE__ */ jsxDEV2("text", {
|
|
5947
6307
|
fg: Colors.error,
|
|
5948
6308
|
bold: true,
|
|
5949
6309
|
children: [
|
|
@@ -5953,22 +6313,22 @@ function ErrorRecoveryPanel({
|
|
|
5953
6313
|
}, undefined, true, undefined, this)
|
|
5954
6314
|
]
|
|
5955
6315
|
}, undefined, true, undefined, this),
|
|
5956
|
-
/* @__PURE__ */
|
|
6316
|
+
/* @__PURE__ */ jsxDEV2("text", {
|
|
5957
6317
|
fg: Colors.muted,
|
|
5958
6318
|
children: message
|
|
5959
6319
|
}, undefined, false, undefined, this),
|
|
5960
|
-
/* @__PURE__ */
|
|
6320
|
+
/* @__PURE__ */ jsxDEV2("box", {
|
|
5961
6321
|
paddingTop: 1,
|
|
5962
6322
|
flexDirection: "row",
|
|
5963
6323
|
gap: 2,
|
|
5964
6324
|
children: [
|
|
5965
|
-
/* @__PURE__ */
|
|
6325
|
+
/* @__PURE__ */ jsxDEV2("text", {
|
|
5966
6326
|
fg: Colors.accent,
|
|
5967
6327
|
bg: Colors.card,
|
|
5968
6328
|
onMouseUp: onRetry,
|
|
5969
6329
|
children: " [Retry] "
|
|
5970
6330
|
}, undefined, false, undefined, this),
|
|
5971
|
-
/* @__PURE__ */
|
|
6331
|
+
/* @__PURE__ */ jsxDEV2("text", {
|
|
5972
6332
|
fg: Colors.dim,
|
|
5973
6333
|
dim: true,
|
|
5974
6334
|
children: "Enter / R"
|
|
@@ -5990,7 +6350,7 @@ class ErrorBoundary extends Component {
|
|
|
5990
6350
|
render() {
|
|
5991
6351
|
if (this.state.error) {
|
|
5992
6352
|
const message = formatBoundaryErrorMessage(this.state.error);
|
|
5993
|
-
return /* @__PURE__ */
|
|
6353
|
+
return /* @__PURE__ */ jsxDEV2(ErrorRecoveryPanel, {
|
|
5994
6354
|
viewName: this.props.viewName,
|
|
5995
6355
|
message,
|
|
5996
6356
|
onRetry: this.handleRetry
|
|
@@ -6002,7 +6362,7 @@ class ErrorBoundary extends Component {
|
|
|
6002
6362
|
|
|
6003
6363
|
// src/components/shared/status-dot.tsx
|
|
6004
6364
|
init_src();
|
|
6005
|
-
import { jsxDEV as
|
|
6365
|
+
import { jsxDEV as jsxDEV3 } from "@opentui/react/jsx-dev-runtime";
|
|
6006
6366
|
var DOT_CHAR = {
|
|
6007
6367
|
operational: "\u2588",
|
|
6008
6368
|
degraded: "\u258C",
|
|
@@ -6014,7 +6374,7 @@ function StatusDot({ status, pulse = false }) {
|
|
|
6014
6374
|
const color = DOT_COLOR[status];
|
|
6015
6375
|
const isDown = status === "down";
|
|
6016
6376
|
const shouldBlink = pulse && status === "operational";
|
|
6017
|
-
return /* @__PURE__ */
|
|
6377
|
+
return /* @__PURE__ */ jsxDEV3("text", {
|
|
6018
6378
|
fg: color,
|
|
6019
6379
|
bold: !isDown,
|
|
6020
6380
|
dim: isDown,
|
|
@@ -6028,24 +6388,24 @@ init_src();
|
|
|
6028
6388
|
|
|
6029
6389
|
// src/components/shared/cool-brackets.tsx
|
|
6030
6390
|
init_src();
|
|
6031
|
-
import { jsxDEV as
|
|
6391
|
+
import { jsxDEV as jsxDEV4 } from "@opentui/react/jsx-dev-runtime";
|
|
6032
6392
|
function CoolBrackets({
|
|
6033
6393
|
children,
|
|
6034
6394
|
open = "\u250C",
|
|
6035
6395
|
close = "\u2510",
|
|
6036
6396
|
gap = 1
|
|
6037
6397
|
}) {
|
|
6038
|
-
return /* @__PURE__ */
|
|
6398
|
+
return /* @__PURE__ */ jsxDEV4("box", {
|
|
6039
6399
|
flexDirection: "row",
|
|
6040
6400
|
gap,
|
|
6041
6401
|
alignItems: "center",
|
|
6042
6402
|
children: [
|
|
6043
|
-
/* @__PURE__ */
|
|
6403
|
+
/* @__PURE__ */ jsxDEV4("text", {
|
|
6044
6404
|
fg: Colors.accent,
|
|
6045
6405
|
children: open
|
|
6046
6406
|
}, undefined, false, undefined, this),
|
|
6047
6407
|
children ?? null,
|
|
6048
|
-
/* @__PURE__ */
|
|
6408
|
+
/* @__PURE__ */ jsxDEV4("text", {
|
|
6049
6409
|
fg: Colors.accent,
|
|
6050
6410
|
children: close
|
|
6051
6411
|
}, undefined, false, undefined, this)
|
|
@@ -6055,20 +6415,20 @@ function CoolBrackets({
|
|
|
6055
6415
|
function CoolGlyph({
|
|
6056
6416
|
char
|
|
6057
6417
|
}) {
|
|
6058
|
-
return /* @__PURE__ */
|
|
6418
|
+
return /* @__PURE__ */ jsxDEV4("text", {
|
|
6059
6419
|
fg: Colors.accent,
|
|
6060
6420
|
children: char
|
|
6061
6421
|
}, undefined, false, undefined, this);
|
|
6062
6422
|
}
|
|
6063
6423
|
|
|
6064
6424
|
// src/components/shared/view-header.tsx
|
|
6065
|
-
import { jsxDEV as
|
|
6425
|
+
import { jsxDEV as jsxDEV5 } from "@opentui/react/jsx-dev-runtime";
|
|
6066
6426
|
function ViewHeader({
|
|
6067
6427
|
title,
|
|
6068
6428
|
meta,
|
|
6069
6429
|
showDivider = true
|
|
6070
6430
|
}) {
|
|
6071
|
-
return /* @__PURE__ */
|
|
6431
|
+
return /* @__PURE__ */ jsxDEV5("box", {
|
|
6072
6432
|
flexDirection: "row",
|
|
6073
6433
|
gap: 2,
|
|
6074
6434
|
paddingBottom: showDivider ? 1 : 0,
|
|
@@ -6078,17 +6438,17 @@ function ViewHeader({
|
|
|
6078
6438
|
justifyContent: "space-between",
|
|
6079
6439
|
width: "100%",
|
|
6080
6440
|
children: [
|
|
6081
|
-
/* @__PURE__ */
|
|
6441
|
+
/* @__PURE__ */ jsxDEV5(CoolBrackets, {
|
|
6082
6442
|
open: "\u250C",
|
|
6083
6443
|
close: "\u2510",
|
|
6084
6444
|
gap: 1,
|
|
6085
|
-
children: /* @__PURE__ */
|
|
6445
|
+
children: /* @__PURE__ */ jsxDEV5("text", {
|
|
6086
6446
|
fg: Colors.accent,
|
|
6087
6447
|
bold: true,
|
|
6088
6448
|
children: title
|
|
6089
6449
|
}, undefined, false, undefined, this)
|
|
6090
6450
|
}, undefined, false, undefined, this),
|
|
6091
|
-
meta ? /* @__PURE__ */
|
|
6451
|
+
meta ? /* @__PURE__ */ jsxDEV5("box", {
|
|
6092
6452
|
flexDirection: "row",
|
|
6093
6453
|
gap: 1,
|
|
6094
6454
|
children: meta
|
|
@@ -6097,65 +6457,9 @@ function ViewHeader({
|
|
|
6097
6457
|
}, undefined, true, undefined, this);
|
|
6098
6458
|
}
|
|
6099
6459
|
|
|
6100
|
-
// src/components/ui/dialog.tsx
|
|
6101
|
-
init_src();
|
|
6102
|
-
import { useState } from "react";
|
|
6103
|
-
import {
|
|
6104
|
-
useDialogKeyboard
|
|
6105
|
-
} from "@opentui-ui/dialog/react";
|
|
6106
|
-
import { jsxDEV as jsxDEV5 } from "@opentui/react/jsx-dev-runtime";
|
|
6107
|
-
async function showConfirm(dialog, options) {
|
|
6108
|
-
return dialog.confirm({
|
|
6109
|
-
content: (ctx) => /* @__PURE__ */ jsxDEV5("box", {
|
|
6110
|
-
flexDirection: "column",
|
|
6111
|
-
padding: 1,
|
|
6112
|
-
gap: 1,
|
|
6113
|
-
children: [
|
|
6114
|
-
/* @__PURE__ */ jsxDEV5("text", {
|
|
6115
|
-
fg: Colors.accent,
|
|
6116
|
-
children: /* @__PURE__ */ jsxDEV5("b", {
|
|
6117
|
-
children: options.title
|
|
6118
|
-
}, undefined, false, undefined, this)
|
|
6119
|
-
}, undefined, false, undefined, this),
|
|
6120
|
-
/* @__PURE__ */ jsxDEV5("text", {
|
|
6121
|
-
fg: Colors.muted,
|
|
6122
|
-
children: options.message
|
|
6123
|
-
}, undefined, false, undefined, this),
|
|
6124
|
-
/* @__PURE__ */ jsxDEV5("box", {
|
|
6125
|
-
flexDirection: "row",
|
|
6126
|
-
gap: 2,
|
|
6127
|
-
justifyContent: "flex-end",
|
|
6128
|
-
children: [
|
|
6129
|
-
/* @__PURE__ */ jsxDEV5("text", {
|
|
6130
|
-
fg: Colors.muted,
|
|
6131
|
-
onMouseUp: () => ctx.resolve(false),
|
|
6132
|
-
children: [
|
|
6133
|
-
" ",
|
|
6134
|
-
options.cancelLabel ?? "Cancel",
|
|
6135
|
-
" "
|
|
6136
|
-
]
|
|
6137
|
-
}, undefined, true, undefined, this),
|
|
6138
|
-
/* @__PURE__ */ jsxDEV5("text", {
|
|
6139
|
-
fg: Colors.accent,
|
|
6140
|
-
bg: Colors.card,
|
|
6141
|
-
onMouseUp: () => ctx.resolve(true),
|
|
6142
|
-
children: [
|
|
6143
|
-
" ",
|
|
6144
|
-
options.confirmLabel ?? "Confirm",
|
|
6145
|
-
" "
|
|
6146
|
-
]
|
|
6147
|
-
}, undefined, true, undefined, this)
|
|
6148
|
-
]
|
|
6149
|
-
}, undefined, true, undefined, this)
|
|
6150
|
-
]
|
|
6151
|
-
}, undefined, true, undefined, this),
|
|
6152
|
-
closeOnClickOutside: options.closeOnClickOutside ?? true
|
|
6153
|
-
});
|
|
6154
|
-
}
|
|
6155
|
-
|
|
6156
6460
|
// src/components/shared/spinner.tsx
|
|
6157
6461
|
init_src();
|
|
6158
|
-
import { useState as useState2, useEffect as
|
|
6462
|
+
import { useState as useState2, useEffect as useEffect4 } from "react";
|
|
6159
6463
|
import { jsxDEV as jsxDEV6 } from "@opentui/react/jsx-dev-runtime";
|
|
6160
6464
|
var SPINNER_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
6161
6465
|
function Spinner({
|
|
@@ -6163,7 +6467,7 @@ function Spinner({
|
|
|
6163
6467
|
color = Colors.highlight
|
|
6164
6468
|
}) {
|
|
6165
6469
|
const [frame, setFrame] = useState2(0);
|
|
6166
|
-
|
|
6470
|
+
useEffect4(() => {
|
|
6167
6471
|
if (globalThis.IS_REACT_ACT_ENVIRONMENT === true) {
|
|
6168
6472
|
return;
|
|
6169
6473
|
}
|
|
@@ -6222,7 +6526,7 @@ function EmptyState({
|
|
|
6222
6526
|
|
|
6223
6527
|
// src/components/views/dashboard/auto-repair-panel.tsx
|
|
6224
6528
|
init_src();
|
|
6225
|
-
import { useMemo } from "react";
|
|
6529
|
+
import { useMemo as useMemo2 } from "react";
|
|
6226
6530
|
import { jsxDEV as jsxDEV7, Fragment } from "@opentui/react/jsx-dev-runtime";
|
|
6227
6531
|
function RepairStatusBadge({
|
|
6228
6532
|
status
|
|
@@ -6252,7 +6556,7 @@ function AutoRepairPanel({
|
|
|
6252
6556
|
onDismiss,
|
|
6253
6557
|
onRerun
|
|
6254
6558
|
}) {
|
|
6255
|
-
const resultCounts =
|
|
6559
|
+
const resultCounts = useMemo2(() => {
|
|
6256
6560
|
if (state.kind !== "results")
|
|
6257
6561
|
return { applied: 0, failed: 0 };
|
|
6258
6562
|
let applied = 0;
|
|
@@ -6420,7 +6724,7 @@ function AutoRepairPanel({
|
|
|
6420
6724
|
|
|
6421
6725
|
// src/components/views/dashboard/model-health-section.tsx
|
|
6422
6726
|
init_src();
|
|
6423
|
-
import { useState as useState3, useCallback, useEffect as
|
|
6727
|
+
import { useState as useState3, useCallback as useCallback2, useEffect as useEffect5 } from "react";
|
|
6424
6728
|
import { jsxDEV as jsxDEV8 } from "@opentui/react/jsx-dev-runtime";
|
|
6425
6729
|
var MODEL_HEALTH_POLL_MS = 30000;
|
|
6426
6730
|
function modelStatusToDot(status) {
|
|
@@ -6528,7 +6832,7 @@ function ModelHealthSection() {
|
|
|
6528
6832
|
const [loading, setLoading] = useState3(true);
|
|
6529
6833
|
const [error, setError] = useState3(null);
|
|
6530
6834
|
const [lastRefresh, setLastRefresh] = useState3(null);
|
|
6531
|
-
|
|
6835
|
+
useEffect5(() => {
|
|
6532
6836
|
let cancelled = false;
|
|
6533
6837
|
let generation = 0;
|
|
6534
6838
|
let inFlight = false;
|
|
@@ -6567,7 +6871,7 @@ function ModelHealthSection() {
|
|
|
6567
6871
|
clearInterval(interval);
|
|
6568
6872
|
};
|
|
6569
6873
|
}, []);
|
|
6570
|
-
const toggleExpand =
|
|
6874
|
+
const toggleExpand = useCallback2((index) => {
|
|
6571
6875
|
setExpandedIndex((prev) => prev === index ? null : index);
|
|
6572
6876
|
}, []);
|
|
6573
6877
|
if (loading && providers.length === 0) {
|
|
@@ -6685,7 +6989,7 @@ function ModelHealthSection() {
|
|
|
6685
6989
|
|
|
6686
6990
|
// src/components/views/dashboard/pyne-health-section.tsx
|
|
6687
6991
|
init_src();
|
|
6688
|
-
import { useState as useState4, useEffect as
|
|
6992
|
+
import { useState as useState4, useEffect as useEffect6 } from "react";
|
|
6689
6993
|
import { jsxDEV as jsxDEV9 } from "@opentui/react/jsx-dev-runtime";
|
|
6690
6994
|
var POLL_MS = 30000;
|
|
6691
6995
|
function statusToDot(status) {
|
|
@@ -6698,7 +7002,7 @@ function statusToDot(status) {
|
|
|
6698
7002
|
function PyneHealthSection() {
|
|
6699
7003
|
const [result, setResult] = useState4(null);
|
|
6700
7004
|
const [loading, setLoading] = useState4(true);
|
|
6701
|
-
|
|
7005
|
+
useEffect6(() => {
|
|
6702
7006
|
let cancelled = false;
|
|
6703
7007
|
let generation = 0;
|
|
6704
7008
|
let inFlight = false;
|
|
@@ -6798,7 +7102,7 @@ function PyneHealthSection() {
|
|
|
6798
7102
|
|
|
6799
7103
|
// src/components/views/dashboard/alerts-panel.tsx
|
|
6800
7104
|
init_src();
|
|
6801
|
-
import { useState as useState5, useMemo as
|
|
7105
|
+
import { useState as useState5, useMemo as useMemo3, useEffect as useEffect7 } from "react";
|
|
6802
7106
|
import { jsxDEV as jsxDEV10 } from "@opentui/react/jsx-dev-runtime";
|
|
6803
7107
|
var SEVERITY_LABEL = {
|
|
6804
7108
|
info: "INFO",
|
|
@@ -6820,10 +7124,10 @@ function AlertsPanel() {
|
|
|
6820
7124
|
const activeView = useUIStore((s) => s.activeView);
|
|
6821
7125
|
const isActive = activeView === "dashboard";
|
|
6822
7126
|
const [scrollOffset, setScrollOffset] = useState5(0);
|
|
6823
|
-
const sortedAlerts =
|
|
7127
|
+
const sortedAlerts = useMemo3(() => {
|
|
6824
7128
|
return [...alerts].sort((a, b) => b.timestamp - a.timestamp).slice(0, MAX_VISIBLE_ALERTS);
|
|
6825
7129
|
}, [alerts]);
|
|
6826
|
-
|
|
7130
|
+
useEffect7(() => {
|
|
6827
7131
|
setScrollOffset((o) => Math.min(o, Math.max(0, sortedAlerts.length - 1)));
|
|
6828
7132
|
}, [sortedAlerts.length]);
|
|
6829
7133
|
useViewKeyboard((key) => {
|
|
@@ -6959,7 +7263,7 @@ function formatStatNumber(value, isPnl = false) {
|
|
|
6959
7263
|
var KILL_SWITCH_POLL_MS = 15000;
|
|
6960
7264
|
function KillSwitchStatusBadge() {
|
|
6961
7265
|
const [state, setState] = useState6("unknown");
|
|
6962
|
-
|
|
7266
|
+
useEffect8(() => {
|
|
6963
7267
|
let cancelled = false;
|
|
6964
7268
|
const refresh = async () => {
|
|
6965
7269
|
try {
|
|
@@ -7060,12 +7364,12 @@ function ServiceHealthGrid() {
|
|
|
7060
7364
|
const activeView = useUIStore((s) => s.activeView);
|
|
7061
7365
|
const isActive = activeView === "dashboard";
|
|
7062
7366
|
const [focusIndex, setFocusIndex] = useState6(0);
|
|
7063
|
-
const visibleWorkers =
|
|
7064
|
-
const emptySlots =
|
|
7065
|
-
|
|
7367
|
+
const visibleWorkers = useMemo4(() => workers.slice(0, 10), [workers]);
|
|
7368
|
+
const emptySlots = useMemo4(() => visibleWorkers.length < 10 ? Array.from({ length: 10 - visibleWorkers.length }, (_, i) => i) : [], [visibleWorkers.length]);
|
|
7369
|
+
useEffect8(() => {
|
|
7066
7370
|
setFocusIndex((i) => visibleWorkers.length === 0 ? 0 : Math.min(i, visibleWorkers.length - 1));
|
|
7067
7371
|
}, [visibleWorkers.length]);
|
|
7068
|
-
const openWorker =
|
|
7372
|
+
const openWorker = useCallback3((workerId) => {
|
|
7069
7373
|
useServiceStore.getState().selectWorker(workerId);
|
|
7070
7374
|
useUIStore.getState().setView("worker-detail");
|
|
7071
7375
|
}, []);
|
|
@@ -7303,13 +7607,13 @@ function DashboardView({ dialog } = {}) {
|
|
|
7303
7607
|
const mountedRef = useRef3(true);
|
|
7304
7608
|
const refreshGenRef = useRef3(0);
|
|
7305
7609
|
const repairRunningRef = useRef3(false);
|
|
7306
|
-
|
|
7610
|
+
useEffect8(() => {
|
|
7307
7611
|
mountedRef.current = true;
|
|
7308
7612
|
return () => {
|
|
7309
7613
|
mountedRef.current = false;
|
|
7310
7614
|
};
|
|
7311
7615
|
}, []);
|
|
7312
|
-
const handleRefresh =
|
|
7616
|
+
const handleRefresh = useCallback3(async () => {
|
|
7313
7617
|
const gen = ++refreshGenRef.current;
|
|
7314
7618
|
try {
|
|
7315
7619
|
const result = await cliBridge.monitorStatus();
|
|
@@ -7321,7 +7625,7 @@ function DashboardView({ dialog } = {}) {
|
|
|
7321
7625
|
}
|
|
7322
7626
|
} catch {}
|
|
7323
7627
|
}, []);
|
|
7324
|
-
const handleRunAutoRepair =
|
|
7628
|
+
const handleRunAutoRepair = useCallback3(async () => {
|
|
7325
7629
|
if (!dialog) {
|
|
7326
7630
|
useServiceStore.getState().addAlert({
|
|
7327
7631
|
id: `repair-noconfirm-${Date.now()}`,
|
|
@@ -7408,10 +7712,10 @@ function DashboardView({ dialog } = {}) {
|
|
|
7408
7712
|
repairRunningRef.current = false;
|
|
7409
7713
|
}
|
|
7410
7714
|
}, [dialog]);
|
|
7411
|
-
const dismissRepairPanel =
|
|
7715
|
+
const dismissRepairPanel = useCallback3(() => {
|
|
7412
7716
|
setRepairState({ kind: "idle" });
|
|
7413
7717
|
}, []);
|
|
7414
|
-
const rerunRepair =
|
|
7718
|
+
const rerunRepair = useCallback3(() => {
|
|
7415
7719
|
handleRunAutoRepair();
|
|
7416
7720
|
}, [handleRunAutoRepair]);
|
|
7417
7721
|
useViewKeyboard((key) => {
|
|
@@ -7419,7 +7723,7 @@ function DashboardView({ dialog } = {}) {
|
|
|
7419
7723
|
dismissRepairPanel();
|
|
7420
7724
|
}
|
|
7421
7725
|
});
|
|
7422
|
-
|
|
7726
|
+
useEffect8(() => {
|
|
7423
7727
|
let cancelled = false;
|
|
7424
7728
|
const runHealthCheck = async () => {
|
|
7425
7729
|
try {
|
|
@@ -7496,7 +7800,7 @@ function DashboardView({ dialog } = {}) {
|
|
|
7496
7800
|
init_src();
|
|
7497
7801
|
init_src();
|
|
7498
7802
|
init_src();
|
|
7499
|
-
import { useState as useState7, useMemo as
|
|
7803
|
+
import { useState as useState7, useMemo as useMemo5, useCallback as useCallback4, useEffect as useEffect9, useRef as useRef4 } from "react";
|
|
7500
7804
|
|
|
7501
7805
|
// src/components/shared/panel.tsx
|
|
7502
7806
|
init_src();
|
|
@@ -7728,7 +8032,7 @@ function WorkersOverview({ dialog } = {}) {
|
|
|
7728
8032
|
const [deployProgress, setDeployProgress] = useState7("");
|
|
7729
8033
|
const mountedRef = useRef4(true);
|
|
7730
8034
|
const deployingRef = useRef4(false);
|
|
7731
|
-
|
|
8035
|
+
useEffect9(() => {
|
|
7732
8036
|
mountedRef.current = true;
|
|
7733
8037
|
return () => {
|
|
7734
8038
|
mountedRef.current = false;
|
|
@@ -7740,7 +8044,7 @@ function WorkersOverview({ dialog } = {}) {
|
|
|
7740
8044
|
const setView = useUIStore((s) => s.setView);
|
|
7741
8045
|
const [cliFallbackTried, setCliFallbackTried] = useState7(false);
|
|
7742
8046
|
const [cliFallbackError, setCliFallbackError] = useState7(null);
|
|
7743
|
-
|
|
8047
|
+
useEffect9(() => {
|
|
7744
8048
|
if (workers.length > 0) {
|
|
7745
8049
|
setCliFallbackTried(false);
|
|
7746
8050
|
setCliFallbackError(null);
|
|
@@ -7811,7 +8115,7 @@ function WorkersOverview({ dialog } = {}) {
|
|
|
7811
8115
|
};
|
|
7812
8116
|
}, [workers.length, cliFallbackTried]);
|
|
7813
8117
|
const maxIndex = Math.max(0, workers.length - 1);
|
|
7814
|
-
const rows =
|
|
8118
|
+
const rows = useMemo5(() => {
|
|
7815
8119
|
const result = [];
|
|
7816
8120
|
for (let i = 0;i < workers.length; i += COLS) {
|
|
7817
8121
|
result.push(workers.slice(i, i + COLS));
|
|
@@ -7819,7 +8123,7 @@ function WorkersOverview({ dialog } = {}) {
|
|
|
7819
8123
|
return result;
|
|
7820
8124
|
}, [workers]);
|
|
7821
8125
|
const safeIndex = Math.min(focusedIndex, maxIndex);
|
|
7822
|
-
|
|
8126
|
+
useEffect9(() => {
|
|
7823
8127
|
setFocusedIndex((i) => Math.min(i, maxIndex));
|
|
7824
8128
|
}, [maxIndex]);
|
|
7825
8129
|
useViewKeyboard((key) => {
|
|
@@ -7846,11 +8150,11 @@ function WorkersOverview({ dialog } = {}) {
|
|
|
7846
8150
|
}
|
|
7847
8151
|
}
|
|
7848
8152
|
});
|
|
7849
|
-
const onProgress =
|
|
8153
|
+
const onProgress = useCallback4((chunk) => {
|
|
7850
8154
|
const safe = redactSecretsInText(chunk);
|
|
7851
8155
|
setDeployProgress((prev) => (prev + safe).slice(-2000));
|
|
7852
8156
|
}, []);
|
|
7853
|
-
const handleLogs =
|
|
8157
|
+
const handleLogs = useCallback4(async (worker) => {
|
|
7854
8158
|
if (deployingRef.current)
|
|
7855
8159
|
return;
|
|
7856
8160
|
const store = useServiceStore.getState();
|
|
@@ -7897,7 +8201,7 @@ function WorkersOverview({ dialog } = {}) {
|
|
|
7897
8201
|
});
|
|
7898
8202
|
}
|
|
7899
8203
|
}, []);
|
|
7900
|
-
const handleDeploy =
|
|
8204
|
+
const handleDeploy = useCallback4(async (worker) => {
|
|
7901
8205
|
if (deployingRef.current)
|
|
7902
8206
|
return;
|
|
7903
8207
|
if (!dialog) {
|
|
@@ -7955,7 +8259,7 @@ function WorkersOverview({ dialog } = {}) {
|
|
|
7955
8259
|
setDeployingWorker(null);
|
|
7956
8260
|
}
|
|
7957
8261
|
}, [onProgress, dialog]);
|
|
7958
|
-
const handleRestart =
|
|
8262
|
+
const handleRestart = useCallback4(async (worker) => {
|
|
7959
8263
|
if (deployingRef.current)
|
|
7960
8264
|
return;
|
|
7961
8265
|
if (!dialog) {
|
|
@@ -8179,7 +8483,7 @@ function WorkersOverview({ dialog } = {}) {
|
|
|
8179
8483
|
|
|
8180
8484
|
// src/components/views/worker-detail.tsx
|
|
8181
8485
|
init_src();
|
|
8182
|
-
import { useState as useState8, useMemo as
|
|
8486
|
+
import { useState as useState8, useMemo as useMemo6, useEffect as useEffect10, useCallback as useCallback5, useRef as useRef5 } from "react";
|
|
8183
8487
|
import { jsxDEV as jsxDEV14 } from "@opentui/react/jsx-dev-runtime";
|
|
8184
8488
|
var PANE_COUNT = 4;
|
|
8185
8489
|
var PANE_NAMES = [
|
|
@@ -8289,10 +8593,10 @@ function LogsPane({
|
|
|
8289
8593
|
focused
|
|
8290
8594
|
}) {
|
|
8291
8595
|
const allLogs = useServiceStore((s) => s.logs);
|
|
8292
|
-
const workerLogs =
|
|
8596
|
+
const workerLogs = useMemo6(() => allLogs.filter((l) => l.workerId === workerId), [allLogs, workerId]);
|
|
8293
8597
|
const [paused, setPaused] = useState8(false);
|
|
8294
8598
|
const [, setAutoScroll] = useState8(true);
|
|
8295
|
-
|
|
8599
|
+
useEffect10(() => {
|
|
8296
8600
|
if (!paused) {
|
|
8297
8601
|
setAutoScroll(true);
|
|
8298
8602
|
}
|
|
@@ -8304,7 +8608,7 @@ function LogsPane({
|
|
|
8304
8608
|
setPaused((p) => !p);
|
|
8305
8609
|
}
|
|
8306
8610
|
});
|
|
8307
|
-
const displayedLogs =
|
|
8611
|
+
const displayedLogs = useMemo6(() => {
|
|
8308
8612
|
const source = paused ? workerLogs : workerLogs.slice(-50);
|
|
8309
8613
|
return source;
|
|
8310
8614
|
}, [workerLogs, paused]);
|
|
@@ -8446,7 +8750,7 @@ function ConfigPreviewPane({
|
|
|
8446
8750
|
entries,
|
|
8447
8751
|
loading
|
|
8448
8752
|
}) {
|
|
8449
|
-
const displayEntries =
|
|
8753
|
+
const displayEntries = useMemo6(() => {
|
|
8450
8754
|
if (entries && entries.length > 0)
|
|
8451
8755
|
return entries;
|
|
8452
8756
|
return [
|
|
@@ -8528,7 +8832,7 @@ function WorkerDetail() {
|
|
|
8528
8832
|
const mountedRef = useRef5(true);
|
|
8529
8833
|
const configGenRef = useRef5(0);
|
|
8530
8834
|
const logsGenRef = useRef5(0);
|
|
8531
|
-
|
|
8835
|
+
useEffect10(() => {
|
|
8532
8836
|
mountedRef.current = true;
|
|
8533
8837
|
return () => {
|
|
8534
8838
|
mountedRef.current = false;
|
|
@@ -8538,8 +8842,8 @@ function WorkerDetail() {
|
|
|
8538
8842
|
const workers = useServiceStore((s) => s.workers);
|
|
8539
8843
|
const connectionStatus = useServiceStore((s) => s.connectionStatus);
|
|
8540
8844
|
const goBack = useUIStore((s) => s.goBack);
|
|
8541
|
-
const worker =
|
|
8542
|
-
const fetchConfig =
|
|
8845
|
+
const worker = useMemo6(() => workers.find((w) => w.id === selectedWorkerId) ?? null, [workers, selectedWorkerId]);
|
|
8846
|
+
const fetchConfig = useCallback5(async () => {
|
|
8543
8847
|
if (!worker)
|
|
8544
8848
|
return;
|
|
8545
8849
|
const gen = ++configGenRef.current;
|
|
@@ -8579,7 +8883,7 @@ function WorkerDetail() {
|
|
|
8579
8883
|
}
|
|
8580
8884
|
}
|
|
8581
8885
|
}, [worker]);
|
|
8582
|
-
const fetchLogs =
|
|
8886
|
+
const fetchLogs = useCallback5(async () => {
|
|
8583
8887
|
if (!worker)
|
|
8584
8888
|
return;
|
|
8585
8889
|
const gen = ++logsGenRef.current;
|
|
@@ -8623,10 +8927,10 @@ function WorkerDetail() {
|
|
|
8623
8927
|
}
|
|
8624
8928
|
}
|
|
8625
8929
|
}, [worker]);
|
|
8626
|
-
|
|
8930
|
+
useEffect10(() => {
|
|
8627
8931
|
fetchConfig();
|
|
8628
8932
|
}, [fetchConfig]);
|
|
8629
|
-
|
|
8933
|
+
useEffect10(() => {
|
|
8630
8934
|
if (connectionStatus !== "connected") {
|
|
8631
8935
|
fetchLogs();
|
|
8632
8936
|
return;
|
|
@@ -8636,7 +8940,7 @@ function WorkerDetail() {
|
|
|
8636
8940
|
fetchLogs();
|
|
8637
8941
|
}
|
|
8638
8942
|
}, [connectionStatus, fetchLogs, worker]);
|
|
8639
|
-
const handleRefresh =
|
|
8943
|
+
const handleRefresh = useCallback5(() => {
|
|
8640
8944
|
fetchConfig();
|
|
8641
8945
|
fetchLogs();
|
|
8642
8946
|
}, [fetchConfig, fetchLogs]);
|
|
@@ -8791,7 +9095,7 @@ function WorkerDetail() {
|
|
|
8791
9095
|
|
|
8792
9096
|
// src/components/views/trade-monitor.tsx
|
|
8793
9097
|
init_src();
|
|
8794
|
-
import { useState as useState9, useMemo as
|
|
9098
|
+
import { useState as useState9, useMemo as useMemo7, useRef as useRef6, useEffect as useEffect11 } from "react";
|
|
8795
9099
|
import { jsxDEV as jsxDEV15, Fragment as Fragment2 } from "@opentui/react/jsx-dev-runtime";
|
|
8796
9100
|
var MAX_VISIBLE_TRADES = 120;
|
|
8797
9101
|
var SIDE_COLOR = {
|
|
@@ -8914,7 +9218,7 @@ function LiveTradeFeed({
|
|
|
8914
9218
|
const [selectedIndex, setSelectedIndex] = useState9(0);
|
|
8915
9219
|
const frozenRef = useRef6([]);
|
|
8916
9220
|
const [frozenStream, setFrozenStream] = useState9(null);
|
|
8917
|
-
|
|
9221
|
+
useEffect11(() => {
|
|
8918
9222
|
if (paused) {
|
|
8919
9223
|
frozenRef.current = [...tradeStream];
|
|
8920
9224
|
setFrozenStream(frozenRef.current);
|
|
@@ -8924,9 +9228,9 @@ function LiveTradeFeed({
|
|
|
8924
9228
|
}
|
|
8925
9229
|
}, [paused]);
|
|
8926
9230
|
const effectiveStream = paused ? frozenStream ?? frozenRef.current : tradeStream;
|
|
8927
|
-
const sortedTrades =
|
|
9231
|
+
const sortedTrades = useMemo7(() => selectVisibleTrades(effectiveStream, MAX_VISIBLE_TRADES), [effectiveStream]);
|
|
8928
9232
|
const maxIndex = Math.max(0, sortedTrades.length - 1);
|
|
8929
|
-
|
|
9233
|
+
useEffect11(() => {
|
|
8930
9234
|
setSelectedIndex((i) => Math.min(i, maxIndex));
|
|
8931
9235
|
}, [maxIndex]);
|
|
8932
9236
|
const safeIndex = Math.min(selectedIndex, maxIndex);
|
|
@@ -9079,7 +9383,7 @@ function LiveTradeFeed({
|
|
|
9079
9383
|
}
|
|
9080
9384
|
function OpenPositions() {
|
|
9081
9385
|
const tradeStream = useServiceStore((s) => s.tradeStream);
|
|
9082
|
-
const positions =
|
|
9386
|
+
const positions = useMemo7(() => {
|
|
9083
9387
|
const map = new Map;
|
|
9084
9388
|
for (const trade of tradeStream) {
|
|
9085
9389
|
const existing = map.get(trade.symbol);
|
|
@@ -9204,7 +9508,7 @@ function OpenPositions() {
|
|
|
9204
9508
|
function PerformanceSummary() {
|
|
9205
9509
|
const tradeStream = useServiceStore((s) => s.tradeStream);
|
|
9206
9510
|
const metrics = useServiceStore((s) => s.metrics);
|
|
9207
|
-
const perf =
|
|
9511
|
+
const perf = useMemo7(() => {
|
|
9208
9512
|
const todayStart = startOfToday();
|
|
9209
9513
|
const weekStart = startOfDaysAgo(7);
|
|
9210
9514
|
const monthStart = startOfDaysAgo(30);
|
|
@@ -9413,7 +9717,7 @@ function TradeMonitor() {
|
|
|
9413
9717
|
|
|
9414
9718
|
// src/components/views/logs-viewer.tsx
|
|
9415
9719
|
init_src();
|
|
9416
|
-
import { useState as useState10, useMemo as
|
|
9720
|
+
import { useState as useState10, useMemo as useMemo8, useCallback as useCallback6, useEffect as useEffect12, useRef as useRef7 } from "react";
|
|
9417
9721
|
import { jsxDEV as jsxDEV16 } from "@opentui/react/jsx-dev-runtime";
|
|
9418
9722
|
var LEVEL_LABEL = {
|
|
9419
9723
|
error: "ERR",
|
|
@@ -9704,7 +10008,7 @@ function LogsViewer() {
|
|
|
9704
10008
|
const activeView = useUIStore((s) => s.activeView);
|
|
9705
10009
|
const isActive = activeView === "logs-viewer";
|
|
9706
10010
|
const sseConnected = connectionStatus === "connected";
|
|
9707
|
-
|
|
10011
|
+
useEffect12(() => {
|
|
9708
10012
|
if (searchTimerRef.current)
|
|
9709
10013
|
clearTimeout(searchTimerRef.current);
|
|
9710
10014
|
searchTimerRef.current = setTimeout(() => {
|
|
@@ -9718,11 +10022,11 @@ function LogsViewer() {
|
|
|
9718
10022
|
}
|
|
9719
10023
|
};
|
|
9720
10024
|
}, [searchText]);
|
|
9721
|
-
const workerNames =
|
|
9722
|
-
const toggleAll =
|
|
10025
|
+
const workerNames = useMemo8(() => workers.map((w) => w.name), [workers]);
|
|
10026
|
+
const toggleAll = useCallback6(() => {
|
|
9723
10027
|
setAllLevels((prev) => !prev);
|
|
9724
10028
|
}, []);
|
|
9725
|
-
const toggleLevel =
|
|
10029
|
+
const toggleLevel = useCallback6((lvl) => {
|
|
9726
10030
|
setLevels((prev) => {
|
|
9727
10031
|
const next = new Set(prev);
|
|
9728
10032
|
if (next.has(lvl))
|
|
@@ -9732,7 +10036,7 @@ function LogsViewer() {
|
|
|
9732
10036
|
return next;
|
|
9733
10037
|
});
|
|
9734
10038
|
}, []);
|
|
9735
|
-
const toggleWorker =
|
|
10039
|
+
const toggleWorker = useCallback6((name) => {
|
|
9736
10040
|
setSelectedWorkers((prev) => {
|
|
9737
10041
|
const next = new Set(prev);
|
|
9738
10042
|
if (next.has(name))
|
|
@@ -9742,7 +10046,7 @@ function LogsViewer() {
|
|
|
9742
10046
|
return next;
|
|
9743
10047
|
});
|
|
9744
10048
|
}, []);
|
|
9745
|
-
const handleExport =
|
|
10049
|
+
const handleExport = useCallback6(async () => {
|
|
9746
10050
|
const ts = Date.now();
|
|
9747
10051
|
try {
|
|
9748
10052
|
const result = await cliBridge.exec(["logs", "all"], {
|
|
@@ -9782,7 +10086,7 @@ function LogsViewer() {
|
|
|
9782
10086
|
}, []);
|
|
9783
10087
|
const [clearArmed, setClearArmed] = useState10(false);
|
|
9784
10088
|
const clearArmTimer = useRef7(null);
|
|
9785
|
-
const handleClear =
|
|
10089
|
+
const handleClear = useCallback6(() => {
|
|
9786
10090
|
if (!clearArmed) {
|
|
9787
10091
|
setClearArmed(true);
|
|
9788
10092
|
if (clearArmTimer.current)
|
|
@@ -9814,7 +10118,7 @@ function LogsViewer() {
|
|
|
9814
10118
|
acknowledged: false
|
|
9815
10119
|
});
|
|
9816
10120
|
}, [clearArmed]);
|
|
9817
|
-
const handleFetch =
|
|
10121
|
+
const handleFetch = useCallback6(async () => {
|
|
9818
10122
|
const ts = Date.now();
|
|
9819
10123
|
let fetchedCount = 0;
|
|
9820
10124
|
const names = useServiceStore.getState().workers.map((w) => w.name);
|
|
@@ -9843,20 +10147,20 @@ function LogsViewer() {
|
|
|
9843
10147
|
};
|
|
9844
10148
|
useServiceStore.getState().addAlert(alert);
|
|
9845
10149
|
}, []);
|
|
9846
|
-
const filteredLogs =
|
|
10150
|
+
const filteredLogs = useMemo8(() => applyLogFilters(allLogs, {
|
|
9847
10151
|
allLevels,
|
|
9848
10152
|
levels,
|
|
9849
10153
|
selectedWorkers,
|
|
9850
10154
|
searchText: debouncedSearch,
|
|
9851
10155
|
workers
|
|
9852
10156
|
}), [allLogs, allLevels, levels, selectedWorkers, debouncedSearch, workers]);
|
|
9853
|
-
const displayed =
|
|
10157
|
+
const displayed = useMemo8(() => {
|
|
9854
10158
|
const newestFirst = filteredLogs.slice().reverse();
|
|
9855
10159
|
return newestFirst.slice(0, MAX_VISIBLE_LOGS);
|
|
9856
10160
|
}, [filteredLogs]);
|
|
9857
10161
|
const [frozen, setFrozen] = useState10(null);
|
|
9858
10162
|
const visible = paused && frozen !== null ? frozen : displayed;
|
|
9859
|
-
|
|
10163
|
+
useEffect12(() => {
|
|
9860
10164
|
if (paused && frozen === null) {
|
|
9861
10165
|
setFrozen(displayed);
|
|
9862
10166
|
}
|
|
@@ -9971,7 +10275,7 @@ function LogsViewer() {
|
|
|
9971
10275
|
// src/components/views/service-manager.tsx
|
|
9972
10276
|
init_service_store();
|
|
9973
10277
|
init_src();
|
|
9974
|
-
import { useState as useState11, useCallback as
|
|
10278
|
+
import { useState as useState11, useCallback as useCallback7, useEffect as useEffect13, useMemo as useMemo9, useRef as useRef8 } from "react";
|
|
9975
10279
|
import { jsxDEV as jsxDEV17 } from "@opentui/react/jsx-dev-runtime";
|
|
9976
10280
|
var EDGE_LOCATIONS = [
|
|
9977
10281
|
{ code: "SFO", city: "San Francisco", x: 4, y: 3, latency: 2 },
|
|
@@ -10002,7 +10306,7 @@ var EDGE_LOCATION_BY_CELL = (() => {
|
|
|
10002
10306
|
})();
|
|
10003
10307
|
function EdgeMap() {
|
|
10004
10308
|
const [selectedCode, setSelectedCode] = useState11(null);
|
|
10005
|
-
const selectedLocation =
|
|
10309
|
+
const selectedLocation = useMemo9(() => EDGE_LOCATIONS.find((l) => l.code === selectedCode) ?? null, [selectedCode]);
|
|
10006
10310
|
return /* @__PURE__ */ jsxDEV17("box", {
|
|
10007
10311
|
flexDirection: "column",
|
|
10008
10312
|
flexGrow: 1,
|
|
@@ -10331,13 +10635,13 @@ function KillSwitchSection({ dialog, onAlert }) {
|
|
|
10331
10635
|
const loadingRef = useRef8(false);
|
|
10332
10636
|
const activeView = useUIStore((s) => s.activeView);
|
|
10333
10637
|
const isActive = activeView === "service-manager";
|
|
10334
|
-
|
|
10638
|
+
useEffect13(() => {
|
|
10335
10639
|
mountedRef.current = true;
|
|
10336
10640
|
return () => {
|
|
10337
10641
|
mountedRef.current = false;
|
|
10338
10642
|
};
|
|
10339
10643
|
}, []);
|
|
10340
|
-
const refresh =
|
|
10644
|
+
const refresh = useCallback7(async () => {
|
|
10341
10645
|
if (loadingRef.current)
|
|
10342
10646
|
return;
|
|
10343
10647
|
loadingRef.current = true;
|
|
@@ -10363,10 +10667,10 @@ function KillSwitchSection({ dialog, onAlert }) {
|
|
|
10363
10667
|
setLoading(false);
|
|
10364
10668
|
}
|
|
10365
10669
|
}, []);
|
|
10366
|
-
|
|
10670
|
+
useEffect13(() => {
|
|
10367
10671
|
refresh();
|
|
10368
10672
|
}, [refresh]);
|
|
10369
|
-
const setEngaged =
|
|
10673
|
+
const setEngaged = useCallback7(async (engaged2) => {
|
|
10370
10674
|
if (!dialog) {
|
|
10371
10675
|
useServiceStore.getState().addAlert({
|
|
10372
10676
|
id: `killswitch-noconfirm-${Date.now()}`,
|
|
@@ -10540,23 +10844,23 @@ function ServiceManager({ dialog }) {
|
|
|
10540
10844
|
const [selectedIndex, setSelectedIndex] = useState11(0);
|
|
10541
10845
|
const mountedRef = useRef8(true);
|
|
10542
10846
|
const deployingRef = useRef8(false);
|
|
10543
|
-
|
|
10847
|
+
useEffect13(() => {
|
|
10544
10848
|
mountedRef.current = true;
|
|
10545
10849
|
return () => {
|
|
10546
10850
|
mountedRef.current = false;
|
|
10547
10851
|
};
|
|
10548
10852
|
}, []);
|
|
10549
|
-
|
|
10853
|
+
useEffect13(() => {
|
|
10550
10854
|
setSelectedIndex((i) => workers.length === 0 ? 0 : Math.min(i, workers.length - 1));
|
|
10551
10855
|
}, [workers.length]);
|
|
10552
|
-
const totalEdgeCount =
|
|
10856
|
+
const totalEdgeCount = useMemo9(() => workers.reduce((sum, w) => sum + (w.edgeCount ?? 0), 0), [workers]);
|
|
10553
10857
|
const displayEdgeCount = totalEdgeCount;
|
|
10554
10858
|
const showPlus = false;
|
|
10555
|
-
const onProgress =
|
|
10859
|
+
const onProgress = useCallback7((chunk) => {
|
|
10556
10860
|
const safe = redactSecretsInText(chunk);
|
|
10557
10861
|
setDeployProgress((prev) => (prev + safe).slice(-2000));
|
|
10558
10862
|
}, []);
|
|
10559
|
-
const addResultAlert =
|
|
10863
|
+
const addResultAlert = useCallback7((id, type, result, successMsg, failMsg) => {
|
|
10560
10864
|
const store = useServiceStore.getState();
|
|
10561
10865
|
store.addAlert({
|
|
10562
10866
|
id,
|
|
@@ -10567,7 +10871,7 @@ function ServiceManager({ dialog }) {
|
|
|
10567
10871
|
acknowledged: false
|
|
10568
10872
|
});
|
|
10569
10873
|
}, []);
|
|
10570
|
-
const blockWithoutDialog =
|
|
10874
|
+
const blockWithoutDialog = useCallback7((action, target) => {
|
|
10571
10875
|
useServiceStore.getState().addAlert({
|
|
10572
10876
|
id: `${action}-noconfirm-${Date.now()}`,
|
|
10573
10877
|
type: action,
|
|
@@ -10577,7 +10881,7 @@ function ServiceManager({ dialog }) {
|
|
|
10577
10881
|
acknowledged: false
|
|
10578
10882
|
});
|
|
10579
10883
|
}, []);
|
|
10580
|
-
const handleDeploy =
|
|
10884
|
+
const handleDeploy = useCallback7(async (worker) => {
|
|
10581
10885
|
if (deployingRef.current)
|
|
10582
10886
|
return;
|
|
10583
10887
|
if (!dialog) {
|
|
@@ -10619,7 +10923,7 @@ function ServiceManager({ dialog }) {
|
|
|
10619
10923
|
setDeployingWorker(null);
|
|
10620
10924
|
}
|
|
10621
10925
|
}, [dialog, onProgress, addResultAlert, blockWithoutDialog]);
|
|
10622
|
-
const handleRestart =
|
|
10926
|
+
const handleRestart = useCallback7(async (worker) => {
|
|
10623
10927
|
if (deployingRef.current)
|
|
10624
10928
|
return;
|
|
10625
10929
|
if (!dialog) {
|
|
@@ -10661,7 +10965,7 @@ function ServiceManager({ dialog }) {
|
|
|
10661
10965
|
setDeployingWorker(null);
|
|
10662
10966
|
}
|
|
10663
10967
|
}, [dialog, onProgress, addResultAlert, blockWithoutDialog]);
|
|
10664
|
-
const handleDeployAll =
|
|
10968
|
+
const handleDeployAll = useCallback7(async () => {
|
|
10665
10969
|
if (deployingRef.current)
|
|
10666
10970
|
return;
|
|
10667
10971
|
if (!dialog) {
|
|
@@ -10703,7 +11007,7 @@ function ServiceManager({ dialog }) {
|
|
|
10703
11007
|
setDeployingWorker(null);
|
|
10704
11008
|
}
|
|
10705
11009
|
}, [dialog, workers.length, onProgress, addResultAlert, blockWithoutDialog]);
|
|
10706
|
-
const handleRestartAll =
|
|
11010
|
+
const handleRestartAll = useCallback7(async () => {
|
|
10707
11011
|
if (deployingRef.current)
|
|
10708
11012
|
return;
|
|
10709
11013
|
if (!dialog) {
|
|
@@ -10884,11 +11188,11 @@ function ServiceManager({ dialog }) {
|
|
|
10884
11188
|
init_src();
|
|
10885
11189
|
import { existsSync as existsSync5 } from "fs";
|
|
10886
11190
|
import { isAbsolute, relative, resolve as pathResolve } from "path";
|
|
10887
|
-
import { useState as useState12, useCallback as
|
|
11191
|
+
import { useState as useState12, useCallback as useCallback8, useMemo as useMemo12, useRef as useRef9, useEffect as useEffect14 } from "react";
|
|
10888
11192
|
|
|
10889
11193
|
// src/components/views/config-editor/file-tree.tsx
|
|
10890
11194
|
init_src();
|
|
10891
|
-
import { useMemo as
|
|
11195
|
+
import { useMemo as useMemo10 } from "react";
|
|
10892
11196
|
import { jsxDEV as jsxDEV18 } from "@opentui/react/jsx-dev-runtime";
|
|
10893
11197
|
function flattenTree(nodes, level = 0) {
|
|
10894
11198
|
const result = [];
|
|
@@ -10907,7 +11211,7 @@ function FileTree({
|
|
|
10907
11211
|
focusedPath,
|
|
10908
11212
|
onSelectFile
|
|
10909
11213
|
}) {
|
|
10910
|
-
const flatNodes =
|
|
11214
|
+
const flatNodes = useMemo10(() => flattenTree(nodes), [nodes]);
|
|
10911
11215
|
return /* @__PURE__ */ jsxDEV18("box", {
|
|
10912
11216
|
flexDirection: "column",
|
|
10913
11217
|
flexGrow: 1,
|
|
@@ -10963,7 +11267,7 @@ function FileTree({
|
|
|
10963
11267
|
|
|
10964
11268
|
// src/components/views/config-editor/code-editor.tsx
|
|
10965
11269
|
init_src();
|
|
10966
|
-
import { useMemo as
|
|
11270
|
+
import { useMemo as useMemo11 } from "react";
|
|
10967
11271
|
import { parse as parseToml, TomlError } from "smol-toml";
|
|
10968
11272
|
import { jsxDEV as jsxDEV19, Fragment as Fragment3 } from "@opentui/react/jsx-dev-runtime";
|
|
10969
11273
|
var TOML_COLORS = {
|
|
@@ -11275,11 +11579,11 @@ function CodeEditor({
|
|
|
11275
11579
|
scrollOffset: _scrollOffset,
|
|
11276
11580
|
maxDisplayLines = 5000
|
|
11277
11581
|
}) {
|
|
11278
|
-
const lines =
|
|
11582
|
+
const lines = useMemo11(() => content.split(`
|
|
11279
11583
|
`), [content]);
|
|
11280
11584
|
const truncated = lines.length > maxDisplayLines;
|
|
11281
|
-
const visibleLines =
|
|
11282
|
-
const errorLineSet =
|
|
11585
|
+
const visibleLines = useMemo11(() => truncated ? lines.slice(0, maxDisplayLines) : lines, [lines, maxDisplayLines, truncated]);
|
|
11586
|
+
const errorLineSet = useMemo11(() => {
|
|
11283
11587
|
const set = new Set;
|
|
11284
11588
|
for (const err of syntaxErrors)
|
|
11285
11589
|
set.add(err.line);
|
|
@@ -11702,8 +12006,8 @@ function ConfigEditor() {
|
|
|
11702
12006
|
const [validationError, setValidationError] = useState12(null);
|
|
11703
12007
|
const [undoStack, setUndoStack] = useState12([]);
|
|
11704
12008
|
const [redoStack, setRedoStack] = useState12([]);
|
|
11705
|
-
const fileTree =
|
|
11706
|
-
const flatFiles =
|
|
12009
|
+
const fileTree = useMemo12(() => CONFIG_TREE_BLUEPRINT, []);
|
|
12010
|
+
const flatFiles = useMemo12(() => {
|
|
11707
12011
|
const files = [];
|
|
11708
12012
|
function walk(nodes) {
|
|
11709
12013
|
for (const n of nodes) {
|
|
@@ -11721,7 +12025,7 @@ function ConfigEditor() {
|
|
|
11721
12025
|
const unsavedCount = unsavedPaths.size;
|
|
11722
12026
|
const safeFocusedIdx = Math.max(0, Math.min(focusedTreeIdx, flatFiles.length - 1));
|
|
11723
12027
|
const focusedFilePath = flatFiles[safeFocusedIdx]?.path ?? null;
|
|
11724
|
-
const selectFile =
|
|
12028
|
+
const selectFile = useCallback8(async (path2) => {
|
|
11725
12029
|
if (fileContents.has(path2)) {
|
|
11726
12030
|
setSelectedFile(path2);
|
|
11727
12031
|
setActivePane("editor");
|
|
@@ -11738,7 +12042,7 @@ function ConfigEditor() {
|
|
|
11738
12042
|
setStatusMessage(`Loaded: ${path2}`);
|
|
11739
12043
|
}, [fileContents]);
|
|
11740
12044
|
const prevContentRef = useRef9(currentContent);
|
|
11741
|
-
|
|
12045
|
+
useEffect14(() => {
|
|
11742
12046
|
if (!selectedFile || !currentContent)
|
|
11743
12047
|
return;
|
|
11744
12048
|
if (prevContentRef.current !== currentContent && prevContentRef.current !== "") {
|
|
@@ -11750,7 +12054,7 @@ function ConfigEditor() {
|
|
|
11750
12054
|
}
|
|
11751
12055
|
prevContentRef.current = currentContent;
|
|
11752
12056
|
}, [currentContent, selectedFile]);
|
|
11753
|
-
const handleSave =
|
|
12057
|
+
const handleSave = useCallback8(async () => {
|
|
11754
12058
|
if (!selectedFile)
|
|
11755
12059
|
return;
|
|
11756
12060
|
try {
|
|
@@ -11786,7 +12090,7 @@ function ConfigEditor() {
|
|
|
11786
12090
|
setStatusMessage(`Failed to save: ${msg}`);
|
|
11787
12091
|
}
|
|
11788
12092
|
}, [selectedFile, currentContent, fileType]);
|
|
11789
|
-
const handleValidate =
|
|
12093
|
+
const handleValidate = useCallback8(async () => {
|
|
11790
12094
|
if (!selectedFile)
|
|
11791
12095
|
return;
|
|
11792
12096
|
const errors = validateSyntax(currentContent, fileType);
|
|
@@ -11806,7 +12110,7 @@ function ConfigEditor() {
|
|
|
11806
12110
|
setStatusMessage("Validation passed \u2014 Config is valid");
|
|
11807
12111
|
}
|
|
11808
12112
|
}, [selectedFile, currentContent, fileType]);
|
|
11809
|
-
const handleDiff =
|
|
12113
|
+
const handleDiff = useCallback8(() => {
|
|
11810
12114
|
const original = selectedFile ? originalContents.get(selectedFile) ?? "" : "";
|
|
11811
12115
|
const origLines = original.split(`
|
|
11812
12116
|
`).length;
|
|
@@ -11819,7 +12123,7 @@ function ConfigEditor() {
|
|
|
11819
12123
|
setStatusMessage(`Diff: ${origLines} \u2192 ${currLines} lines (${diff > 0 ? "+" : ""}${diff})`);
|
|
11820
12124
|
}
|
|
11821
12125
|
}, [selectedFile, originalContents, currentContent]);
|
|
11822
|
-
const handleFormat =
|
|
12126
|
+
const handleFormat = useCallback8(() => {
|
|
11823
12127
|
if (!selectedFile)
|
|
11824
12128
|
return;
|
|
11825
12129
|
const formatted = formatContent(currentContent, fileType);
|
|
@@ -11829,7 +12133,7 @@ function ConfigEditor() {
|
|
|
11829
12133
|
}
|
|
11830
12134
|
setStatusMessage(`Formatted: ${selectedFile}`);
|
|
11831
12135
|
}, [selectedFile, currentContent, fileType]);
|
|
11832
|
-
const handleUndo =
|
|
12136
|
+
const handleUndo = useCallback8(() => {
|
|
11833
12137
|
if (undoStack.length === 0 || !selectedFile)
|
|
11834
12138
|
return;
|
|
11835
12139
|
const prev = undoStack[undoStack.length - 1];
|
|
@@ -11839,7 +12143,7 @@ function ConfigEditor() {
|
|
|
11839
12143
|
setUnsavedPaths((paths) => new Set(paths).add(selectedFile));
|
|
11840
12144
|
setStatusMessage("Undo");
|
|
11841
12145
|
}, [undoStack, currentContent, selectedFile]);
|
|
11842
|
-
const handleRedo =
|
|
12146
|
+
const handleRedo = useCallback8(() => {
|
|
11843
12147
|
if (redoStack.length === 0 || !selectedFile)
|
|
11844
12148
|
return;
|
|
11845
12149
|
const next = redoStack[redoStack.length - 1];
|
|
@@ -11851,7 +12155,7 @@ function ConfigEditor() {
|
|
|
11851
12155
|
}, [redoStack, currentContent, selectedFile]);
|
|
11852
12156
|
const [findMode, setFindMode] = useState12(false);
|
|
11853
12157
|
const [findQuery, setFindQuery] = useState12("");
|
|
11854
|
-
const handleFind =
|
|
12158
|
+
const handleFind = useCallback8(() => {
|
|
11855
12159
|
setFindMode((p) => !p);
|
|
11856
12160
|
if (!findMode) {
|
|
11857
12161
|
setFindQuery("");
|
|
@@ -12051,7 +12355,7 @@ function ConfigEditor() {
|
|
|
12051
12355
|
init_src();
|
|
12052
12356
|
init_src();
|
|
12053
12357
|
init_src();
|
|
12054
|
-
import { useState as useState13, useEffect as
|
|
12358
|
+
import { useState as useState13, useEffect as useEffect15, useCallback as useCallback9, useRef as useRef10 } from "react";
|
|
12055
12359
|
import { jsxDEV as jsxDEV22, Fragment as Fragment4 } from "@opentui/react/jsx-dev-runtime";
|
|
12056
12360
|
async function spawnVersion(cmd, flag) {
|
|
12057
12361
|
try {
|
|
@@ -12332,7 +12636,7 @@ function SetupWizard({ dialog }) {
|
|
|
12332
12636
|
const isActive = activeView === "setup-wizard";
|
|
12333
12637
|
const addAlert = useServiceStore((s) => s.addAlert);
|
|
12334
12638
|
const loadedRef = useRef10(false);
|
|
12335
|
-
const runChecks =
|
|
12639
|
+
const runChecks = useCallback9(async () => {
|
|
12336
12640
|
setPrereqsRunning(true);
|
|
12337
12641
|
setPrereqs([
|
|
12338
12642
|
{ label: "RUNTIME", checks: [await checkBun(), await checkGit()] },
|
|
@@ -12345,10 +12649,10 @@ function SetupWizard({ dialog }) {
|
|
|
12345
12649
|
]);
|
|
12346
12650
|
setPrereqsRunning(false);
|
|
12347
12651
|
}, []);
|
|
12348
|
-
|
|
12652
|
+
useEffect15(() => {
|
|
12349
12653
|
runChecks();
|
|
12350
12654
|
}, [runChecks]);
|
|
12351
|
-
|
|
12655
|
+
useEffect15(() => {
|
|
12352
12656
|
(async () => {
|
|
12353
12657
|
try {
|
|
12354
12658
|
const file = Bun.file("wrangler.jsonc");
|
|
@@ -12368,7 +12672,7 @@ function SetupWizard({ dialog }) {
|
|
|
12368
12672
|
} catch {}
|
|
12369
12673
|
})();
|
|
12370
12674
|
}, []);
|
|
12371
|
-
|
|
12675
|
+
useEffect15(() => {
|
|
12372
12676
|
(async () => {
|
|
12373
12677
|
try {
|
|
12374
12678
|
const f = Bun.file(WIZARD_SESSION_PATH);
|
|
@@ -13383,7 +13687,7 @@ Deploy error: ${err.message}
|
|
|
13383
13687
|
|
|
13384
13688
|
// src/components/views/settings.tsx
|
|
13385
13689
|
init_src();
|
|
13386
|
-
import { useMemo as
|
|
13690
|
+
import { useMemo as useMemo13, useState as useState14, useCallback as useCallback10, useEffect as useEffect16 } from "react";
|
|
13387
13691
|
import * as path2 from "path";
|
|
13388
13692
|
import * as os from "os";
|
|
13389
13693
|
import { jsxDEV as jsxDEV23, Fragment as Fragment5 } from "@opentui/react/jsx-dev-runtime";
|
|
@@ -13533,7 +13837,7 @@ function ThemePanel({
|
|
|
13533
13837
|
}) {
|
|
13534
13838
|
const refreshIntervalMs = useConfigStore((s) => s.refreshIntervalMs);
|
|
13535
13839
|
const defaultView = useConfigStore((s) => s.defaultView);
|
|
13536
|
-
const connection =
|
|
13840
|
+
const connection = useMemo13(() => {
|
|
13537
13841
|
let configFallback = {};
|
|
13538
13842
|
try {
|
|
13539
13843
|
const cfg = readConfigSync();
|
|
@@ -14075,12 +14379,12 @@ function SettingsView({ dialog } = {}) {
|
|
|
14075
14379
|
const resetDefaults = useConfigStore((s) => s.resetDefaults);
|
|
14076
14380
|
const toggleNotification = useConfigStore((s) => s.toggleNotification);
|
|
14077
14381
|
const soundEnabled = useConfigStore((s) => s.soundEnabled);
|
|
14078
|
-
|
|
14382
|
+
useEffect16(() => {
|
|
14079
14383
|
if (theme === "light") {
|
|
14080
14384
|
updateConfig({ theme: "dark" });
|
|
14081
14385
|
}
|
|
14082
14386
|
}, [theme, updateConfig]);
|
|
14083
|
-
const confirmAction =
|
|
14387
|
+
const confirmAction = useCallback10(async (title, message, confirmLabel) => {
|
|
14084
14388
|
if (!dialog) {
|
|
14085
14389
|
useServiceStore.getState().addAlert({
|
|
14086
14390
|
id: `settings-noconfirm-${Date.now()}`,
|
|
@@ -14099,7 +14403,7 @@ function SettingsView({ dialog } = {}) {
|
|
|
14099
14403
|
cancelLabel: "Cancel"
|
|
14100
14404
|
});
|
|
14101
14405
|
}, [dialog]);
|
|
14102
|
-
const handleClearCache =
|
|
14406
|
+
const handleClearCache = useCallback10(async () => {
|
|
14103
14407
|
const ok = await confirmAction("Clear Cache?", "Delete ~/.hoox/cache? This cannot be undone.", "Clear Cache");
|
|
14104
14408
|
if (!ok)
|
|
14105
14409
|
return;
|
|
@@ -14126,7 +14430,7 @@ function SettingsView({ dialog } = {}) {
|
|
|
14126
14430
|
});
|
|
14127
14431
|
}
|
|
14128
14432
|
}, [confirmAction]);
|
|
14129
|
-
const handleExportData =
|
|
14433
|
+
const handleExportData = useCallback10(async () => {
|
|
14130
14434
|
try {
|
|
14131
14435
|
const result = await cliBridge2().configShow();
|
|
14132
14436
|
if (!result.success) {
|
|
@@ -14162,11 +14466,11 @@ function SettingsView({ dialog } = {}) {
|
|
|
14162
14466
|
});
|
|
14163
14467
|
}
|
|
14164
14468
|
}, []);
|
|
14165
|
-
const handleImportData =
|
|
14469
|
+
const handleImportData = useCallback10(async () => {
|
|
14166
14470
|
setImporting(true);
|
|
14167
14471
|
setImportPath("");
|
|
14168
14472
|
}, []);
|
|
14169
|
-
const handleImportConfirm =
|
|
14473
|
+
const handleImportConfirm = useCallback10(async () => {
|
|
14170
14474
|
if (!importPath.trim())
|
|
14171
14475
|
return;
|
|
14172
14476
|
if (!dialog) {
|
|
@@ -14254,7 +14558,7 @@ function SettingsView({ dialog } = {}) {
|
|
|
14254
14558
|
setImporting(false);
|
|
14255
14559
|
setImportPath("");
|
|
14256
14560
|
}, [importPath, updateConfig, dialog]);
|
|
14257
|
-
const handleCheckSetup =
|
|
14561
|
+
const handleCheckSetup = useCallback10(async () => {
|
|
14258
14562
|
setSetupCheck({ kind: "running" });
|
|
14259
14563
|
try {
|
|
14260
14564
|
const result = await cliBridge2().checkSetup();
|
|
@@ -14317,10 +14621,10 @@ function SettingsView({ dialog } = {}) {
|
|
|
14317
14621
|
});
|
|
14318
14622
|
}
|
|
14319
14623
|
}, []);
|
|
14320
|
-
const dismissCheckSetup =
|
|
14624
|
+
const dismissCheckSetup = useCallback10(() => {
|
|
14321
14625
|
setSetupCheck({ kind: "idle" });
|
|
14322
14626
|
}, []);
|
|
14323
|
-
const handleRunAutoRepair =
|
|
14627
|
+
const handleRunAutoRepair = useCallback10(async () => {
|
|
14324
14628
|
const ok = await confirmAction("Run Auto-Repair?", "Apply non-destructive config fixes (placeholders, flags, worker configs). Continue?", "Run Repair");
|
|
14325
14629
|
if (!ok)
|
|
14326
14630
|
return;
|
|
@@ -14371,7 +14675,7 @@ function SettingsView({ dialog } = {}) {
|
|
|
14371
14675
|
});
|
|
14372
14676
|
}
|
|
14373
14677
|
}, [confirmAction]);
|
|
14374
|
-
const handleResetDefaults =
|
|
14678
|
+
const handleResetDefaults = useCallback10(async () => {
|
|
14375
14679
|
const ok = await confirmAction("Reset Defaults?", "Reset theme, refresh rate, default view, and notification preferences to factory defaults?", "Reset");
|
|
14376
14680
|
if (!ok)
|
|
14377
14681
|
return;
|
|
@@ -14385,13 +14689,13 @@ function SettingsView({ dialog } = {}) {
|
|
|
14385
14689
|
acknowledged: false
|
|
14386
14690
|
});
|
|
14387
14691
|
}, [confirmAction, resetDefaults]);
|
|
14388
|
-
|
|
14692
|
+
useEffect16(() => {
|
|
14389
14693
|
const g = globalThis;
|
|
14390
14694
|
if (g.__hooxTestAutoCheckSetup) {
|
|
14391
14695
|
handleCheckSetup();
|
|
14392
14696
|
}
|
|
14393
14697
|
}, []);
|
|
14394
|
-
const maxItemsPerPanel =
|
|
14698
|
+
const maxItemsPerPanel = useMemo13(() => {
|
|
14395
14699
|
return {
|
|
14396
14700
|
0: THEME_ITEM_COUNT,
|
|
14397
14701
|
1: NOTIF_ITEM_COUNT,
|
|
@@ -14619,7 +14923,7 @@ function SettingsView({ dialog } = {}) {
|
|
|
14619
14923
|
|
|
14620
14924
|
// src/components/views/queue-depth.tsx
|
|
14621
14925
|
init_src();
|
|
14622
|
-
import { useCallback as
|
|
14926
|
+
import { useCallback as useCallback11, useEffect as useEffect17, useMemo as useMemo14, useRef as useRef11, useState as useState15 } from "react";
|
|
14623
14927
|
import { jsxDEV as jsxDEV24 } from "@opentui/react/jsx-dev-runtime";
|
|
14624
14928
|
var REFRESH_INTERVAL_MS = 5000;
|
|
14625
14929
|
var STATUS_RANK = {
|
|
@@ -14802,7 +15106,7 @@ function QueueDepthView() {
|
|
|
14802
15106
|
const [error, setError] = useState15(null);
|
|
14803
15107
|
const [lastSampledAt, setLastSampledAt] = useState15(null);
|
|
14804
15108
|
const fetchGenRef = useRef11(0);
|
|
14805
|
-
const refresh =
|
|
15109
|
+
const refresh = useCallback11(async (opts) => {
|
|
14806
15110
|
const soft = opts?.soft === true;
|
|
14807
15111
|
const gen = ++fetchGenRef.current;
|
|
14808
15112
|
if (!soft)
|
|
@@ -14820,13 +15124,13 @@ function QueueDepthView() {
|
|
|
14820
15124
|
if (!soft || gen === fetchGenRef.current)
|
|
14821
15125
|
setLoading(false);
|
|
14822
15126
|
}, []);
|
|
14823
|
-
|
|
15127
|
+
useEffect17(() => {
|
|
14824
15128
|
refresh({ soft: false });
|
|
14825
15129
|
return () => {
|
|
14826
15130
|
fetchGenRef.current += 1;
|
|
14827
15131
|
};
|
|
14828
15132
|
}, [refresh]);
|
|
14829
|
-
|
|
15133
|
+
useEffect17(() => {
|
|
14830
15134
|
if (!isActive)
|
|
14831
15135
|
return;
|
|
14832
15136
|
const handle = setInterval(() => {
|
|
@@ -14841,7 +15145,7 @@ function QueueDepthView() {
|
|
|
14841
15145
|
refresh({ soft: false });
|
|
14842
15146
|
}
|
|
14843
15147
|
});
|
|
14844
|
-
const sortedQueues =
|
|
15148
|
+
const sortedQueues = useMemo14(() => sortQueuesByPressure(queues), [queues]);
|
|
14845
15149
|
return /* @__PURE__ */ jsxDEV24(ErrorBoundary, {
|
|
14846
15150
|
viewName: "Queue Depth",
|
|
14847
15151
|
children: /* @__PURE__ */ jsxDEV24("box", {
|
|
@@ -14988,7 +15292,7 @@ function QueueDepthView() {
|
|
|
14988
15292
|
|
|
14989
15293
|
// src/components/views/kv-viewer.tsx
|
|
14990
15294
|
init_src();
|
|
14991
|
-
import { useCallback as
|
|
15295
|
+
import { useCallback as useCallback12, useEffect as useEffect18, useMemo as useMemo15, useRef as useRef12, useState as useState16 } from "react";
|
|
14992
15296
|
import { jsxDEV as jsxDEV25 } from "@opentui/react/jsx-dev-runtime";
|
|
14993
15297
|
var REFRESH_INTERVAL_MS2 = 5000;
|
|
14994
15298
|
var MAX_VISIBLE_KEYS = 200;
|
|
@@ -15288,7 +15592,7 @@ function KvViewer() {
|
|
|
15288
15592
|
const [valueError, setValueError] = useState16(null);
|
|
15289
15593
|
const listGenRef = useRef12(0);
|
|
15290
15594
|
const revealGenRef = useRef12(0);
|
|
15291
|
-
|
|
15595
|
+
useEffect18(() => {
|
|
15292
15596
|
if (searchTimerRef.current)
|
|
15293
15597
|
clearTimeout(searchTimerRef.current);
|
|
15294
15598
|
searchTimerRef.current = setTimeout(() => {
|
|
@@ -15302,7 +15606,7 @@ function KvViewer() {
|
|
|
15302
15606
|
}
|
|
15303
15607
|
};
|
|
15304
15608
|
}, [search]);
|
|
15305
|
-
const refresh =
|
|
15609
|
+
const refresh = useCallback12(async (opts) => {
|
|
15306
15610
|
const soft = opts?.soft === true;
|
|
15307
15611
|
const gen = ++listGenRef.current;
|
|
15308
15612
|
if (!soft)
|
|
@@ -15318,14 +15622,14 @@ function KvViewer() {
|
|
|
15318
15622
|
}
|
|
15319
15623
|
setLoading(false);
|
|
15320
15624
|
}, []);
|
|
15321
|
-
|
|
15625
|
+
useEffect18(() => {
|
|
15322
15626
|
refresh({ soft: false });
|
|
15323
15627
|
return () => {
|
|
15324
15628
|
listGenRef.current += 1;
|
|
15325
15629
|
revealGenRef.current += 1;
|
|
15326
15630
|
};
|
|
15327
15631
|
}, [refresh]);
|
|
15328
|
-
|
|
15632
|
+
useEffect18(() => {
|
|
15329
15633
|
if (!isActive)
|
|
15330
15634
|
return;
|
|
15331
15635
|
const handle = setInterval(() => {
|
|
@@ -15334,22 +15638,22 @@ function KvViewer() {
|
|
|
15334
15638
|
return () => clearInterval(handle);
|
|
15335
15639
|
}, [isActive, refresh]);
|
|
15336
15640
|
const allKeys = snapshot?.keys ?? [];
|
|
15337
|
-
const filteredKeys =
|
|
15338
|
-
const visibleKeys =
|
|
15339
|
-
const secretCount =
|
|
15340
|
-
const selectedKey =
|
|
15641
|
+
const filteredKeys = useMemo15(() => filterKvKeys(allKeys, debouncedSearch), [allKeys, debouncedSearch]);
|
|
15642
|
+
const visibleKeys = useMemo15(() => filteredKeys.slice(0, MAX_VISIBLE_KEYS), [filteredKeys]);
|
|
15643
|
+
const secretCount = useMemo15(() => allKeys.filter((k) => k.isSecret).length, [allKeys]);
|
|
15644
|
+
const selectedKey = useMemo15(() => {
|
|
15341
15645
|
if (!selectedKeyName)
|
|
15342
15646
|
return null;
|
|
15343
15647
|
return allKeys.find((k) => k.name === selectedKeyName) ?? null;
|
|
15344
15648
|
}, [allKeys, selectedKeyName]);
|
|
15345
|
-
|
|
15649
|
+
useEffect18(() => {
|
|
15346
15650
|
revealGenRef.current += 1;
|
|
15347
15651
|
setRevealed(false);
|
|
15348
15652
|
setValue(null);
|
|
15349
15653
|
setValueError(null);
|
|
15350
15654
|
setValueLoading(false);
|
|
15351
15655
|
}, [selectedKeyName]);
|
|
15352
|
-
const handleReveal =
|
|
15656
|
+
const handleReveal = useCallback12(async () => {
|
|
15353
15657
|
if (!selectedKey)
|
|
15354
15658
|
return;
|
|
15355
15659
|
const gen = ++revealGenRef.current;
|
|
@@ -15366,7 +15670,7 @@ function KvViewer() {
|
|
|
15366
15670
|
}
|
|
15367
15671
|
setValueLoading(false);
|
|
15368
15672
|
}, [selectedKey]);
|
|
15369
|
-
const handleHide =
|
|
15673
|
+
const handleHide = useCallback12(() => {
|
|
15370
15674
|
revealGenRef.current += 1;
|
|
15371
15675
|
setRevealed(false);
|
|
15372
15676
|
setValue(null);
|
|
@@ -15652,7 +15956,7 @@ function KvViewer() {
|
|
|
15652
15956
|
|
|
15653
15957
|
// src/components/views/secrets-viewer.tsx
|
|
15654
15958
|
init_src();
|
|
15655
|
-
import { useCallback as
|
|
15959
|
+
import { useCallback as useCallback13, useEffect as useEffect19, useMemo as useMemo16, useRef as useRef13, useState as useState17 } from "react";
|
|
15656
15960
|
import { jsxDEV as jsxDEV26 } from "@opentui/react/jsx-dev-runtime";
|
|
15657
15961
|
var REFRESH_INTERVAL_MS3 = 5000;
|
|
15658
15962
|
var MAX_VISIBLE_SECRETS = 200;
|
|
@@ -15764,7 +16068,7 @@ function SecretsViewer() {
|
|
|
15764
16068
|
const searchTimerRef = useRef13(null);
|
|
15765
16069
|
const listGenRef = useRef13(0);
|
|
15766
16070
|
const [selectedSecretName, setSelectedSecretName] = useState17(null);
|
|
15767
|
-
|
|
16071
|
+
useEffect19(() => {
|
|
15768
16072
|
if (searchTimerRef.current)
|
|
15769
16073
|
clearTimeout(searchTimerRef.current);
|
|
15770
16074
|
searchTimerRef.current = setTimeout(() => {
|
|
@@ -15778,7 +16082,7 @@ function SecretsViewer() {
|
|
|
15778
16082
|
}
|
|
15779
16083
|
};
|
|
15780
16084
|
}, [search]);
|
|
15781
|
-
const refresh =
|
|
16085
|
+
const refresh = useCallback13(async (opts) => {
|
|
15782
16086
|
const soft = opts?.soft === true;
|
|
15783
16087
|
const gen = ++listGenRef.current;
|
|
15784
16088
|
if (!soft)
|
|
@@ -15794,13 +16098,13 @@ function SecretsViewer() {
|
|
|
15794
16098
|
}
|
|
15795
16099
|
setLoading(false);
|
|
15796
16100
|
}, []);
|
|
15797
|
-
|
|
16101
|
+
useEffect19(() => {
|
|
15798
16102
|
refresh({ soft: false });
|
|
15799
16103
|
return () => {
|
|
15800
16104
|
listGenRef.current += 1;
|
|
15801
16105
|
};
|
|
15802
16106
|
}, [refresh]);
|
|
15803
|
-
|
|
16107
|
+
useEffect19(() => {
|
|
15804
16108
|
if (!isActive)
|
|
15805
16109
|
return;
|
|
15806
16110
|
const handle = setInterval(() => {
|
|
@@ -15809,9 +16113,9 @@ function SecretsViewer() {
|
|
|
15809
16113
|
return () => clearInterval(handle);
|
|
15810
16114
|
}, [isActive, refresh]);
|
|
15811
16115
|
const allSecrets = snapshot?.secrets ?? [];
|
|
15812
|
-
const filteredSecrets =
|
|
15813
|
-
const visibleSecrets =
|
|
15814
|
-
const selectedSecret =
|
|
16116
|
+
const filteredSecrets = useMemo16(() => filterSecrets(allSecrets, debouncedSearch), [allSecrets, debouncedSearch]);
|
|
16117
|
+
const visibleSecrets = useMemo16(() => filteredSecrets.slice(0, MAX_VISIBLE_SECRETS), [filteredSecrets]);
|
|
16118
|
+
const selectedSecret = useMemo16(() => {
|
|
15815
16119
|
if (!selectedSecretName)
|
|
15816
16120
|
return null;
|
|
15817
16121
|
return allSecrets.find((s) => s.name === selectedSecretName) ?? null;
|
|
@@ -16179,7 +16483,7 @@ function SecretsViewer() {
|
|
|
16179
16483
|
|
|
16180
16484
|
// src/components/views/ai-chat.tsx
|
|
16181
16485
|
init_src();
|
|
16182
|
-
import { useCallback as
|
|
16486
|
+
import { useCallback as useCallback14, useEffect as useEffect20, useRef as useRef14, useState as useState18 } from "react";
|
|
16183
16487
|
|
|
16184
16488
|
// src/services/tui-storage.ts
|
|
16185
16489
|
import { rename, unlink } from "fs/promises";
|
|
@@ -16366,7 +16670,7 @@ function AiChatView() {
|
|
|
16366
16670
|
const currentStreamRef = useRef14(null);
|
|
16367
16671
|
const scrollRef = useRef14(null);
|
|
16368
16672
|
const [confirmClear, setConfirmClear] = useState18(false);
|
|
16369
|
-
|
|
16673
|
+
useEffect20(() => {
|
|
16370
16674
|
let cancelled = false;
|
|
16371
16675
|
(async () => {
|
|
16372
16676
|
const stored = await readJsonState(TuiStateFiles.chatHistory, []);
|
|
@@ -16381,13 +16685,13 @@ function AiChatView() {
|
|
|
16381
16685
|
cancelled = true;
|
|
16382
16686
|
};
|
|
16383
16687
|
}, []);
|
|
16384
|
-
|
|
16688
|
+
useEffect20(() => {
|
|
16385
16689
|
if (!historyReady)
|
|
16386
16690
|
return;
|
|
16387
16691
|
const trimmed = sanitizeChatHistory(messages);
|
|
16388
16692
|
writeJsonState(TuiStateFiles.chatHistory, trimmed);
|
|
16389
16693
|
}, [messages, historyReady]);
|
|
16390
|
-
|
|
16694
|
+
useEffect20(() => {
|
|
16391
16695
|
if (!isActive && currentStreamRef.current) {
|
|
16392
16696
|
currentStreamRef.current.abort();
|
|
16393
16697
|
currentStreamRef.current = null;
|
|
@@ -16395,7 +16699,7 @@ function AiChatView() {
|
|
|
16395
16699
|
setStreamingContent("");
|
|
16396
16700
|
}
|
|
16397
16701
|
}, [isActive]);
|
|
16398
|
-
|
|
16702
|
+
useEffect20(() => {
|
|
16399
16703
|
return () => {
|
|
16400
16704
|
if (currentStreamRef.current) {
|
|
16401
16705
|
currentStreamRef.current.abort();
|
|
@@ -16407,15 +16711,15 @@ function AiChatView() {
|
|
|
16407
16711
|
}
|
|
16408
16712
|
};
|
|
16409
16713
|
}, []);
|
|
16410
|
-
const scheduleScroll =
|
|
16714
|
+
const scheduleScroll = useCallback14(() => {
|
|
16411
16715
|
if (scrollRef.current)
|
|
16412
16716
|
clearTimeout(scrollRef.current);
|
|
16413
16717
|
scrollRef.current = setTimeout(() => {}, 50);
|
|
16414
16718
|
}, []);
|
|
16415
|
-
|
|
16719
|
+
useEffect20(() => {
|
|
16416
16720
|
scheduleScroll();
|
|
16417
16721
|
}, [messages, streamingContent, scheduleScroll]);
|
|
16418
|
-
const sendMessage =
|
|
16722
|
+
const sendMessage = useCallback14(async () => {
|
|
16419
16723
|
const trimmed = inputText.trim();
|
|
16420
16724
|
if (!trimmed || isStreaming)
|
|
16421
16725
|
return;
|
|
@@ -16471,13 +16775,13 @@ function AiChatView() {
|
|
|
16471
16775
|
currentStreamRef.current = null;
|
|
16472
16776
|
}
|
|
16473
16777
|
}, [inputText, isStreaming, messages, selectedModel]);
|
|
16474
|
-
const handleInputKeyDown =
|
|
16778
|
+
const handleInputKeyDown = useCallback14((event) => {
|
|
16475
16779
|
if (event.key === "Enter" && !event.shiftKey) {
|
|
16476
16780
|
event.preventDefault();
|
|
16477
16781
|
sendMessage();
|
|
16478
16782
|
}
|
|
16479
16783
|
}, [sendMessage]);
|
|
16480
|
-
|
|
16784
|
+
useEffect20(() => {
|
|
16481
16785
|
if (isActive) {}
|
|
16482
16786
|
}, [isActive]);
|
|
16483
16787
|
const statusColor2 = streamStatus === "connected" ? ConnectionStatusColor.connected : streamStatus === "reconnecting" ? ConnectionStatusColor.reconnecting : streamStatus === "disconnected" ? ConnectionStatusColor.offline : Colors.muted;
|
|
@@ -16625,7 +16929,7 @@ function AiChatView() {
|
|
|
16625
16929
|
|
|
16626
16930
|
// src/components/views/db-query.tsx
|
|
16627
16931
|
init_src();
|
|
16628
|
-
import { useCallback as
|
|
16932
|
+
import { useCallback as useCallback15, useEffect as useEffect21, useMemo as useMemo17, useRef as useRef15, useState as useState19 } from "react";
|
|
16629
16933
|
import { jsxDEV as jsxDEV28, Fragment as Fragment6 } from "@opentui/react/jsx-dev-runtime";
|
|
16630
16934
|
var MAX_HISTORY = 20;
|
|
16631
16935
|
var MAX_VISIBLE_ROWS = 200;
|
|
@@ -16943,7 +17247,7 @@ function DbQueryView() {
|
|
|
16943
17247
|
const [sortDir, setSortDir] = useState19("asc");
|
|
16944
17248
|
const [selectedRow, setSelectedRow] = useState19(0);
|
|
16945
17249
|
const queryGenRef = useRef15(0);
|
|
16946
|
-
|
|
17250
|
+
useEffect21(() => {
|
|
16947
17251
|
let cancelled = false;
|
|
16948
17252
|
(async () => {
|
|
16949
17253
|
const stored = await readJsonState(TuiStateFiles.dbQueryHistory, []);
|
|
@@ -16959,12 +17263,12 @@ function DbQueryView() {
|
|
|
16959
17263
|
queryGenRef.current += 1;
|
|
16960
17264
|
};
|
|
16961
17265
|
}, []);
|
|
16962
|
-
|
|
17266
|
+
useEffect21(() => {
|
|
16963
17267
|
if (!historyReady)
|
|
16964
17268
|
return;
|
|
16965
17269
|
writeJsonState(TuiStateFiles.dbQueryHistory, history);
|
|
16966
17270
|
}, [history, historyReady]);
|
|
16967
|
-
const executeQuery =
|
|
17271
|
+
const executeQuery = useCallback15(async (query) => {
|
|
16968
17272
|
const trimmed = query.trim();
|
|
16969
17273
|
if (trimmed.length === 0)
|
|
16970
17274
|
return;
|
|
@@ -16997,7 +17301,7 @@ function DbQueryView() {
|
|
|
16997
17301
|
}
|
|
16998
17302
|
setLoading(false);
|
|
16999
17303
|
}, []);
|
|
17000
|
-
|
|
17304
|
+
useEffect21(() => {
|
|
17001
17305
|
if (sql.trim().length === 0) {
|
|
17002
17306
|
setValidation(null);
|
|
17003
17307
|
return;
|
|
@@ -17005,13 +17309,13 @@ function DbQueryView() {
|
|
|
17005
17309
|
const v = validateReadOnlySql(sql.trim());
|
|
17006
17310
|
setValidation(v);
|
|
17007
17311
|
}, [sql]);
|
|
17008
|
-
const handleActivateInput =
|
|
17312
|
+
const handleActivateInput = useCallback15(() => {
|
|
17009
17313
|
setInputActive(true);
|
|
17010
17314
|
}, []);
|
|
17011
|
-
const handleDeactivateInput =
|
|
17315
|
+
const handleDeactivateInput = useCallback15(() => {
|
|
17012
17316
|
setInputActive(false);
|
|
17013
17317
|
}, []);
|
|
17014
|
-
const handleSort =
|
|
17318
|
+
const handleSort = useCallback15((col) => {
|
|
17015
17319
|
setSortCol((prev) => {
|
|
17016
17320
|
if (prev === col) {
|
|
17017
17321
|
setSortDir((d) => d === "asc" ? "desc" : "asc");
|
|
@@ -17021,7 +17325,7 @@ function DbQueryView() {
|
|
|
17021
17325
|
return col;
|
|
17022
17326
|
});
|
|
17023
17327
|
}, []);
|
|
17024
|
-
const handleHistoryUp =
|
|
17328
|
+
const handleHistoryUp = useCallback15(() => {
|
|
17025
17329
|
if (history.length === 0)
|
|
17026
17330
|
return;
|
|
17027
17331
|
const next = Math.min(historyIdx + 1, history.length - 1);
|
|
@@ -17029,7 +17333,7 @@ function DbQueryView() {
|
|
|
17029
17333
|
setSql(history[next] ?? "");
|
|
17030
17334
|
setValidation(null);
|
|
17031
17335
|
}, [history, historyIdx]);
|
|
17032
|
-
const handleHistoryDown =
|
|
17336
|
+
const handleHistoryDown = useCallback15(() => {
|
|
17033
17337
|
if (historyIdx <= 0) {
|
|
17034
17338
|
setHistoryIdx(-1);
|
|
17035
17339
|
setSql("");
|
|
@@ -17091,13 +17395,13 @@ function DbQueryView() {
|
|
|
17091
17395
|
});
|
|
17092
17396
|
const columns = result?.columns ?? [];
|
|
17093
17397
|
const rows = result?.rows ?? [];
|
|
17094
|
-
const sortedRows =
|
|
17398
|
+
const sortedRows = useMemo17(() => {
|
|
17095
17399
|
if (!sortCol || rows.length === 0)
|
|
17096
17400
|
return rows;
|
|
17097
17401
|
return [...rows].sort((a, b) => compareCells(a[sortCol], b[sortCol], sortDir));
|
|
17098
17402
|
}, [rows, sortCol, sortDir]);
|
|
17099
|
-
const visibleRows =
|
|
17100
|
-
const columnWidths =
|
|
17403
|
+
const visibleRows = useMemo17(() => sortedRows.slice(0, MAX_VISIBLE_ROWS), [sortedRows]);
|
|
17404
|
+
const columnWidths = useMemo17(() => computeColumnWidths(columns, visibleRows), [columns, visibleRows]);
|
|
17101
17405
|
const totalWidth = columns.reduce((acc, col) => acc + (columnWidths.get(col) ?? COLUMN_WIDTH_STRATEGY.fallback) + 1, 0);
|
|
17102
17406
|
return /* @__PURE__ */ jsxDEV28(ErrorBoundary, {
|
|
17103
17407
|
viewName: "DB Query",
|
|
@@ -17309,7 +17613,7 @@ function DbQueryView() {
|
|
|
17309
17613
|
|
|
17310
17614
|
// src/components/views/edge-topology.tsx
|
|
17311
17615
|
init_src();
|
|
17312
|
-
import { useState as useState20, useEffect as
|
|
17616
|
+
import { useState as useState20, useEffect as useEffect22, useMemo as useMemo18 } from "react";
|
|
17313
17617
|
import * as fs from "fs";
|
|
17314
17618
|
import * as path3 from "path";
|
|
17315
17619
|
import { jsxDEV as jsxDEV29, Fragment as Fragment7 } from "@opentui/react/jsx-dev-runtime";
|
|
@@ -17358,7 +17662,7 @@ function EdgeTopologyInner() {
|
|
|
17358
17662
|
const [selectedNode, setSelectedNode] = useState20(null);
|
|
17359
17663
|
const [activeCommunity, setActiveCommunity] = useState20(null);
|
|
17360
17664
|
const [focusedIndex, setFocusedIndex] = useState20(0);
|
|
17361
|
-
|
|
17665
|
+
useEffect22(() => {
|
|
17362
17666
|
let cancelled = false;
|
|
17363
17667
|
try {
|
|
17364
17668
|
const graphPath = resolveGraphMetadataPath();
|
|
@@ -17384,7 +17688,7 @@ function EdgeTopologyInner() {
|
|
|
17384
17688
|
const workers = metadata ? Object.entries(metadata.workers) : [];
|
|
17385
17689
|
const infra = metadata ? Object.entries(metadata.infrastructure) : [];
|
|
17386
17690
|
const communities = metadata ? metadata.communities : [];
|
|
17387
|
-
const selectableItems =
|
|
17691
|
+
const selectableItems = useMemo18(() => {
|
|
17388
17692
|
if (!metadata)
|
|
17389
17693
|
return [];
|
|
17390
17694
|
const visibleWorkers = activeCommunity ? workers.filter(([id]) => communities.find((c) => c.id === activeCommunity)?.nodeIds.includes(`workspace:${id}`)) : workers;
|
|
@@ -17400,7 +17704,7 @@ function EdgeTopologyInner() {
|
|
|
17400
17704
|
...visibleInfra.map(([id]) => ({ type: "infra", id }))
|
|
17401
17705
|
];
|
|
17402
17706
|
}, [metadata, activeCommunity, workers, infra, communities]);
|
|
17403
|
-
|
|
17707
|
+
useEffect22(() => {
|
|
17404
17708
|
if (selectableItems.length === 0) {
|
|
17405
17709
|
setFocusedIndex(0);
|
|
17406
17710
|
return;
|
|
@@ -17839,7 +18143,7 @@ function EdgeTopologyInner() {
|
|
|
17839
18143
|
|
|
17840
18144
|
// src/components/views/worker-settings.tsx
|
|
17841
18145
|
init_src();
|
|
17842
|
-
import { useCallback as
|
|
18146
|
+
import { useCallback as useCallback16, useEffect as useEffect23, useMemo as useMemo19, useRef as useRef16, useState as useState21 } from "react";
|
|
17843
18147
|
|
|
17844
18148
|
// src/services/dashboard-settings-loader.ts
|
|
17845
18149
|
init_src();
|
|
@@ -17897,7 +18201,7 @@ function WorkerSettingsView() {
|
|
|
17897
18201
|
const [pendingDangerousKey, setPendingDangerousKey] = useState21(null);
|
|
17898
18202
|
const loadGeneration = useRef16(0);
|
|
17899
18203
|
const selected = manifests2[workerIndex] ?? null;
|
|
17900
|
-
const flatFields =
|
|
18204
|
+
const flatFields = useMemo19(() => {
|
|
17901
18205
|
if (!selected)
|
|
17902
18206
|
return [];
|
|
17903
18207
|
const out = [];
|
|
@@ -17915,7 +18219,7 @@ function WorkerSettingsView() {
|
|
|
17915
18219
|
}
|
|
17916
18220
|
return out;
|
|
17917
18221
|
}, [selected]);
|
|
17918
|
-
const loadValues =
|
|
18222
|
+
const loadValues = useCallback16(async (manifest) => {
|
|
17919
18223
|
const gen = ++loadGeneration.current;
|
|
17920
18224
|
const fields = [];
|
|
17921
18225
|
for (const section of manifest.sections) {
|
|
@@ -17952,7 +18256,7 @@ function WorkerSettingsView() {
|
|
|
17952
18256
|
next[k] = v;
|
|
17953
18257
|
setValues(next);
|
|
17954
18258
|
}, []);
|
|
17955
|
-
const refresh =
|
|
18259
|
+
const refresh = useCallback16(async () => {
|
|
17956
18260
|
setLoading(true);
|
|
17957
18261
|
setError(null);
|
|
17958
18262
|
try {
|
|
@@ -17972,12 +18276,12 @@ function WorkerSettingsView() {
|
|
|
17972
18276
|
setLoading(false);
|
|
17973
18277
|
}
|
|
17974
18278
|
}, [loadValues, workerIndex]);
|
|
17975
|
-
|
|
18279
|
+
useEffect23(() => {
|
|
17976
18280
|
if (!isActive)
|
|
17977
18281
|
return;
|
|
17978
18282
|
refresh();
|
|
17979
18283
|
}, [isActive]);
|
|
17980
|
-
const selectWorker =
|
|
18284
|
+
const selectWorker = useCallback16(async (idx) => {
|
|
17981
18285
|
if (idx < 0 || idx >= manifests2.length)
|
|
17982
18286
|
return;
|
|
17983
18287
|
setWorkerIndex(idx);
|
|
@@ -17991,7 +18295,7 @@ function WorkerSettingsView() {
|
|
|
17991
18295
|
setLoading(false);
|
|
17992
18296
|
}
|
|
17993
18297
|
}, [manifests2, loadValues]);
|
|
17994
|
-
const cycleFieldValue =
|
|
18298
|
+
const cycleFieldValue = useCallback16((delta) => {
|
|
17995
18299
|
const row = flatFields[fieldIndex];
|
|
17996
18300
|
if (!row || row.field.kind === "secret")
|
|
17997
18301
|
return;
|
|
@@ -18024,7 +18328,7 @@ function WorkerSettingsView() {
|
|
|
18024
18328
|
}));
|
|
18025
18329
|
}
|
|
18026
18330
|
}, [flatFields, fieldIndex, values]);
|
|
18027
|
-
const saveCurrent =
|
|
18331
|
+
const saveCurrent = useCallback16(async () => {
|
|
18028
18332
|
const row = flatFields[fieldIndex];
|
|
18029
18333
|
if (!row || !selected)
|
|
18030
18334
|
return;
|
|
@@ -18603,7 +18907,7 @@ var ALL_PALETTE_COMMANDS = [
|
|
|
18603
18907
|
|
|
18604
18908
|
// src/components/shared/crash-screen.tsx
|
|
18605
18909
|
init_src();
|
|
18606
|
-
import { useKeyboard as
|
|
18910
|
+
import { useKeyboard as useKeyboard5 } from "@opentui/react";
|
|
18607
18911
|
import { jsxDEV as jsxDEV32 } from "@opentui/react/jsx-dev-runtime";
|
|
18608
18912
|
function formatCrashMessage(error, maxLen = 120) {
|
|
18609
18913
|
const first = (error.message || "Unknown error").split(`
|
|
@@ -18621,7 +18925,7 @@ function CrashScreen({
|
|
|
18621
18925
|
`) ? error.message.split(`
|
|
18622
18926
|
`)[1] : undefined;
|
|
18623
18927
|
const secondLine = secondRaw ? redactSecretsInText(secondRaw).slice(0, 80) : undefined;
|
|
18624
|
-
|
|
18928
|
+
useKeyboard5((key) => {
|
|
18625
18929
|
const name = String(key.name ?? "").toLowerCase();
|
|
18626
18930
|
if (name === "r" || name === "1") {
|
|
18627
18931
|
onAction("restart");
|
|
@@ -18750,8 +19054,8 @@ function CrashScreen({
|
|
|
18750
19054
|
|
|
18751
19055
|
// src/components/shared/command-palette.tsx
|
|
18752
19056
|
init_src();
|
|
18753
|
-
import { useState as useState22, useMemo as
|
|
18754
|
-
import { useKeyboard as
|
|
19057
|
+
import { useState as useState22, useMemo as useMemo20, useEffect as useEffect24 } from "react";
|
|
19058
|
+
import { useKeyboard as useKeyboard6 } from "@opentui/react";
|
|
18755
19059
|
import { jsxDEV as jsxDEV33 } from "@opentui/react/jsx-dev-runtime";
|
|
18756
19060
|
var CATEGORY_BADGE = {
|
|
18757
19061
|
view: { label: "view", color: Colors.info },
|
|
@@ -18804,20 +19108,20 @@ function CommandPalette({
|
|
|
18804
19108
|
}) {
|
|
18805
19109
|
const [query, setQuery] = useState22("");
|
|
18806
19110
|
const [selectedIndex, setSelectedIndex] = useState22(0);
|
|
18807
|
-
const filtered =
|
|
19111
|
+
const filtered = useMemo20(() => filterCommands(commands, query), [commands, query]);
|
|
18808
19112
|
const safeIndex = filtered.length === 0 ? 0 : Math.min(selectedIndex, filtered.length - 1);
|
|
18809
|
-
|
|
19113
|
+
useEffect24(() => {
|
|
18810
19114
|
if (!visible) {
|
|
18811
19115
|
setQuery("");
|
|
18812
19116
|
setSelectedIndex(0);
|
|
18813
19117
|
}
|
|
18814
19118
|
}, [visible]);
|
|
18815
|
-
|
|
19119
|
+
useEffect24(() => {
|
|
18816
19120
|
if (selectedIndex !== safeIndex) {
|
|
18817
19121
|
setSelectedIndex(safeIndex);
|
|
18818
19122
|
}
|
|
18819
19123
|
}, [safeIndex, selectedIndex]);
|
|
18820
|
-
|
|
19124
|
+
useKeyboard6((key) => {
|
|
18821
19125
|
if (!visible)
|
|
18822
19126
|
return;
|
|
18823
19127
|
if (key.name === "escape") {
|
|
@@ -19052,8 +19356,8 @@ function QuitModal({
|
|
|
19052
19356
|
|
|
19053
19357
|
// src/components/layout/statusbar.tsx
|
|
19054
19358
|
init_src();
|
|
19055
|
-
import { useCallback as
|
|
19056
|
-
import { useKeyboard as
|
|
19359
|
+
import { useCallback as useCallback17, memo } from "react";
|
|
19360
|
+
import { useKeyboard as useKeyboard7 } from "@opentui/react";
|
|
19057
19361
|
import { jsxDEV as jsxDEV35 } from "@opentui/react/jsx-dev-runtime";
|
|
19058
19362
|
var ERROR_TYPE_LABELS = {
|
|
19059
19363
|
"binary-not-found": "CLI binary not found",
|
|
@@ -19266,10 +19570,10 @@ function StatusBar() {
|
|
|
19266
19570
|
const authReady = conn.hasAuth;
|
|
19267
19571
|
const errorKind = classifyConnectionError(lastError);
|
|
19268
19572
|
const showAuthHint = tuiMode === "remote" && (!authReady || errorKind === "auth" || Boolean(lastError?.includes("401")));
|
|
19269
|
-
const toggleError =
|
|
19573
|
+
const toggleError = useCallback17(() => {
|
|
19270
19574
|
toggleStatusErrorExpanded();
|
|
19271
19575
|
}, [toggleStatusErrorExpanded]);
|
|
19272
|
-
|
|
19576
|
+
useKeyboard7((key) => {
|
|
19273
19577
|
if (isShellOverlayOpen())
|
|
19274
19578
|
return;
|
|
19275
19579
|
const name = String(key.name ?? "").toLowerCase();
|
|
@@ -19461,9 +19765,6 @@ function quitApp() {
|
|
|
19461
19765
|
}
|
|
19462
19766
|
function AppRoot({ safeMode = false }) {
|
|
19463
19767
|
return /* @__PURE__ */ jsxDEV37(DialogProvider, {
|
|
19464
|
-
size: "medium",
|
|
19465
|
-
backdropColor: Colors.backdrop,
|
|
19466
|
-
backdropOpacity: 0.35,
|
|
19467
19768
|
children: /* @__PURE__ */ jsxDEV37(AppRootInner, {
|
|
19468
19769
|
safeMode
|
|
19469
19770
|
}, undefined, false, undefined, this)
|
|
@@ -19481,7 +19782,7 @@ function AppRootInner({ safeMode = false }) {
|
|
|
19481
19782
|
const closePalette = useUIStore((s) => s.closePalette);
|
|
19482
19783
|
const showModal = useUIStore((s) => s.showModal);
|
|
19483
19784
|
const dismissModal = useUIStore((s) => s.dismissModal);
|
|
19484
|
-
const requestQuit =
|
|
19785
|
+
const requestQuit = useCallback18(() => {
|
|
19485
19786
|
closePalette();
|
|
19486
19787
|
showModal({
|
|
19487
19788
|
type: "confirm",
|
|
@@ -19491,7 +19792,7 @@ function AppRootInner({ safeMode = false }) {
|
|
|
19491
19792
|
onCancel: () => dismissModal()
|
|
19492
19793
|
});
|
|
19493
19794
|
}, [closePalette, showModal, dismissModal]);
|
|
19494
|
-
|
|
19795
|
+
useEffect25(() => {
|
|
19495
19796
|
let cancelled = false;
|
|
19496
19797
|
(async () => {
|
|
19497
19798
|
const session = await restoreSession();
|
|
@@ -19511,7 +19812,7 @@ function AppRootInner({ safeMode = false }) {
|
|
|
19511
19812
|
cancelled = true;
|
|
19512
19813
|
};
|
|
19513
19814
|
}, [setView, toggleSidebar]);
|
|
19514
|
-
|
|
19815
|
+
useEffect25(() => {
|
|
19515
19816
|
if (restoring)
|
|
19516
19817
|
return;
|
|
19517
19818
|
if (safeMode) {
|
|
@@ -19640,7 +19941,7 @@ function AppRootInner({ safeMode = false }) {
|
|
|
19640
19941
|
useServiceStore.getState().stopStreams();
|
|
19641
19942
|
};
|
|
19642
19943
|
}, [restoring, safeMode]);
|
|
19643
|
-
|
|
19944
|
+
useEffect25(() => {
|
|
19644
19945
|
if (restoring)
|
|
19645
19946
|
return;
|
|
19646
19947
|
const conn = resolveTuiConnectionEnv();
|
|
@@ -19669,19 +19970,19 @@ function AppRootInner({ safeMode = false }) {
|
|
|
19669
19970
|
});
|
|
19670
19971
|
return unsub;
|
|
19671
19972
|
}, [restoring]);
|
|
19672
|
-
|
|
19973
|
+
useEffect25(() => {
|
|
19673
19974
|
return () => {
|
|
19674
19975
|
const lastUpdated = useServiceStore.getState().lastUpdated;
|
|
19675
19976
|
saveSession(useUIStore.getState().activeView, useUIStore.getState().sidebarExpanded, { cols: 80, rows: 24 }, lastUpdated).catch(() => {});
|
|
19676
19977
|
};
|
|
19677
19978
|
}, []);
|
|
19678
|
-
|
|
19979
|
+
useEffect25(() => {
|
|
19679
19980
|
const unsubscribe = cliBridge.onError((details) => {
|
|
19680
19981
|
useServiceStore.getState().setLastErrorDetails(details);
|
|
19681
19982
|
});
|
|
19682
19983
|
return unsubscribe;
|
|
19683
19984
|
}, []);
|
|
19684
|
-
const onGlobalKey =
|
|
19985
|
+
const onGlobalKey = useCallback18((key) => {
|
|
19685
19986
|
const name = String(key.name ?? "").toLowerCase();
|
|
19686
19987
|
if (modal?.type === "confirm" && modal.title === "Quit HOOX?") {
|
|
19687
19988
|
if (name === "return" || name === "enter" || name === "y") {
|
|
@@ -19766,7 +20067,7 @@ function AppRootInner({ safeMode = false }) {
|
|
|
19766
20067
|
requestQuit,
|
|
19767
20068
|
safeMode
|
|
19768
20069
|
]);
|
|
19769
|
-
|
|
20070
|
+
useKeyboard8(onGlobalKey);
|
|
19770
20071
|
if (restoring) {
|
|
19771
20072
|
return /* @__PURE__ */ jsxDEV37("box", {
|
|
19772
20073
|
flexDirection: "column",
|
|
@@ -19876,7 +20177,7 @@ function AppRootInner({ safeMode = false }) {
|
|
|
19876
20177
|
function CrashRecoveryApp() {
|
|
19877
20178
|
const [crash, setCrash] = useState23(null);
|
|
19878
20179
|
const [safeMode, setSafeMode] = useState23(false);
|
|
19879
|
-
const handleCrashAction =
|
|
20180
|
+
const handleCrashAction = useCallback18((action) => {
|
|
19880
20181
|
switch (action) {
|
|
19881
20182
|
case "restart":
|
|
19882
20183
|
setCrash(null);
|
|
@@ -19904,7 +20205,7 @@ function CrashRecoveryApp() {
|
|
|
19904
20205
|
break;
|
|
19905
20206
|
}
|
|
19906
20207
|
}, [crash, safeMode]);
|
|
19907
|
-
|
|
20208
|
+
useEffect25(() => {
|
|
19908
20209
|
if (typeof process === "undefined")
|
|
19909
20210
|
return;
|
|
19910
20211
|
const onUncaught = (error) => {
|