@solongate/proxy 0.81.49 → 0.81.50
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/index.js +250 -263
- package/dist/tui/index.js +247 -252
- package/dist/tui/panels/Settings.d.ts +4 -1
- package/package.json +1 -1
- package/dist/tui/panels/Accounts.d.ts +0 -7
package/dist/index.js
CHANGED
|
@@ -9956,8 +9956,8 @@ var init_Audit = __esm({
|
|
|
9956
9956
|
// src/tui/panels/Settings.tsx
|
|
9957
9957
|
import { Box as Box7, Text as Text7, useInput as useInput6 } from "ink";
|
|
9958
9958
|
import TextInput5 from "ink-text-input";
|
|
9959
|
-
import { useState as useState7 } from "react";
|
|
9960
|
-
import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
9959
|
+
import { useEffect as useEffect6, useRef as useRef3, useState as useState7 } from "react";
|
|
9960
|
+
import { Fragment as Fragment5, jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
9961
9961
|
function alertBodyFor(channel) {
|
|
9962
9962
|
const c2 = channel.trim();
|
|
9963
9963
|
const base = { name: "dataroom alert", threshold: 5, windowSeconds: 60, signal: "any" };
|
|
@@ -9965,7 +9965,12 @@ function alertBodyFor(channel) {
|
|
|
9965
9965
|
if (c2.includes("@")) return { ...base, emails: [c2] };
|
|
9966
9966
|
return { ...base, telegram: [c2] };
|
|
9967
9967
|
}
|
|
9968
|
-
function SettingsPanel({
|
|
9968
|
+
function SettingsPanel({
|
|
9969
|
+
active: active2,
|
|
9970
|
+
focused,
|
|
9971
|
+
viewApiKey,
|
|
9972
|
+
onView
|
|
9973
|
+
}) {
|
|
9969
9974
|
void active2;
|
|
9970
9975
|
const { cols, rows } = usePanelSize();
|
|
9971
9976
|
const [sel, setSel] = useState7(0);
|
|
@@ -9974,24 +9979,40 @@ function SettingsPanel({ active: active2, focused }) {
|
|
|
9974
9979
|
const [confirmDel, setConfirmDel] = useState7(null);
|
|
9975
9980
|
const [msg, setMsg] = useState7(null);
|
|
9976
9981
|
const [busy, setBusy] = useState7(false);
|
|
9977
|
-
const
|
|
9978
|
-
const
|
|
9979
|
-
const
|
|
9982
|
+
const [accounts, setAccounts] = useState7(() => listAccounts());
|
|
9983
|
+
const [login, setLogin] = useState7(null);
|
|
9984
|
+
const [tick, setTick] = useState7(0);
|
|
9985
|
+
const abort = useRef3(false);
|
|
9986
|
+
const refreshAccounts = () => setAccounts(listAccounts());
|
|
9987
|
+
const locked = accounts.length === 0;
|
|
9988
|
+
useEffect6(() => {
|
|
9989
|
+
if (!login || login.phase === "done" || login.phase === "error") return;
|
|
9990
|
+
const t = setInterval(() => setTick((n) => n + 1), 120);
|
|
9991
|
+
return () => clearInterval(t);
|
|
9992
|
+
}, [login]);
|
|
9993
|
+
const localQ = useLoader(() => listAccounts().length ? api.settings.getLocalLogs() : Promise.resolve(null));
|
|
9994
|
+
const whQ = useLoader(() => listAccounts().length ? api.settings.getWebhooks() : Promise.resolve(null));
|
|
9995
|
+
const alertQ = useLoader(() => listAccounts().length ? api.settings.getAlerts() : Promise.resolve(null));
|
|
9980
9996
|
const local = localQ.data;
|
|
9981
9997
|
const webhooks = whQ.data?.webhooks ?? [];
|
|
9982
9998
|
const alerts = alertQ.data?.rules ?? [];
|
|
9983
9999
|
const rowsAll = [
|
|
9984
|
-
{ kind: "
|
|
9985
|
-
{ kind: "
|
|
9986
|
-
...
|
|
9987
|
-
|
|
9988
|
-
|
|
9989
|
-
|
|
10000
|
+
...accounts.map((acc) => ({ kind: "acct", acc })),
|
|
10001
|
+
{ kind: "acct-add" },
|
|
10002
|
+
...locked ? [] : [
|
|
10003
|
+
{ kind: "ll-enabled" },
|
|
10004
|
+
{ kind: "ll-path" },
|
|
10005
|
+
...webhooks.map((wh) => ({ kind: "wh", wh })),
|
|
10006
|
+
{ kind: "wh-add" },
|
|
10007
|
+
...alerts.map((rule) => ({ kind: "alert", rule })),
|
|
10008
|
+
{ kind: "alert-add" }
|
|
10009
|
+
]
|
|
9990
10010
|
];
|
|
9991
10011
|
const selClamped = Math.min(sel, rowsAll.length - 1);
|
|
9992
10012
|
const cur = rowsAll[selClamped];
|
|
9993
|
-
const keyOf = (r) => r.kind === "wh" ? "wh:" + r.wh.id : r.kind === "alert" ? "alert:" + r.rule.id : r.kind;
|
|
10013
|
+
const keyOf = (r) => r.kind === "acct" ? "acct:" + r.acc.apiKey : r.kind === "wh" ? "wh:" + r.wh.id : r.kind === "alert" ? "alert:" + r.rule.id : r.kind;
|
|
9994
10014
|
const reloadAll = () => {
|
|
10015
|
+
refreshAccounts();
|
|
9995
10016
|
localQ.reload();
|
|
9996
10017
|
whQ.reload();
|
|
9997
10018
|
alertQ.reload();
|
|
@@ -10005,8 +10026,48 @@ function SettingsPanel({ active: active2, focused }) {
|
|
|
10005
10026
|
reload();
|
|
10006
10027
|
}).catch((e) => setMsg({ text: "\u2717 " + (e instanceof Error ? e.message : String(e)), level: "bad" })).finally(() => setBusy(false));
|
|
10007
10028
|
};
|
|
10029
|
+
const beginLogin = () => {
|
|
10030
|
+
if (login && (login.phase === "starting" || login.phase === "waiting")) return;
|
|
10031
|
+
abort.current = false;
|
|
10032
|
+
setLogin({ phase: "starting" });
|
|
10033
|
+
void (async () => {
|
|
10034
|
+
let start2;
|
|
10035
|
+
try {
|
|
10036
|
+
start2 = await startDeviceLogin(DEFAULT_API_URL2);
|
|
10037
|
+
} catch (e) {
|
|
10038
|
+
setLogin({ phase: "error", msg: "could not reach SolonGate: " + (e instanceof Error ? e.message : String(e)) });
|
|
10039
|
+
return;
|
|
10040
|
+
}
|
|
10041
|
+
setLogin({ phase: "waiting", url: start2.verifyUrl });
|
|
10042
|
+
openBrowser(start2.verifyUrl);
|
|
10043
|
+
while (Date.now() < start2.expiresAt && !abort.current) {
|
|
10044
|
+
await new Promise((r) => setTimeout(r, start2.intervalMs));
|
|
10045
|
+
if (abort.current) return;
|
|
10046
|
+
const res = await pollDeviceLogin(DEFAULT_API_URL2, start2.deviceCode);
|
|
10047
|
+
if (res.status === "approved" && res.apiKey) {
|
|
10048
|
+
saveAccount({ apiKey: res.apiKey, apiUrl: DEFAULT_API_URL2, project: res.project, user: res.user, email: res.email });
|
|
10049
|
+
setLogin({ phase: "done", msg: `\u2713 added ${res.email || res.user || res.project || "account"}` });
|
|
10050
|
+
setViewCredentials({ apiKey: res.apiKey, apiUrl: DEFAULT_API_URL2 });
|
|
10051
|
+
onView?.({ apiKey: res.apiKey, apiUrl: DEFAULT_API_URL2, project: res.project, user: res.user, email: res.email });
|
|
10052
|
+
reloadAll();
|
|
10053
|
+
return;
|
|
10054
|
+
}
|
|
10055
|
+
if (res.status === "expired" || res.status === "not_found") {
|
|
10056
|
+
setLogin({ phase: "error", msg: "code expired \u2014 press n to retry" });
|
|
10057
|
+
return;
|
|
10058
|
+
}
|
|
10059
|
+
}
|
|
10060
|
+
if (!abort.current) setLogin({ phase: "error", msg: "timed out \u2014 press n to retry" });
|
|
10061
|
+
})();
|
|
10062
|
+
};
|
|
10008
10063
|
const activate = (r) => {
|
|
10009
|
-
if (r.kind === "
|
|
10064
|
+
if (r.kind === "acct") {
|
|
10065
|
+
setViewCredentials({ apiKey: r.acc.apiKey, apiUrl: r.acc.apiUrl });
|
|
10066
|
+
onView?.(r.acc);
|
|
10067
|
+
setMsg({ text: `viewing ${acctLabel(r.acc)}`, level: "ok" });
|
|
10068
|
+
} else if (r.kind === "acct-add") {
|
|
10069
|
+
beginLogin();
|
|
10070
|
+
} else if (r.kind === "ll-enabled") {
|
|
10010
10071
|
if (!local) return;
|
|
10011
10072
|
if (!local.enabled && !local.path.trim()) {
|
|
10012
10073
|
setMsg({ text: "set a path first (\u2193 then enter)", level: "bad" });
|
|
@@ -10045,6 +10106,13 @@ function SettingsPanel({ active: active2, focused }) {
|
|
|
10045
10106
|
};
|
|
10046
10107
|
useInput6(
|
|
10047
10108
|
(inp, key) => {
|
|
10109
|
+
if (login && (login.phase === "starting" || login.phase === "waiting")) {
|
|
10110
|
+
if (key.escape) {
|
|
10111
|
+
abort.current = true;
|
|
10112
|
+
setLogin(null);
|
|
10113
|
+
}
|
|
10114
|
+
return;
|
|
10115
|
+
}
|
|
10048
10116
|
setMsg(null);
|
|
10049
10117
|
if (key.upArrow) {
|
|
10050
10118
|
setSel((n) => Math.max(0, n - 1));
|
|
@@ -10053,6 +10121,11 @@ function SettingsPanel({ active: active2, focused }) {
|
|
|
10053
10121
|
setSel((n) => Math.min(rowsAll.length - 1, n + 1));
|
|
10054
10122
|
setConfirmDel(null);
|
|
10055
10123
|
} else if (key.return || inp === " ") activate(cur);
|
|
10124
|
+
else if (inp === "m" && cur.kind === "acct") {
|
|
10125
|
+
const ok = setActiveAccount({ apiKey: cur.acc.apiKey, apiUrl: cur.acc.apiUrl });
|
|
10126
|
+
setMsg(ok ? { text: `\u2713 ${acctLabel(cur.acc)} is now the ACTIVE key (guard + logging)`, level: "ok" } : { text: "\u2717 could not set active", level: "bad" });
|
|
10127
|
+
refreshAccounts();
|
|
10128
|
+
} else if (inp === "n") beginLogin();
|
|
10056
10129
|
else if (inp === "e" && cur.kind === "wh") {
|
|
10057
10130
|
const next = EVENTS[(EVENTS.indexOf(cur.wh.events) + 1) % EVENTS.length];
|
|
10058
10131
|
run12(`webhook events \u2192 ${next}`, () => api.settings.updateWebhook(cur.wh.id, { events: next }), whQ.reload);
|
|
@@ -10079,247 +10152,163 @@ function SettingsPanel({ active: active2, focused }) {
|
|
|
10079
10152
|
},
|
|
10080
10153
|
{ isActive: focused && !editing }
|
|
10081
10154
|
);
|
|
10082
|
-
const
|
|
10083
|
-
|
|
10155
|
+
const spin = SPIN2[tick % SPIN2.length];
|
|
10156
|
+
if (login && (login.phase === "starting" || login.phase === "waiting")) {
|
|
10157
|
+
return /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
|
|
10158
|
+
/* @__PURE__ */ jsx7(Text7, { bold: true, color: theme.accentBright, children: "Add an account" }),
|
|
10159
|
+
login.phase === "starting" ? /* @__PURE__ */ jsxs7(Text7, { color: theme.dim, children: [
|
|
10160
|
+
spin,
|
|
10161
|
+
" starting device pairing\u2026"
|
|
10162
|
+
] }) : /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", marginTop: 1, children: [
|
|
10163
|
+
/* @__PURE__ */ jsx7(Text7, { color: theme.dim, children: "Opening your browser to authorize. If it didn't open, visit:" }),
|
|
10164
|
+
/* @__PURE__ */ jsx7(Text7, { color: theme.accentBright, bold: true, wrap: "truncate", children: login.url }),
|
|
10165
|
+
/* @__PURE__ */ jsxs7(Box7, { marginTop: 1, children: [
|
|
10166
|
+
/* @__PURE__ */ jsxs7(Text7, { color: theme.warn, children: [
|
|
10167
|
+
spin,
|
|
10168
|
+
" waiting for authorization\u2026 "
|
|
10169
|
+
] }),
|
|
10170
|
+
/* @__PURE__ */ jsx7(Text7, { color: theme.dim, children: "esc to cancel" })
|
|
10171
|
+
] })
|
|
10172
|
+
] })
|
|
10173
|
+
] });
|
|
10174
|
+
}
|
|
10175
|
+
const loading = !locked && (localQ.loading && !localQ.data || whQ.loading && !whQ.data || alertQ.loading && !alertQ.data);
|
|
10176
|
+
const error = locked ? null : localQ.error ?? whQ.error ?? alertQ.error;
|
|
10084
10177
|
const mark = (r) => keyOf(r) === keyOf(cur) && focused ? "\u25B8 " : " ";
|
|
10085
10178
|
const onOff = (on) => on ? /* @__PURE__ */ jsx7(Text7, { color: theme.ok, children: "on " }) : /* @__PURE__ */ jsx7(Text7, { color: theme.dim, children: "off" });
|
|
10086
10179
|
const chanOf = (rule) => [...(rule.slackUrls ?? []).map((u) => "slack " + u), ...rule.emails ?? [], ...(rule.telegram ?? []).map((t) => "tg " + t)].join(", ") || "\u2014";
|
|
10087
|
-
const listBudget = Math.max(4, rows -
|
|
10180
|
+
const listBudget = Math.max(4, rows - 10);
|
|
10088
10181
|
const start = Math.min(Math.max(0, selClamped - Math.floor(listBudget / 2)), Math.max(0, rowsAll.length - listBudget));
|
|
10089
10182
|
const inWindow = (r) => {
|
|
10090
10183
|
const i = rowsAll.findIndex((x) => keyOf(x) === keyOf(r));
|
|
10091
10184
|
return i >= start && i < start + listBudget;
|
|
10092
10185
|
};
|
|
10093
10186
|
return /* @__PURE__ */ jsx7(DataView, { loading, error, children: /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
|
|
10094
|
-
/* @__PURE__ */ jsx7(Text7, { color: theme.dim, children: focused ? "\u2191\u2193 move \xB7 enter
|
|
10187
|
+
/* @__PURE__ */ jsx7(Text7, { color: theme.dim, children: focused ? "\u2191\u2193 move \xB7 enter view-toggle-edit \xB7 m make active \xB7 n add account \xB7 e events \xB7 d delete \xB7 r refresh" : "press \u2192 to configure" }),
|
|
10095
10188
|
editing ? /* @__PURE__ */ jsxs7(Box7, { children: [
|
|
10096
10189
|
/* @__PURE__ */ jsx7(Text7, { color: theme.warn, children: editing === "path" ? "local log path: " : editing === "wh-url" ? "webhook url: " : "channel (slack url / email / telegram id): " }),
|
|
10097
10190
|
/* @__PURE__ */ jsx7(TextInput5, { value: input, onChange: setInput, onSubmit: submitInput })
|
|
10098
|
-
] }) : msg ? /* @__PURE__ */ jsx7(Text7, { color: msg.level === "bad" ? theme.bad : theme.ok, children: truncate2(msg.text, cols) }) : /* @__PURE__ */ jsx7(Text7, { children: " " }),
|
|
10099
|
-
inWindow(rowsAll[0]) || inWindow(rowsAll[1]) ? /* @__PURE__ */ jsxs7(Box7, { marginTop: 1, flexDirection: "column", children: [
|
|
10100
|
-
/* @__PURE__ */ jsxs7(Text7, { bold: true, color: theme.accentBright, children: [
|
|
10101
|
-
"LOCAL LOGS ",
|
|
10102
|
-
/* @__PURE__ */ jsx7(Text7, { color: theme.dim, children: "\u2014 hooks mirror every decision to a file on the agent machine" })
|
|
10103
|
-
] }),
|
|
10104
|
-
/* @__PURE__ */ jsxs7(Text7, { wrap: "truncate", children: [
|
|
10105
|
-
/* @__PURE__ */ jsx7(Text7, { color: keyOf(cur) === "ll-enabled" && focused ? theme.accentBright : theme.dim, children: mark(rowsAll[0]) }),
|
|
10106
|
-
/* @__PURE__ */ jsx7(Text7, { color: theme.dim, children: "enabled ".padEnd(10) }),
|
|
10107
|
-
onOff(!!local?.enabled),
|
|
10108
|
-
/* @__PURE__ */ jsx7(Text7, { color: theme.dim, children: " enter toggles" })
|
|
10109
|
-
] }),
|
|
10110
|
-
/* @__PURE__ */ jsxs7(Text7, { wrap: "truncate", children: [
|
|
10111
|
-
/* @__PURE__ */ jsx7(Text7, { color: keyOf(cur) === "ll-path" && focused ? theme.accentBright : theme.dim, children: mark(rowsAll[1]) }),
|
|
10112
|
-
/* @__PURE__ */ jsx7(Text7, { color: theme.dim, children: "path ".padEnd(10) }),
|
|
10113
|
-
local?.path ? /* @__PURE__ */ jsx7(Text7, { color: theme.accent, children: truncate2(local.path, cols - 14) }) : /* @__PURE__ */ jsx7(Text7, { color: theme.dim, children: "not set \u2014 enter to edit" })
|
|
10114
|
-
] })
|
|
10115
|
-
] }) : null,
|
|
10191
|
+
] }) : msg ? /* @__PURE__ */ jsx7(Text7, { color: msg.level === "bad" ? theme.bad : theme.ok, children: truncate2(msg.text, cols) }) : login?.msg ? /* @__PURE__ */ jsx7(Text7, { color: login.phase === "error" ? theme.bad : theme.ok, children: login.msg }) : /* @__PURE__ */ jsx7(Text7, { children: " " }),
|
|
10116
10192
|
/* @__PURE__ */ jsxs7(Box7, { marginTop: 1, flexDirection: "column", children: [
|
|
10117
10193
|
/* @__PURE__ */ jsxs7(Text7, { bold: true, color: theme.accentBright, children: [
|
|
10118
|
-
"
|
|
10194
|
+
"ACCOUNTS ",
|
|
10119
10195
|
/* @__PURE__ */ jsxs7(Text7, { color: theme.dim, children: [
|
|
10120
|
-
"\u2014
|
|
10121
|
-
|
|
10122
|
-
")"
|
|
10196
|
+
"\u2014 logged in on this device (",
|
|
10197
|
+
accounts.length,
|
|
10198
|
+
") \xB7 \u25CF viewing = shown here \xB7 ACTIVE = key the guard uses"
|
|
10123
10199
|
] })
|
|
10124
10200
|
] }),
|
|
10125
|
-
|
|
10126
|
-
/* @__PURE__ */ jsx7(Text7, { color:
|
|
10127
|
-
|
|
10128
|
-
/* @__PURE__ */ jsx7(Text7, { color: theme.
|
|
10129
|
-
|
|
10130
|
-
|
|
10131
|
-
|
|
10132
|
-
|
|
10133
|
-
/* @__PURE__ */
|
|
10201
|
+
accounts.length === 0 ? /* @__PURE__ */ jsxs7(Text7, { children: [
|
|
10202
|
+
/* @__PURE__ */ jsx7(Text7, { color: theme.dim, children: " no accounts yet \u2014 " }),
|
|
10203
|
+
/* @__PURE__ */ jsx7(Text7, { color: theme.accent, children: "n" }),
|
|
10204
|
+
/* @__PURE__ */ jsx7(Text7, { color: theme.dim, children: " (or enter) logs in, pairs this device and unlocks the dataroom" })
|
|
10205
|
+
] }) : null,
|
|
10206
|
+
accounts.filter((acc) => inWindow({ kind: "acct", acc })).map((a) => {
|
|
10207
|
+
const isView = viewApiKey ? a.apiKey === viewApiKey : accounts[0]?.apiKey === a.apiKey;
|
|
10208
|
+
const isActive = isActiveAccount(a.apiKey);
|
|
10209
|
+
return /* @__PURE__ */ jsxs7(Text7, { wrap: "truncate", children: [
|
|
10210
|
+
/* @__PURE__ */ jsx7(Text7, { color: keyOf(cur) === "acct:" + a.apiKey && focused ? theme.accentBright : theme.dim, children: mark({ kind: "acct", acc: a }) }),
|
|
10211
|
+
/* @__PURE__ */ jsx7(Text7, { color: theme.accent, children: truncate2(acctLabel(a), 30).padEnd(31) }),
|
|
10212
|
+
isView ? /* @__PURE__ */ jsx7(Text7, { color: theme.ok, children: "\u25CF viewing " }) : /* @__PURE__ */ jsx7(Text7, { color: theme.dim, children: " " }),
|
|
10213
|
+
isActive ? /* @__PURE__ */ jsx7(Text7, { color: theme.warn, children: "ACTIVE " }) : /* @__PURE__ */ jsx7(Text7, { color: theme.dim, children: " " }),
|
|
10214
|
+
/* @__PURE__ */ jsx7(Text7, { color: theme.dim, children: a.project ? truncate2(a.project, 24) : "" })
|
|
10215
|
+
] }, a.apiKey);
|
|
10216
|
+
}),
|
|
10217
|
+
inWindow({ kind: "acct-add" }) ? /* @__PURE__ */ jsxs7(Text7, { children: [
|
|
10218
|
+
/* @__PURE__ */ jsx7(Text7, { color: cur.kind === "acct-add" && focused ? theme.accentBright : theme.dim, children: mark({ kind: "acct-add" }) }),
|
|
10219
|
+
/* @__PURE__ */ jsx7(Text7, { color: theme.dim, children: "+ add account (enter \u2014 device login in the browser)" })
|
|
10134
10220
|
] }) : null
|
|
10135
10221
|
] }),
|
|
10136
|
-
/* @__PURE__ */ jsxs7(
|
|
10137
|
-
/* @__PURE__ */ jsxs7(
|
|
10138
|
-
|
|
10139
|
-
|
|
10140
|
-
"\u2014
|
|
10141
|
-
|
|
10142
|
-
|
|
10222
|
+
locked ? null : /* @__PURE__ */ jsxs7(Fragment5, { children: [
|
|
10223
|
+
inWindow({ kind: "ll-enabled" }) || inWindow({ kind: "ll-path" }) ? /* @__PURE__ */ jsxs7(Box7, { marginTop: 1, flexDirection: "column", children: [
|
|
10224
|
+
/* @__PURE__ */ jsxs7(Text7, { bold: true, color: theme.accentBright, children: [
|
|
10225
|
+
"LOCAL LOGS ",
|
|
10226
|
+
/* @__PURE__ */ jsx7(Text7, { color: theme.dim, children: "\u2014 hooks mirror every decision to a file on the agent machine" })
|
|
10227
|
+
] }),
|
|
10228
|
+
/* @__PURE__ */ jsxs7(Text7, { wrap: "truncate", children: [
|
|
10229
|
+
/* @__PURE__ */ jsx7(Text7, { color: keyOf(cur) === "ll-enabled" && focused ? theme.accentBright : theme.dim, children: mark({ kind: "ll-enabled" }) }),
|
|
10230
|
+
/* @__PURE__ */ jsx7(Text7, { color: theme.dim, children: "enabled ".padEnd(10) }),
|
|
10231
|
+
onOff(!!local?.enabled),
|
|
10232
|
+
/* @__PURE__ */ jsx7(Text7, { color: theme.dim, children: " enter toggles" })
|
|
10233
|
+
] }),
|
|
10234
|
+
/* @__PURE__ */ jsxs7(Text7, { wrap: "truncate", children: [
|
|
10235
|
+
/* @__PURE__ */ jsx7(Text7, { color: keyOf(cur) === "ll-path" && focused ? theme.accentBright : theme.dim, children: mark({ kind: "ll-path" }) }),
|
|
10236
|
+
/* @__PURE__ */ jsx7(Text7, { color: theme.dim, children: "path ".padEnd(10) }),
|
|
10237
|
+
local?.path ? /* @__PURE__ */ jsx7(Text7, { color: theme.accent, children: truncate2(local.path, cols - 14) }) : /* @__PURE__ */ jsx7(Text7, { color: theme.dim, children: "not set \u2014 enter to edit" })
|
|
10143
10238
|
] })
|
|
10239
|
+
] }) : null,
|
|
10240
|
+
/* @__PURE__ */ jsxs7(Box7, { marginTop: 1, flexDirection: "column", children: [
|
|
10241
|
+
/* @__PURE__ */ jsxs7(Text7, { bold: true, color: theme.accentBright, children: [
|
|
10242
|
+
"WEBHOOKS ",
|
|
10243
|
+
/* @__PURE__ */ jsxs7(Text7, { color: theme.dim, children: [
|
|
10244
|
+
"\u2014 POST every matching event to your endpoint (",
|
|
10245
|
+
webhooks.length,
|
|
10246
|
+
")"
|
|
10247
|
+
] })
|
|
10248
|
+
] }),
|
|
10249
|
+
webhooks.filter((wh) => inWindow({ kind: "wh", wh })).map((wh) => /* @__PURE__ */ jsxs7(Text7, { wrap: "truncate", children: [
|
|
10250
|
+
/* @__PURE__ */ jsx7(Text7, { color: keyOf(cur) === "wh:" + wh.id && focused ? theme.accentBright : theme.dim, children: mark({ kind: "wh", wh }) }),
|
|
10251
|
+
onOff(wh.enabled),
|
|
10252
|
+
/* @__PURE__ */ jsx7(Text7, { color: theme.warn, children: (" " + wh.events).padEnd(9) }),
|
|
10253
|
+
/* @__PURE__ */ jsx7(Text7, { color: theme.accent, children: truncate2(wh.url, cols - 16) })
|
|
10254
|
+
] }, wh.id)),
|
|
10255
|
+
inWindow({ kind: "wh-add" }) ? /* @__PURE__ */ jsxs7(Text7, { children: [
|
|
10256
|
+
/* @__PURE__ */ jsx7(Text7, { color: cur.kind === "wh-add" && focused ? theme.accentBright : theme.dim, children: mark({ kind: "wh-add" }) }),
|
|
10257
|
+
/* @__PURE__ */ jsx7(Text7, { color: theme.dim, children: "+ add webhook (enter)" })
|
|
10258
|
+
] }) : null
|
|
10144
10259
|
] }),
|
|
10145
|
-
|
|
10146
|
-
/* @__PURE__ */
|
|
10147
|
-
|
|
10148
|
-
|
|
10149
|
-
|
|
10150
|
-
|
|
10151
|
-
|
|
10152
|
-
|
|
10153
|
-
|
|
10154
|
-
|
|
10155
|
-
|
|
10260
|
+
/* @__PURE__ */ jsxs7(Box7, { marginTop: 1, flexDirection: "column", children: [
|
|
10261
|
+
/* @__PURE__ */ jsxs7(Text7, { bold: true, color: theme.accentBright, children: [
|
|
10262
|
+
"ALERTS ",
|
|
10263
|
+
/* @__PURE__ */ jsxs7(Text7, { color: theme.dim, children: [
|
|
10264
|
+
"\u2014 notify on a signal spike (",
|
|
10265
|
+
alerts.length,
|
|
10266
|
+
")"
|
|
10267
|
+
] })
|
|
10268
|
+
] }),
|
|
10269
|
+
alerts.filter((rule) => inWindow({ kind: "alert", rule })).map((rule) => /* @__PURE__ */ jsxs7(Text7, { wrap: "truncate", children: [
|
|
10270
|
+
/* @__PURE__ */ jsx7(Text7, { color: keyOf(cur) === "alert:" + rule.id && focused ? theme.accentBright : theme.dim, children: mark({ kind: "alert", rule }) }),
|
|
10271
|
+
onOff(rule.enabled),
|
|
10272
|
+
/* @__PURE__ */ jsx7(Text7, { color: theme.warn, children: (" " + rule.signal).padEnd(11) }),
|
|
10273
|
+
/* @__PURE__ */ jsx7(Text7, { children: `\u2265${rule.threshold}/${rule.windowSeconds}s ` }),
|
|
10274
|
+
/* @__PURE__ */ jsx7(Text7, { color: theme.accent, children: truncate2(chanOf(rule), cols - 26) })
|
|
10275
|
+
] }, rule.id)),
|
|
10276
|
+
inWindow({ kind: "alert-add" }) ? /* @__PURE__ */ jsxs7(Text7, { children: [
|
|
10277
|
+
/* @__PURE__ */ jsx7(Text7, { color: cur.kind === "alert-add" && focused ? theme.accentBright : theme.dim, children: mark({ kind: "alert-add" }) }),
|
|
10278
|
+
/* @__PURE__ */ jsx7(Text7, { color: theme.dim, children: "+ add alert (enter \u2014 one channel: slack url, email or telegram chat id)" })
|
|
10279
|
+
] }) : null
|
|
10280
|
+
] })
|
|
10156
10281
|
] })
|
|
10157
10282
|
] }) });
|
|
10158
10283
|
}
|
|
10159
|
-
var EVENTS;
|
|
10284
|
+
var EVENTS, SPIN2, acctLabel;
|
|
10160
10285
|
var init_Settings = __esm({
|
|
10161
10286
|
"src/tui/panels/Settings.tsx"() {
|
|
10162
10287
|
"use strict";
|
|
10163
10288
|
init_api_client();
|
|
10289
|
+
init_client();
|
|
10290
|
+
init_device_login();
|
|
10164
10291
|
init_components();
|
|
10165
10292
|
init_hooks();
|
|
10166
10293
|
init_theme();
|
|
10167
10294
|
EVENTS = ["denials", "allowed", "all"];
|
|
10168
|
-
}
|
|
10169
|
-
});
|
|
10170
|
-
|
|
10171
|
-
// src/tui/panels/Accounts.tsx
|
|
10172
|
-
import { Box as Box8, Text as Text8, useInput as useInput7 } from "ink";
|
|
10173
|
-
import { useEffect as useEffect6, useRef as useRef3, useState as useState8 } from "react";
|
|
10174
|
-
import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
10175
|
-
function AccountsPanel({
|
|
10176
|
-
focused,
|
|
10177
|
-
viewApiKey,
|
|
10178
|
-
onView
|
|
10179
|
-
}) {
|
|
10180
|
-
const [accounts, setAccounts] = useState8(() => listAccounts());
|
|
10181
|
-
const [sel, setSel] = useState8(0);
|
|
10182
|
-
const [msg, setMsg] = useState8(null);
|
|
10183
|
-
const [login, setLogin] = useState8(null);
|
|
10184
|
-
const [tick, setTick] = useState8(0);
|
|
10185
|
-
const abort = useRef3(false);
|
|
10186
|
-
const refresh = () => setAccounts(listAccounts());
|
|
10187
|
-
useEffect6(() => {
|
|
10188
|
-
if (!login || login.phase === "done" || login.phase === "error") return;
|
|
10189
|
-
const t = setInterval(() => setTick((n) => n + 1), 120);
|
|
10190
|
-
return () => clearInterval(t);
|
|
10191
|
-
}, [login]);
|
|
10192
|
-
const beginLogin = () => {
|
|
10193
|
-
if (login && (login.phase === "starting" || login.phase === "waiting")) return;
|
|
10194
|
-
abort.current = false;
|
|
10195
|
-
setLogin({ phase: "starting" });
|
|
10196
|
-
void (async () => {
|
|
10197
|
-
let start;
|
|
10198
|
-
try {
|
|
10199
|
-
start = await startDeviceLogin(DEFAULT_API_URL2);
|
|
10200
|
-
} catch (e) {
|
|
10201
|
-
setLogin({ phase: "error", msg: "could not reach SolonGate: " + (e instanceof Error ? e.message : String(e)) });
|
|
10202
|
-
return;
|
|
10203
|
-
}
|
|
10204
|
-
setLogin({ phase: "waiting", url: start.verifyUrl });
|
|
10205
|
-
openBrowser(start.verifyUrl);
|
|
10206
|
-
while (Date.now() < start.expiresAt && !abort.current) {
|
|
10207
|
-
await new Promise((r) => setTimeout(r, start.intervalMs));
|
|
10208
|
-
if (abort.current) return;
|
|
10209
|
-
const res = await pollDeviceLogin(DEFAULT_API_URL2, start.deviceCode);
|
|
10210
|
-
if (res.status === "approved" && res.apiKey) {
|
|
10211
|
-
saveAccount({ apiKey: res.apiKey, apiUrl: DEFAULT_API_URL2, project: res.project, user: res.user, email: res.email });
|
|
10212
|
-
setLogin({ phase: "done", msg: `\u2713 added ${res.email || res.user || res.project || "account"}` });
|
|
10213
|
-
refresh();
|
|
10214
|
-
setViewCredentials({ apiKey: res.apiKey, apiUrl: DEFAULT_API_URL2 });
|
|
10215
|
-
onView?.({ apiKey: res.apiKey, apiUrl: DEFAULT_API_URL2, project: res.project, user: res.user, email: res.email });
|
|
10216
|
-
return;
|
|
10217
|
-
}
|
|
10218
|
-
if (res.status === "expired" || res.status === "not_found") {
|
|
10219
|
-
setLogin({ phase: "error", msg: "code expired \u2014 press n to retry" });
|
|
10220
|
-
return;
|
|
10221
|
-
}
|
|
10222
|
-
}
|
|
10223
|
-
if (!abort.current) setLogin({ phase: "error", msg: "timed out \u2014 press n to retry" });
|
|
10224
|
-
})();
|
|
10225
|
-
};
|
|
10226
|
-
useInput7(
|
|
10227
|
-
(input, key) => {
|
|
10228
|
-
if (login && (login.phase === "starting" || login.phase === "waiting")) {
|
|
10229
|
-
if (key.escape) {
|
|
10230
|
-
abort.current = true;
|
|
10231
|
-
setLogin(null);
|
|
10232
|
-
}
|
|
10233
|
-
return;
|
|
10234
|
-
}
|
|
10235
|
-
if (key.upArrow) setSel((n) => Math.max(0, n - 1));
|
|
10236
|
-
else if (key.downArrow) setSel((n) => Math.min(accounts.length - 1, n + 1));
|
|
10237
|
-
else if (key.return) {
|
|
10238
|
-
const a = accounts[sel];
|
|
10239
|
-
if (a) {
|
|
10240
|
-
setViewCredentials({ apiKey: a.apiKey, apiUrl: a.apiUrl });
|
|
10241
|
-
onView?.(a);
|
|
10242
|
-
setMsg({ text: `viewing ${a.email || a.user || a.project || "account \u2026" + a.apiKey.slice(-4)}`, level: "ok" });
|
|
10243
|
-
}
|
|
10244
|
-
} else if (input === "m") {
|
|
10245
|
-
const a = accounts[sel];
|
|
10246
|
-
if (a) {
|
|
10247
|
-
const ok = setActiveAccount({ apiKey: a.apiKey, apiUrl: a.apiUrl });
|
|
10248
|
-
setMsg(ok ? { text: `\u2713 ${a.email || a.user || a.project || "account"} is now the ACTIVE key (guard + logging)`, level: "ok" } : { text: "\u2717 could not set active", level: "bad" });
|
|
10249
|
-
refresh();
|
|
10250
|
-
}
|
|
10251
|
-
} else if (input === "n") beginLogin();
|
|
10252
|
-
else if (input === "r") refresh();
|
|
10253
|
-
},
|
|
10254
|
-
{ isActive: focused }
|
|
10255
|
-
);
|
|
10256
|
-
const spin = SPIN2[tick % SPIN2.length];
|
|
10257
|
-
if (login && (login.phase === "starting" || login.phase === "waiting")) {
|
|
10258
|
-
return /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", children: [
|
|
10259
|
-
/* @__PURE__ */ jsx8(Text8, { bold: true, color: theme.accentBright, children: "Add an account" }),
|
|
10260
|
-
login.phase === "starting" ? /* @__PURE__ */ jsxs8(Text8, { color: theme.dim, children: [
|
|
10261
|
-
spin,
|
|
10262
|
-
" starting device pairing\u2026"
|
|
10263
|
-
] }) : /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", marginTop: 1, children: [
|
|
10264
|
-
/* @__PURE__ */ jsx8(Text8, { color: theme.dim, children: "Opening your browser to authorize. If it didn't open, visit:" }),
|
|
10265
|
-
/* @__PURE__ */ jsx8(Text8, { color: theme.accentBright, bold: true, wrap: "truncate", children: login.url }),
|
|
10266
|
-
/* @__PURE__ */ jsxs8(Box8, { marginTop: 1, children: [
|
|
10267
|
-
/* @__PURE__ */ jsxs8(Text8, { color: theme.warn, children: [
|
|
10268
|
-
spin,
|
|
10269
|
-
" waiting for authorization\u2026 "
|
|
10270
|
-
] }),
|
|
10271
|
-
/* @__PURE__ */ jsx8(Text8, { color: theme.dim, children: "esc to cancel" })
|
|
10272
|
-
] })
|
|
10273
|
-
] })
|
|
10274
|
-
] });
|
|
10275
|
-
}
|
|
10276
|
-
return /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", children: [
|
|
10277
|
-
/* @__PURE__ */ jsx8(Text8, { color: theme.dim, children: focused ? "\u2191\u2193 select \xB7 enter view \xB7 m make active \xB7 n add account \xB7 r refresh" : "press \u2192 to manage accounts" }),
|
|
10278
|
-
msg ? /* @__PURE__ */ jsx8(Text8, { color: msg.level === "bad" ? theme.bad : theme.ok, children: truncate2(msg.text, 70) }) : login?.msg ? /* @__PURE__ */ jsx8(Text8, { color: login.phase === "error" ? theme.bad : theme.ok, children: login.msg }) : /* @__PURE__ */ jsx8(Text8, { children: " " }),
|
|
10279
|
-
/* @__PURE__ */ jsx8(Box8, { marginTop: 1, flexDirection: "column", children: accounts.length === 0 ? /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", children: [
|
|
10280
|
-
/* @__PURE__ */ jsx8(Text8, { color: theme.dim, children: "No accounts on this device yet." }),
|
|
10281
|
-
/* @__PURE__ */ jsxs8(Text8, { children: [
|
|
10282
|
-
/* @__PURE__ */ jsx8(Text8, { color: theme.accent, children: "n" }),
|
|
10283
|
-
/* @__PURE__ */ jsx8(Text8, { color: theme.dim, children: " to log in \u2014 pairs this device and starts protecting your Claude Code sessions." })
|
|
10284
|
-
] })
|
|
10285
|
-
] }) : accounts.map((a, i) => {
|
|
10286
|
-
const isSel = i === sel && focused;
|
|
10287
|
-
const isView = viewApiKey ? a.apiKey === viewApiKey : i === 0;
|
|
10288
|
-
const isActive = isActiveAccount(a.apiKey);
|
|
10289
|
-
return /* @__PURE__ */ jsxs8(Text8, { wrap: "truncate", backgroundColor: isSel ? "#333333" : void 0, bold: isSel, children: [
|
|
10290
|
-
/* @__PURE__ */ jsx8(Text8, { color: isSel ? theme.accentBright : theme.dim, children: isSel ? "\u25B8 " : " " }),
|
|
10291
|
-
/* @__PURE__ */ jsx8(Text8, { color: theme.accent, children: truncate2(a.email || a.user || "account \u2026" + a.apiKey.slice(-4), 30).padEnd(31) }),
|
|
10292
|
-
isView ? /* @__PURE__ */ jsx8(Text8, { color: theme.ok, children: "\u25CF viewing " }) : /* @__PURE__ */ jsx8(Text8, { color: theme.dim, children: " " }),
|
|
10293
|
-
isActive ? /* @__PURE__ */ jsx8(Text8, { color: theme.warn, children: "ACTIVE " }) : /* @__PURE__ */ jsx8(Text8, { color: theme.dim, children: " " }),
|
|
10294
|
-
/* @__PURE__ */ jsx8(Text8, { color: theme.dim, children: a.project ? truncate2(a.project, 24) : "" })
|
|
10295
|
-
] }, a.apiKey);
|
|
10296
|
-
}) }),
|
|
10297
|
-
/* @__PURE__ */ jsx8(Box8, { marginTop: 1, flexDirection: "column", children: /* @__PURE__ */ jsx8(Text8, { color: theme.dim, children: "\u25CF viewing = the account the dataroom is showing \xB7 ACTIVE = the key the guard hooks + logging use" }) })
|
|
10298
|
-
] });
|
|
10299
|
-
}
|
|
10300
|
-
var SPIN2;
|
|
10301
|
-
var init_Accounts = __esm({
|
|
10302
|
-
"src/tui/panels/Accounts.tsx"() {
|
|
10303
|
-
"use strict";
|
|
10304
|
-
init_client();
|
|
10305
|
-
init_device_login();
|
|
10306
|
-
init_theme();
|
|
10307
10295
|
SPIN2 = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
10296
|
+
acctLabel = (a) => a.email || a.user || "account \u2026" + a.apiKey.slice(-4);
|
|
10308
10297
|
}
|
|
10309
10298
|
});
|
|
10310
10299
|
|
|
10311
10300
|
// src/tui/App.tsx
|
|
10312
|
-
import { Box as
|
|
10313
|
-
import { useEffect as useEffect7, useState as
|
|
10314
|
-
import { jsx as
|
|
10301
|
+
import { Box as Box8, Text as Text8, useApp, useInput as useInput7 } from "ink";
|
|
10302
|
+
import { useEffect as useEffect7, useState as useState8 } from "react";
|
|
10303
|
+
import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
10315
10304
|
function LiveHint() {
|
|
10316
|
-
return /* @__PURE__ */
|
|
10317
|
-
/* @__PURE__ */
|
|
10318
|
-
/* @__PURE__ */
|
|
10319
|
-
/* @__PURE__ */
|
|
10320
|
-
/* @__PURE__ */
|
|
10305
|
+
return /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", children: [
|
|
10306
|
+
/* @__PURE__ */ jsx8(Text8, { color: theme.accentBright, bold: true, children: "\u25B6 REALTIME CONSOLE" }),
|
|
10307
|
+
/* @__PURE__ */ jsx8(Text8, { color: theme.dim, children: "Fullscreen live monitor \u2014 streaming tool calls, active charts," }),
|
|
10308
|
+
/* @__PURE__ */ jsx8(Text8, { color: theme.dim, children: "counters, DLP hits and denial alerts. Updates every 2s." }),
|
|
10309
|
+
/* @__PURE__ */ jsx8(Box8, { marginTop: 1, children: /* @__PURE__ */ jsxs8(Text8, { children: [
|
|
10321
10310
|
"press ",
|
|
10322
|
-
/* @__PURE__ */
|
|
10311
|
+
/* @__PURE__ */ jsx8(Text8, { color: theme.accent, children: "enter" }),
|
|
10323
10312
|
" to go live"
|
|
10324
10313
|
] }) })
|
|
10325
10314
|
] });
|
|
@@ -10327,25 +10316,25 @@ function LiveHint() {
|
|
|
10327
10316
|
function Banner({ cols }) {
|
|
10328
10317
|
const wide = cols >= 82;
|
|
10329
10318
|
if (!wide) {
|
|
10330
|
-
return /* @__PURE__ */
|
|
10331
|
-
/* @__PURE__ */
|
|
10332
|
-
/* @__PURE__ */
|
|
10319
|
+
return /* @__PURE__ */ jsxs8(Box8, { children: [
|
|
10320
|
+
/* @__PURE__ */ jsx8(Text8, { bold: true, color: theme.accentBright, children: "SolonGate" }),
|
|
10321
|
+
/* @__PURE__ */ jsx8(Text8, { color: theme.dim, children: " \u2014 security control center" })
|
|
10333
10322
|
] });
|
|
10334
10323
|
}
|
|
10335
|
-
return /* @__PURE__ */
|
|
10336
|
-
BANNER_FULL.map((line, i) => /* @__PURE__ */
|
|
10337
|
-
/* @__PURE__ */
|
|
10324
|
+
return /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", children: [
|
|
10325
|
+
BANNER_FULL.map((line, i) => /* @__PURE__ */ jsx8(Text8, { bold: true, color: BANNER_HEX[i], children: line }, i)),
|
|
10326
|
+
/* @__PURE__ */ jsx8(Text8, { color: theme.dim, children: " security control center \xB7 manage policies, rate limits, DLP & more" })
|
|
10338
10327
|
] });
|
|
10339
10328
|
}
|
|
10340
10329
|
function App() {
|
|
10341
10330
|
const { exit } = useApp();
|
|
10342
|
-
const [accounts, setAccounts] =
|
|
10343
|
-
const [viewKey, setViewKey] =
|
|
10344
|
-
const [viewNonce, setViewNonce] =
|
|
10345
|
-
const [section, setSection] =
|
|
10346
|
-
const [focus, setFocus] =
|
|
10347
|
-
const [help, setHelp] =
|
|
10348
|
-
const [update2, setUpdate] =
|
|
10331
|
+
const [accounts, setAccounts] = useState8(() => listAccounts());
|
|
10332
|
+
const [viewKey, setViewKey] = useState8(() => accounts[0]?.apiKey);
|
|
10333
|
+
const [viewNonce, setViewNonce] = useState8(0);
|
|
10334
|
+
const [section, setSection] = useState8(accounts.length === 0 ? SETTINGS_SECTION : 0);
|
|
10335
|
+
const [focus, setFocus] = useState8("nav");
|
|
10336
|
+
const [help, setHelp] = useState8(false);
|
|
10337
|
+
const [update2, setUpdate] = useState8({ kind: "idle" });
|
|
10349
10338
|
useEffect7(() => {
|
|
10350
10339
|
let alive = true;
|
|
10351
10340
|
const run12 = () => void tuiUpdateFlow((s) => alive && setUpdate(s));
|
|
@@ -10358,7 +10347,7 @@ function App() {
|
|
|
10358
10347
|
}, []);
|
|
10359
10348
|
const acctIdx = Math.max(0, accounts.findIndex((a) => a.apiKey === viewKey));
|
|
10360
10349
|
const cur = accounts[acctIdx];
|
|
10361
|
-
const
|
|
10350
|
+
const acctLabel2 = cur ? cur.email || cur.user || cur.project || `account \u2026${cur.apiKey.slice(-4)}` : "not logged in";
|
|
10362
10351
|
useEffect7(() => {
|
|
10363
10352
|
if (!cur || cur.email) return;
|
|
10364
10353
|
let alive = true;
|
|
@@ -10386,8 +10375,8 @@ function App() {
|
|
|
10386
10375
|
viewAccount(accounts[(acctIdx + 1) % accounts.length]);
|
|
10387
10376
|
};
|
|
10388
10377
|
const locked = accounts.length === 0;
|
|
10389
|
-
const effectiveSection = locked ?
|
|
10390
|
-
|
|
10378
|
+
const effectiveSection = locked ? SETTINGS_SECTION : section;
|
|
10379
|
+
useInput7((input, key) => {
|
|
10391
10380
|
if (help) {
|
|
10392
10381
|
setHelp(false);
|
|
10393
10382
|
return;
|
|
@@ -10415,45 +10404,45 @@ function App() {
|
|
|
10415
10404
|
});
|
|
10416
10405
|
const { cols, rows } = useTermSize();
|
|
10417
10406
|
const current = SECTIONS[effectiveSection];
|
|
10418
|
-
if (help) return /* @__PURE__ */
|
|
10407
|
+
if (help) return /* @__PURE__ */ jsx8(HelpOverlay, { cols, rows });
|
|
10419
10408
|
if (current.label === "Live" && focus === "panel") {
|
|
10420
|
-
return /* @__PURE__ */
|
|
10409
|
+
return /* @__PURE__ */ jsx8(Box8, { flexDirection: "column", width: cols, height: rows - 1, overflow: "hidden", children: /* @__PURE__ */ jsx8(LivePanel, { active: true, focused: true }, viewNonce) });
|
|
10421
10410
|
}
|
|
10422
10411
|
const Panel = current.Panel;
|
|
10423
|
-
const panelBody = current.label === "
|
|
10424
|
-
return /* @__PURE__ */
|
|
10425
|
-
/* @__PURE__ */
|
|
10426
|
-
/* @__PURE__ */
|
|
10427
|
-
/* @__PURE__ */
|
|
10428
|
-
/* @__PURE__ */
|
|
10429
|
-
locked ? /* @__PURE__ */
|
|
10430
|
-
update2.kind === "updating" ? /* @__PURE__ */
|
|
10412
|
+
const panelBody = current.label === "Settings" ? /* @__PURE__ */ jsx8(SettingsPanel, { active: true, focused: focus === "panel", viewApiKey: viewKey, onView: viewAccount }) : /* @__PURE__ */ jsx8(Panel, { active: focus === "panel" || current.label !== "Live", focused: focus === "panel" });
|
|
10413
|
+
return /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", width: cols, height: rows, paddingX: 1, paddingTop: 1, children: [
|
|
10414
|
+
/* @__PURE__ */ jsx8(Banner, { cols }),
|
|
10415
|
+
/* @__PURE__ */ jsxs8(Text8, { wrap: "truncate", children: [
|
|
10416
|
+
/* @__PURE__ */ jsx8(Text8, { color: theme.dim, children: "account: " }),
|
|
10417
|
+
/* @__PURE__ */ jsx8(Text8, { color: locked ? theme.warn : theme.accentBright, bold: true, children: acctLabel2 }),
|
|
10418
|
+
locked ? /* @__PURE__ */ jsx8(Text8, { color: theme.dim, children: " \xB7 log in from Settings to unlock the dataroom" }) : accounts.length > 1 ? /* @__PURE__ */ jsx8(Text8, { color: theme.dim, children: ` (${acctIdx + 1}/${accounts.length} \xB7 a switch \xB7 Settings to manage)` }) : /* @__PURE__ */ jsx8(Text8, { color: theme.dim, children: " \xB7 Settings to add another" }),
|
|
10419
|
+
update2.kind === "updating" ? /* @__PURE__ */ jsx8(Text8, { color: theme.warn, children: ` \u2191 updating to v${update2.version}\u2026` }) : update2.kind === "updated" ? /* @__PURE__ */ jsx8(Text8, { color: theme.ok, bold: true, children: ` \u2191 v${update2.version} installed \u2014 restart (q, then solongate) to apply` }) : update2.kind === "manual" ? /* @__PURE__ */ jsx8(Text8, { color: theme.warn, children: ` \u2191 v${update2.version} available \u2014 npm i -g @solongate/proxy@latest` }) : null
|
|
10431
10420
|
] }),
|
|
10432
|
-
/* @__PURE__ */
|
|
10433
|
-
/* @__PURE__ */
|
|
10421
|
+
/* @__PURE__ */ jsxs8(Box8, { marginTop: 1, flexGrow: 1, children: [
|
|
10422
|
+
/* @__PURE__ */ jsx8(Box8, { flexDirection: "column", width: 16, borderStyle: "round", borderColor: focus === "nav" ? theme.accent : "gray", paddingX: 1, children: SECTIONS.map((s, i) => {
|
|
10434
10423
|
const isCur = i === effectiveSection;
|
|
10435
|
-
const disabled = locked && s.label !== "
|
|
10436
|
-
return /* @__PURE__ */
|
|
10424
|
+
const disabled = locked && s.label !== "Settings";
|
|
10425
|
+
return /* @__PURE__ */ jsx8(Text8, { color: isCur ? theme.accentBright : disabled ? theme.dim : void 0, bold: isCur, dimColor: disabled, children: (isCur ? "\u25B8 " : disabled ? "\u2298 " : " ") + s.label }, s.label);
|
|
10437
10426
|
}) }),
|
|
10438
|
-
/* @__PURE__ */
|
|
10427
|
+
/* @__PURE__ */ jsx8(Box8, { flexGrow: 1, borderStyle: "round", borderColor: focus === "panel" ? theme.accent : "gray", paddingX: 1, paddingY: 0, children: panelBody })
|
|
10439
10428
|
] }, viewNonce),
|
|
10440
|
-
/* @__PURE__ */
|
|
10429
|
+
/* @__PURE__ */ jsx8(Box8, { children: locked ? /* @__PURE__ */ jsx8(KeyHints, { hints: [["\u2192/enter", "open Settings"], ["n", "log in"], ["q", "quit"]] }) : focus === "nav" ? /* @__PURE__ */ jsx8(KeyHints, { hints: [["\u2191\u2193", "section"], ["\u2192/enter", "open"], ...accounts.length > 1 ? [["a", "account"]] : [], ["?", "help"], ["q", "quit"]] }) : /* @__PURE__ */ jsx8(KeyHints, { hints: [["\u2190/esc", "back"], ["\u2191\u2193", "in-panel"], ["space/s", "act"]] }) })
|
|
10441
10430
|
] });
|
|
10442
10431
|
}
|
|
10443
10432
|
function HelpOverlay({ cols, rows }) {
|
|
10444
|
-
return /* @__PURE__ */
|
|
10445
|
-
/* @__PURE__ */
|
|
10446
|
-
/* @__PURE__ */
|
|
10447
|
-
/* @__PURE__ */
|
|
10448
|
-
keys.map(([k, desc]) => /* @__PURE__ */
|
|
10449
|
-
/* @__PURE__ */
|
|
10450
|
-
/* @__PURE__ */
|
|
10433
|
+
return /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", width: cols, height: rows, paddingX: 2, paddingTop: 1, children: [
|
|
10434
|
+
/* @__PURE__ */ jsx8(Text8, { bold: true, color: theme.accentBright, children: "SolonGate \u2014 keyboard shortcuts" }),
|
|
10435
|
+
/* @__PURE__ */ jsx8(Box8, { marginTop: 1, flexDirection: "column", children: HELP.map(([group, keys]) => /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", marginBottom: 1, children: [
|
|
10436
|
+
/* @__PURE__ */ jsx8(Text8, { bold: true, color: theme.accent, children: group }),
|
|
10437
|
+
keys.map(([k, desc]) => /* @__PURE__ */ jsxs8(Text8, { children: [
|
|
10438
|
+
/* @__PURE__ */ jsx8(Text8, { color: theme.accentBright, children: (" " + k).padEnd(16) }),
|
|
10439
|
+
/* @__PURE__ */ jsx8(Text8, { color: theme.dim, children: desc })
|
|
10451
10440
|
] }, k))
|
|
10452
10441
|
] }, group)) }),
|
|
10453
|
-
/* @__PURE__ */
|
|
10442
|
+
/* @__PURE__ */ jsx8(Text8, { color: theme.dim, children: "press any key to close" })
|
|
10454
10443
|
] });
|
|
10455
10444
|
}
|
|
10456
|
-
var SECTIONS, BANNER_HEX,
|
|
10445
|
+
var SECTIONS, BANNER_HEX, SETTINGS_SECTION, HELP;
|
|
10457
10446
|
var init_App = __esm({
|
|
10458
10447
|
"src/tui/App.tsx"() {
|
|
10459
10448
|
"use strict";
|
|
@@ -10466,7 +10455,6 @@ var init_App = __esm({
|
|
|
10466
10455
|
init_Dlp();
|
|
10467
10456
|
init_Audit();
|
|
10468
10457
|
init_Settings();
|
|
10469
|
-
init_Accounts();
|
|
10470
10458
|
init_hooks();
|
|
10471
10459
|
init_client();
|
|
10472
10460
|
init_api_client();
|
|
@@ -10477,11 +10465,10 @@ var init_App = __esm({
|
|
|
10477
10465
|
{ label: "Rate Limit", Panel: RateLimitPanel },
|
|
10478
10466
|
{ label: "DLP", Panel: DlpPanel },
|
|
10479
10467
|
{ label: "Audit", Panel: AuditPanel },
|
|
10480
|
-
{ label: "Settings", Panel: SettingsPanel }
|
|
10481
|
-
{ label: "Accounts", Panel: AccountsPanel }
|
|
10468
|
+
{ label: "Settings", Panel: SettingsPanel }
|
|
10482
10469
|
];
|
|
10483
10470
|
BANNER_HEX = ["white", "white", "white", "white", "white", "white"];
|
|
10484
|
-
|
|
10471
|
+
SETTINGS_SECTION = SECTIONS.findIndex((s) => s.label === "Settings");
|
|
10485
10472
|
HELP = [
|
|
10486
10473
|
["Global", [["\u2191\u2193", "move between sections"], ["\u2192 / enter", "open a section"], ["\u2190 / esc", "back to the menu"], ["?", "this help"], ["q", "quit"]]],
|
|
10487
10474
|
["Live", [["\u2191\u2193", "select a stream row"], ["enter", "full entry content"], ["w", "whitelist the selected DENY"], ["b", "block the selected ALLOW"], ["d / x / r", "filter denies / dlp / rate-limit"], ["f", "local / cloud filter"], ["/", "search"], ["s", "sessions (\u2191\u2193 pick, enter open)"], ["space", "copy mode (freeze)"]]],
|
|
@@ -10503,7 +10490,7 @@ import { appendFileSync as appendFileSync2, mkdirSync as mkdirSync7 } from "fs";
|
|
|
10503
10490
|
import { homedir as homedir8 } from "os";
|
|
10504
10491
|
import { join as join10 } from "path";
|
|
10505
10492
|
import { render } from "ink";
|
|
10506
|
-
import { jsx as
|
|
10493
|
+
import { jsx as jsx9 } from "react/jsx-runtime";
|
|
10507
10494
|
async function launchTui() {
|
|
10508
10495
|
if (!process.stdout.isTTY || !process.stdin.isTTY) {
|
|
10509
10496
|
process.stderr.write(
|
|
@@ -10528,7 +10515,7 @@ async function launchTui() {
|
|
|
10528
10515
|
console.info = toFile("info");
|
|
10529
10516
|
console.debug = toFile("debug");
|
|
10530
10517
|
try {
|
|
10531
|
-
const { waitUntilExit } = render(/* @__PURE__ */
|
|
10518
|
+
const { waitUntilExit } = render(/* @__PURE__ */ jsx9(App, {}), { patchConsole: false });
|
|
10532
10519
|
await waitUntilExit();
|
|
10533
10520
|
} finally {
|
|
10534
10521
|
Object.assign(console, saved);
|