@solongate/proxy 0.81.90 → 0.81.92
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/commands/index.js +1 -0
- package/dist/index.js +33 -8
- package/dist/self-update.d.ts +4 -0
- package/dist/tui/index.js +131 -109
- package/package.json +1 -1
package/dist/commands/index.js
CHANGED
|
@@ -134,6 +134,7 @@ async function request(method, path, opts = {}) {
|
|
|
134
134
|
}
|
|
135
135
|
if (res.status === 401) throw new ApiError(401, "AUTHENTICATION_ERROR", "Invalid API key. Run `solongate` and log in from the Accounts panel.");
|
|
136
136
|
if (res.status === 429) throw new ApiError(429, "RATE_LIMITED", "Rate limited by the API. Slow down and retry.");
|
|
137
|
+
if (res.status >= 500) throw new ApiError(res.status, "SERVER_ERROR", text || "SolonGate API had a problem (server error). Please try again in a moment.");
|
|
137
138
|
throw new ApiError(res.status, "ERROR", text || res.statusText || `HTTP ${res.status}`);
|
|
138
139
|
}
|
|
139
140
|
return json;
|
package/dist/index.js
CHANGED
|
@@ -6558,7 +6558,9 @@ var init_cli_utils = __esm({
|
|
|
6558
6558
|
var self_update_exports = {};
|
|
6559
6559
|
__export(self_update_exports, {
|
|
6560
6560
|
currentVersion: () => currentVersion,
|
|
6561
|
+
latestVersion: () => latestVersion,
|
|
6561
6562
|
maybeSelfUpdate: () => maybeSelfUpdate,
|
|
6563
|
+
newerThan: () => newerThan,
|
|
6562
6564
|
tuiUpdateFlow: () => tuiUpdateFlow
|
|
6563
6565
|
});
|
|
6564
6566
|
import { execFile, spawn } from "child_process";
|
|
@@ -6598,6 +6600,9 @@ function newerThan(b, a) {
|
|
|
6598
6600
|
}
|
|
6599
6601
|
return false;
|
|
6600
6602
|
}
|
|
6603
|
+
async function latestVersion() {
|
|
6604
|
+
return fetchLatest();
|
|
6605
|
+
}
|
|
6601
6606
|
async function fetchLatest() {
|
|
6602
6607
|
try {
|
|
6603
6608
|
const res = await fetch(`https://registry.npmjs.org/${PKG}`, {
|
|
@@ -7274,6 +7279,7 @@ async function request(method, path, opts = {}) {
|
|
|
7274
7279
|
}
|
|
7275
7280
|
if (res.status === 401) throw new ApiError(401, "AUTHENTICATION_ERROR", "Invalid API key. Run `solongate` and log in from the Accounts panel.");
|
|
7276
7281
|
if (res.status === 429) throw new ApiError(429, "RATE_LIMITED", "Rate limited by the API. Slow down and retry.");
|
|
7282
|
+
if (res.status >= 500) throw new ApiError(res.status, "SERVER_ERROR", text || "SolonGate API had a problem (server error). Please try again in a moment.");
|
|
7277
7283
|
throw new ApiError(res.status, "ERROR", text || res.statusText || `HTTP ${res.status}`);
|
|
7278
7284
|
}
|
|
7279
7285
|
return json;
|
|
@@ -9109,7 +9115,7 @@ function RateLimitPanel({ focused }) {
|
|
|
9109
9115
|
const [status, setStatus] = useState4(null);
|
|
9110
9116
|
useEffect4(() => {
|
|
9111
9117
|
if (layersQ.data && !dirty) setDraft({ ...layersQ.data.layers.rateLimit });
|
|
9112
|
-
}, [layersQ.data
|
|
9118
|
+
}, [layersQ.data]);
|
|
9113
9119
|
usePoll(() => {
|
|
9114
9120
|
if (!dirty) layersQ.reloadQuiet();
|
|
9115
9121
|
historyQ.reloadQuiet();
|
|
@@ -9131,6 +9137,7 @@ function RateLimitPanel({ focused }) {
|
|
|
9131
9137
|
setDraft({ ...res.layers.rateLimit });
|
|
9132
9138
|
setDirty(false);
|
|
9133
9139
|
setStatus("\u2713 Saved");
|
|
9140
|
+
layersQ.reload();
|
|
9134
9141
|
historyQ.reload();
|
|
9135
9142
|
insightsQ.reload();
|
|
9136
9143
|
} catch (e) {
|
|
@@ -9191,14 +9198,14 @@ function RateLimitPanel({ focused }) {
|
|
|
9191
9198
|
/* @__PURE__ */ jsx4(BusiestRow, { label: "hour", peak: peaks.hour, limit: draft.perHour }),
|
|
9192
9199
|
/* @__PURE__ */ jsx4(BusiestRow, { label: "day", peak: peaks.day, limit: draft.perDay }),
|
|
9193
9200
|
/* @__PURE__ */ jsx4(Text4, { color: theme.dim, wrap: "truncate", children: `activity`.padEnd(11) + ` last 24h \xB7 ${last24h} calls \xB7 busiest hour ${peaks.hour}/hr` }),
|
|
9194
|
-
/* @__PURE__ */ jsxs4(Box4, {
|
|
9201
|
+
/* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", children: [
|
|
9195
9202
|
/* @__PURE__ */ jsxs4(Text4, { color: theme.accentBright, bold: true, wrap: "truncate", children: [
|
|
9196
9203
|
`Recent bursts 7d${anomalies2.length ? ` (${anomalies2.length})` : ""}`,
|
|
9197
9204
|
/* @__PURE__ */ jsx4(Text4, { color: theme.dim, children: " over the per-minute limit \xB7 Bypassed = detect (not blocked)" })
|
|
9198
9205
|
] }),
|
|
9199
9206
|
anomalies2.length === 0 ? /* @__PURE__ */ jsxs4(Text4, { color: theme.dim, children: [
|
|
9200
9207
|
" ",
|
|
9201
|
-
insightsQ.loading ? "loading\u2026" : "no bursts in the last 7 days"
|
|
9208
|
+
insightsQ.loading ? "loading\u2026" : insightsQ.error ? `couldn't load bursts: ${String(insightsQ.error).slice(0, 60)}` : "no bursts in the last 7 days"
|
|
9202
9209
|
] }) : /* @__PURE__ */ jsx4(
|
|
9203
9210
|
Table,
|
|
9204
9211
|
{
|
|
@@ -9279,7 +9286,7 @@ function DlpPanel({ focused }) {
|
|
|
9279
9286
|
setGhostOn(q.data.layers.ghost.mode === "on");
|
|
9280
9287
|
setGhostPats([...q.data.layers.ghost.patterns]);
|
|
9281
9288
|
}
|
|
9282
|
-
}, [q.data
|
|
9289
|
+
}, [q.data]);
|
|
9283
9290
|
usePoll(() => {
|
|
9284
9291
|
if (!dirty && !adding) q.reloadQuiet();
|
|
9285
9292
|
}, 6e3);
|
|
@@ -9299,6 +9306,7 @@ function DlpPanel({ focused }) {
|
|
|
9299
9306
|
setGhostPats([...res.layers.ghost.patterns]);
|
|
9300
9307
|
setDirty(false);
|
|
9301
9308
|
setStatus("\u2713 Saved");
|
|
9309
|
+
q.reload();
|
|
9302
9310
|
} catch (e) {
|
|
9303
9311
|
setStatus("\u2717 " + (e instanceof Error ? e.message : String(e)));
|
|
9304
9312
|
}
|
|
@@ -10355,6 +10363,18 @@ function SettingsPanel({
|
|
|
10355
10363
|
const [msg, setMsg] = useState7(null);
|
|
10356
10364
|
const [busy, setBusy] = useState7(false);
|
|
10357
10365
|
const [editor, setEditor] = useState7(null);
|
|
10366
|
+
const [latest, setLatest] = useState7(null);
|
|
10367
|
+
const ver = currentVersion();
|
|
10368
|
+
useEffect6(() => {
|
|
10369
|
+
let live2 = true;
|
|
10370
|
+
latestVersion().then((v) => {
|
|
10371
|
+
if (live2) setLatest(v);
|
|
10372
|
+
}).catch(() => {
|
|
10373
|
+
});
|
|
10374
|
+
return () => {
|
|
10375
|
+
live2 = false;
|
|
10376
|
+
};
|
|
10377
|
+
}, []);
|
|
10358
10378
|
const [accounts, setAccounts] = useState7(() => listAccounts());
|
|
10359
10379
|
const [login, setLogin] = useState7(null);
|
|
10360
10380
|
const [tick, setTick] = useState7(0);
|
|
@@ -10908,7 +10928,7 @@ function SettingsPanel({
|
|
|
10908
10928
|
);
|
|
10909
10929
|
lineKey.push("");
|
|
10910
10930
|
}
|
|
10911
|
-
const budget = Math.max(4, rows -
|
|
10931
|
+
const budget = Math.max(4, rows - 3);
|
|
10912
10932
|
const selLine = Math.max(0, lineKey.indexOf(keyOf(cur)));
|
|
10913
10933
|
const maxStart = Math.max(0, lineEls.length - budget);
|
|
10914
10934
|
const startL = Math.min(Math.max(0, selLine - Math.floor(budget / 2)), maxStart);
|
|
@@ -10921,7 +10941,11 @@ function SettingsPanel({
|
|
|
10921
10941
|
/* @__PURE__ */ jsx7(Text7, { color: theme.warn, children: editing === "path" ? "local log path: " : "webhook url: " }),
|
|
10922
10942
|
/* @__PURE__ */ jsx7(TextInput5, { value: input, onChange: setInput, onSubmit: submitInput })
|
|
10923
10943
|
] }) : msg ? /* @__PURE__ */ jsx7(Text7, { wrap: "truncate", color: msg.level === "bad" ? theme.bad : theme.ok, children: truncate2(msg.text, cols) }) : login?.msg ? /* @__PURE__ */ jsx7(Text7, { wrap: "truncate", color: login.phase === "error" ? theme.bad : theme.ok, children: login.msg }) : /* @__PURE__ */ jsx7(Text7, { children: " " }),
|
|
10924
|
-
/* @__PURE__ */ jsx7(Box7, { flexDirection: "column", height: budget, overflow: "hidden", children: win })
|
|
10944
|
+
/* @__PURE__ */ jsx7(Box7, { flexDirection: "column", height: budget, overflow: "hidden", children: win }),
|
|
10945
|
+
/* @__PURE__ */ jsxs7(Text7, { wrap: "truncate", color: theme.dim, children: [
|
|
10946
|
+
`solongate v${ver}`,
|
|
10947
|
+
latest ? newerThan(latest, ver) ? /* @__PURE__ */ jsx7(Text7, { color: theme.warn, children: ` \xB7 v${latest} on npm \u2014 auto-updating` }) : /* @__PURE__ */ jsx7(Text7, { color: theme.ok, children: " \xB7 latest" }) : null
|
|
10948
|
+
] })
|
|
10925
10949
|
] }) });
|
|
10926
10950
|
}
|
|
10927
10951
|
var EVENTS, SPIN2, SIGNALS2, SIGNAL_LABEL, WINDOWS, winLabel, THRESH_MIN, THRESH_MAX, nearestWindowIdx, editorFieldCount, acctLabel, alertChannel;
|
|
@@ -10933,6 +10957,7 @@ var init_Settings = __esm({
|
|
|
10933
10957
|
init_device_login();
|
|
10934
10958
|
init_global_install();
|
|
10935
10959
|
init_logs_server_daemon();
|
|
10960
|
+
init_self_update();
|
|
10936
10961
|
init_components();
|
|
10937
10962
|
init_hooks();
|
|
10938
10963
|
init_theme();
|
|
@@ -14973,9 +14998,9 @@ var PolicyStore = class {
|
|
|
14973
14998
|
saveVersion(policySet, reason, createdBy) {
|
|
14974
14999
|
const id = policySet.id;
|
|
14975
15000
|
const history = this.versions.get(id) ?? [];
|
|
14976
|
-
const
|
|
15001
|
+
const latestVersion2 = history.length > 0 ? history[history.length - 1].version : 0;
|
|
14977
15002
|
const version = {
|
|
14978
|
-
version:
|
|
15003
|
+
version: latestVersion2 + 1,
|
|
14979
15004
|
policySet: Object.freeze({ ...policySet }),
|
|
14980
15005
|
hash: this.computeHash(policySet),
|
|
14981
15006
|
reason,
|
package/dist/self-update.d.ts
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
export declare function currentVersion(): string;
|
|
2
|
+
/** true when `b` is a strictly newer semver than `a` (numeric triples only). */
|
|
3
|
+
export declare function newerThan(b: string, a: string): boolean;
|
|
4
|
+
/** The latest version published to npm, or null if it can't be reached. */
|
|
5
|
+
export declare function latestVersion(): Promise<string | null>;
|
|
2
6
|
/** What the dataroom shows about the updater. */
|
|
3
7
|
export type UpdateStatus = {
|
|
4
8
|
kind: 'idle';
|
package/dist/tui/index.js
CHANGED
|
@@ -504,6 +504,7 @@ async function request(method, path, opts = {}) {
|
|
|
504
504
|
}
|
|
505
505
|
if (res.status === 401) throw new ApiError(401, "AUTHENTICATION_ERROR", "Invalid API key. Run `solongate` and log in from the Accounts panel.");
|
|
506
506
|
if (res.status === 429) throw new ApiError(429, "RATE_LIMITED", "Rate limited by the API. Slow down and retry.");
|
|
507
|
+
if (res.status >= 500) throw new ApiError(res.status, "SERVER_ERROR", text || "SolonGate API had a problem (server error). Please try again in a moment.");
|
|
507
508
|
throw new ApiError(res.status, "ERROR", text || res.statusText || `HTTP ${res.status}`);
|
|
508
509
|
}
|
|
509
510
|
return json;
|
|
@@ -2202,7 +2203,7 @@ function RateLimitPanel({ focused }) {
|
|
|
2202
2203
|
const [status, setStatus] = useState4(null);
|
|
2203
2204
|
useEffect4(() => {
|
|
2204
2205
|
if (layersQ.data && !dirty) setDraft({ ...layersQ.data.layers.rateLimit });
|
|
2205
|
-
}, [layersQ.data
|
|
2206
|
+
}, [layersQ.data]);
|
|
2206
2207
|
usePoll(() => {
|
|
2207
2208
|
if (!dirty) layersQ.reloadQuiet();
|
|
2208
2209
|
historyQ.reloadQuiet();
|
|
@@ -2224,6 +2225,7 @@ function RateLimitPanel({ focused }) {
|
|
|
2224
2225
|
setDraft({ ...res.layers.rateLimit });
|
|
2225
2226
|
setDirty(false);
|
|
2226
2227
|
setStatus("\u2713 Saved");
|
|
2228
|
+
layersQ.reload();
|
|
2227
2229
|
historyQ.reload();
|
|
2228
2230
|
insightsQ.reload();
|
|
2229
2231
|
} catch (e) {
|
|
@@ -2284,14 +2286,14 @@ function RateLimitPanel({ focused }) {
|
|
|
2284
2286
|
/* @__PURE__ */ jsx4(BusiestRow, { label: "hour", peak: peaks.hour, limit: draft.perHour }),
|
|
2285
2287
|
/* @__PURE__ */ jsx4(BusiestRow, { label: "day", peak: peaks.day, limit: draft.perDay }),
|
|
2286
2288
|
/* @__PURE__ */ jsx4(Text4, { color: theme.dim, wrap: "truncate", children: `activity`.padEnd(11) + ` last 24h \xB7 ${last24h} calls \xB7 busiest hour ${peaks.hour}/hr` }),
|
|
2287
|
-
/* @__PURE__ */ jsxs4(Box4, {
|
|
2289
|
+
/* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", children: [
|
|
2288
2290
|
/* @__PURE__ */ jsxs4(Text4, { color: theme.accentBright, bold: true, wrap: "truncate", children: [
|
|
2289
2291
|
`Recent bursts 7d${anomalies2.length ? ` (${anomalies2.length})` : ""}`,
|
|
2290
2292
|
/* @__PURE__ */ jsx4(Text4, { color: theme.dim, children: " over the per-minute limit \xB7 Bypassed = detect (not blocked)" })
|
|
2291
2293
|
] }),
|
|
2292
2294
|
anomalies2.length === 0 ? /* @__PURE__ */ jsxs4(Text4, { color: theme.dim, children: [
|
|
2293
2295
|
" ",
|
|
2294
|
-
insightsQ.loading ? "loading\u2026" : "no bursts in the last 7 days"
|
|
2296
|
+
insightsQ.loading ? "loading\u2026" : insightsQ.error ? `couldn't load bursts: ${String(insightsQ.error).slice(0, 60)}` : "no bursts in the last 7 days"
|
|
2295
2297
|
] }) : /* @__PURE__ */ jsx4(
|
|
2296
2298
|
Table,
|
|
2297
2299
|
{
|
|
@@ -2357,7 +2359,7 @@ function DlpPanel({ focused }) {
|
|
|
2357
2359
|
setGhostOn(q.data.layers.ghost.mode === "on");
|
|
2358
2360
|
setGhostPats([...q.data.layers.ghost.patterns]);
|
|
2359
2361
|
}
|
|
2360
|
-
}, [q.data
|
|
2362
|
+
}, [q.data]);
|
|
2361
2363
|
usePoll(() => {
|
|
2362
2364
|
if (!dirty && !adding) q.reloadQuiet();
|
|
2363
2365
|
}, 6e3);
|
|
@@ -2377,6 +2379,7 @@ function DlpPanel({ focused }) {
|
|
|
2377
2379
|
setGhostPats([...res.layers.ghost.patterns]);
|
|
2378
2380
|
setDirty(false);
|
|
2379
2381
|
setStatus("\u2713 Saved");
|
|
2382
|
+
q.reload();
|
|
2380
2383
|
} catch (e) {
|
|
2381
2384
|
setStatus("\u2717 " + (e instanceof Error ? e.message : String(e)));
|
|
2382
2385
|
}
|
|
@@ -3464,6 +3467,112 @@ function stopLogsServerDaemon() {
|
|
|
3464
3467
|
return { desired: "off", running: false, port: s.port || LOGS_SERVER_PORT };
|
|
3465
3468
|
}
|
|
3466
3469
|
|
|
3470
|
+
// src/self-update.ts
|
|
3471
|
+
import { execFile, spawn as spawn4 } from "child_process";
|
|
3472
|
+
import { mkdirSync as mkdirSync6, openSync as openSync3, readFileSync as readFileSync6, writeFileSync as writeFileSync7 } from "fs";
|
|
3473
|
+
import { homedir as homedir8 } from "os";
|
|
3474
|
+
import { dirname as dirname3, join as join8 } from "path";
|
|
3475
|
+
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
3476
|
+
var PKG = "@solongate/proxy";
|
|
3477
|
+
var CHECK_EVERY_MS = 30 * 60 * 1e3;
|
|
3478
|
+
var ATTEMPT_EVERY_MS = 6 * 60 * 60 * 1e3;
|
|
3479
|
+
var STATE_FILE2 = join8(homedir8(), ".solongate", ".self-update.json");
|
|
3480
|
+
var LOG_FILE2 = join8(homedir8(), ".solongate", "self-update.log");
|
|
3481
|
+
function readState2() {
|
|
3482
|
+
try {
|
|
3483
|
+
const s = JSON.parse(readFileSync6(STATE_FILE2, "utf-8"));
|
|
3484
|
+
return s && typeof s === "object" ? s : {};
|
|
3485
|
+
} catch {
|
|
3486
|
+
return {};
|
|
3487
|
+
}
|
|
3488
|
+
}
|
|
3489
|
+
function writeState2(s) {
|
|
3490
|
+
try {
|
|
3491
|
+
mkdirSync6(join8(homedir8(), ".solongate"), { recursive: true });
|
|
3492
|
+
writeFileSync7(STATE_FILE2, JSON.stringify(s));
|
|
3493
|
+
} catch {
|
|
3494
|
+
}
|
|
3495
|
+
}
|
|
3496
|
+
function currentVersion() {
|
|
3497
|
+
try {
|
|
3498
|
+
const pkg = JSON.parse(readFileSync6(join8(dirname3(fileURLToPath3(import.meta.url)), "..", "package.json"), "utf-8"));
|
|
3499
|
+
return pkg.version ?? "0.0.0";
|
|
3500
|
+
} catch {
|
|
3501
|
+
return "0.0.0";
|
|
3502
|
+
}
|
|
3503
|
+
}
|
|
3504
|
+
function newerThan(b, a) {
|
|
3505
|
+
const pa = a.split(".").map((n) => parseInt(n, 10) || 0);
|
|
3506
|
+
const pb = b.split(".").map((n) => parseInt(n, 10) || 0);
|
|
3507
|
+
for (let i = 0; i < 3; i++) {
|
|
3508
|
+
if ((pb[i] ?? 0) > (pa[i] ?? 0)) return true;
|
|
3509
|
+
if ((pb[i] ?? 0) < (pa[i] ?? 0)) return false;
|
|
3510
|
+
}
|
|
3511
|
+
return false;
|
|
3512
|
+
}
|
|
3513
|
+
async function latestVersion() {
|
|
3514
|
+
return fetchLatest();
|
|
3515
|
+
}
|
|
3516
|
+
async function fetchLatest() {
|
|
3517
|
+
try {
|
|
3518
|
+
const res = await fetch(`https://registry.npmjs.org/${PKG}`, {
|
|
3519
|
+
headers: { accept: "application/vnd.npm.install-v1+json" },
|
|
3520
|
+
signal: AbortSignal.timeout(3e3)
|
|
3521
|
+
});
|
|
3522
|
+
if (!res.ok) return null;
|
|
3523
|
+
const j = await res.json();
|
|
3524
|
+
const latest = j["dist-tags"]?.latest;
|
|
3525
|
+
if (typeof latest !== "string") return null;
|
|
3526
|
+
if (!j.versions || !(latest in j.versions)) return null;
|
|
3527
|
+
return latest;
|
|
3528
|
+
} catch {
|
|
3529
|
+
return null;
|
|
3530
|
+
}
|
|
3531
|
+
}
|
|
3532
|
+
function runGlobalInstall(version) {
|
|
3533
|
+
return new Promise((resolve3) => {
|
|
3534
|
+
try {
|
|
3535
|
+
mkdirSync6(join8(homedir8(), ".solongate"), { recursive: true });
|
|
3536
|
+
execFile(
|
|
3537
|
+
"npm",
|
|
3538
|
+
["install", "-g", `${PKG}@${version}`],
|
|
3539
|
+
{ timeout: 3e5, windowsHide: true, shell: process.platform === "win32" },
|
|
3540
|
+
(err, stdout, stderr) => {
|
|
3541
|
+
try {
|
|
3542
|
+
writeFileSync7(LOG_FILE2, `${(/* @__PURE__ */ new Date()).toISOString()} install ${version}: ${err ? "FAILED" : "ok"}
|
|
3543
|
+
${stdout}
|
|
3544
|
+
${stderr}
|
|
3545
|
+
`, { flag: "a" });
|
|
3546
|
+
} catch {
|
|
3547
|
+
}
|
|
3548
|
+
resolve3(!err);
|
|
3549
|
+
}
|
|
3550
|
+
);
|
|
3551
|
+
} catch {
|
|
3552
|
+
resolve3(false);
|
|
3553
|
+
}
|
|
3554
|
+
});
|
|
3555
|
+
}
|
|
3556
|
+
async function tuiUpdateFlow(onStatus) {
|
|
3557
|
+
try {
|
|
3558
|
+
const current = currentVersion();
|
|
3559
|
+
const latest = await fetchLatest();
|
|
3560
|
+
const state = readState2();
|
|
3561
|
+
if (latest) writeState2({ ...state, lastCheckAt: Date.now(), latestSeen: latest });
|
|
3562
|
+
if (!latest || !newerThan(latest, current)) return;
|
|
3563
|
+
if (readState2().installed === latest) {
|
|
3564
|
+
onStatus({ kind: "updated", version: latest });
|
|
3565
|
+
return;
|
|
3566
|
+
}
|
|
3567
|
+
onStatus({ kind: "updating", version: latest });
|
|
3568
|
+
if (await runGlobalInstall(latest)) {
|
|
3569
|
+
writeState2({ ...readState2(), installed: latest });
|
|
3570
|
+
onStatus({ kind: "updated", version: latest });
|
|
3571
|
+
}
|
|
3572
|
+
} catch {
|
|
3573
|
+
}
|
|
3574
|
+
}
|
|
3575
|
+
|
|
3467
3576
|
// src/tui/panels/Settings.tsx
|
|
3468
3577
|
import { Fragment as Fragment4, jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
3469
3578
|
var EVENTS = ["denials", "allowed", "all"];
|
|
@@ -3498,6 +3607,18 @@ function SettingsPanel({
|
|
|
3498
3607
|
const [msg, setMsg] = useState7(null);
|
|
3499
3608
|
const [busy, setBusy] = useState7(false);
|
|
3500
3609
|
const [editor, setEditor] = useState7(null);
|
|
3610
|
+
const [latest, setLatest] = useState7(null);
|
|
3611
|
+
const ver = currentVersion();
|
|
3612
|
+
useEffect6(() => {
|
|
3613
|
+
let live2 = true;
|
|
3614
|
+
latestVersion().then((v) => {
|
|
3615
|
+
if (live2) setLatest(v);
|
|
3616
|
+
}).catch(() => {
|
|
3617
|
+
});
|
|
3618
|
+
return () => {
|
|
3619
|
+
live2 = false;
|
|
3620
|
+
};
|
|
3621
|
+
}, []);
|
|
3501
3622
|
const [accounts, setAccounts] = useState7(() => listAccounts());
|
|
3502
3623
|
const [login, setLogin] = useState7(null);
|
|
3503
3624
|
const [tick, setTick] = useState7(0);
|
|
@@ -4051,7 +4172,7 @@ function SettingsPanel({
|
|
|
4051
4172
|
);
|
|
4052
4173
|
lineKey.push("");
|
|
4053
4174
|
}
|
|
4054
|
-
const budget = Math.max(4, rows -
|
|
4175
|
+
const budget = Math.max(4, rows - 3);
|
|
4055
4176
|
const selLine = Math.max(0, lineKey.indexOf(keyOf(cur)));
|
|
4056
4177
|
const maxStart = Math.max(0, lineEls.length - budget);
|
|
4057
4178
|
const startL = Math.min(Math.max(0, selLine - Math.floor(budget / 2)), maxStart);
|
|
@@ -4064,113 +4185,14 @@ function SettingsPanel({
|
|
|
4064
4185
|
/* @__PURE__ */ jsx7(Text7, { color: theme.warn, children: editing === "path" ? "local log path: " : "webhook url: " }),
|
|
4065
4186
|
/* @__PURE__ */ jsx7(TextInput5, { value: input, onChange: setInput, onSubmit: submitInput })
|
|
4066
4187
|
] }) : msg ? /* @__PURE__ */ jsx7(Text7, { wrap: "truncate", color: msg.level === "bad" ? theme.bad : theme.ok, children: truncate(msg.text, cols) }) : login?.msg ? /* @__PURE__ */ jsx7(Text7, { wrap: "truncate", color: login.phase === "error" ? theme.bad : theme.ok, children: login.msg }) : /* @__PURE__ */ jsx7(Text7, { children: " " }),
|
|
4067
|
-
/* @__PURE__ */ jsx7(Box7, { flexDirection: "column", height: budget, overflow: "hidden", children: win })
|
|
4188
|
+
/* @__PURE__ */ jsx7(Box7, { flexDirection: "column", height: budget, overflow: "hidden", children: win }),
|
|
4189
|
+
/* @__PURE__ */ jsxs7(Text7, { wrap: "truncate", color: theme.dim, children: [
|
|
4190
|
+
`solongate v${ver}`,
|
|
4191
|
+
latest ? newerThan(latest, ver) ? /* @__PURE__ */ jsx7(Text7, { color: theme.warn, children: ` \xB7 v${latest} on npm \u2014 auto-updating` }) : /* @__PURE__ */ jsx7(Text7, { color: theme.ok, children: " \xB7 latest" }) : null
|
|
4192
|
+
] })
|
|
4068
4193
|
] }) });
|
|
4069
4194
|
}
|
|
4070
4195
|
|
|
4071
|
-
// src/self-update.ts
|
|
4072
|
-
import { execFile, spawn as spawn4 } from "child_process";
|
|
4073
|
-
import { mkdirSync as mkdirSync6, openSync as openSync3, readFileSync as readFileSync6, writeFileSync as writeFileSync7 } from "fs";
|
|
4074
|
-
import { homedir as homedir8 } from "os";
|
|
4075
|
-
import { dirname as dirname3, join as join8 } from "path";
|
|
4076
|
-
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
4077
|
-
var PKG = "@solongate/proxy";
|
|
4078
|
-
var CHECK_EVERY_MS = 30 * 60 * 1e3;
|
|
4079
|
-
var ATTEMPT_EVERY_MS = 6 * 60 * 60 * 1e3;
|
|
4080
|
-
var STATE_FILE2 = join8(homedir8(), ".solongate", ".self-update.json");
|
|
4081
|
-
var LOG_FILE2 = join8(homedir8(), ".solongate", "self-update.log");
|
|
4082
|
-
function readState2() {
|
|
4083
|
-
try {
|
|
4084
|
-
const s = JSON.parse(readFileSync6(STATE_FILE2, "utf-8"));
|
|
4085
|
-
return s && typeof s === "object" ? s : {};
|
|
4086
|
-
} catch {
|
|
4087
|
-
return {};
|
|
4088
|
-
}
|
|
4089
|
-
}
|
|
4090
|
-
function writeState2(s) {
|
|
4091
|
-
try {
|
|
4092
|
-
mkdirSync6(join8(homedir8(), ".solongate"), { recursive: true });
|
|
4093
|
-
writeFileSync7(STATE_FILE2, JSON.stringify(s));
|
|
4094
|
-
} catch {
|
|
4095
|
-
}
|
|
4096
|
-
}
|
|
4097
|
-
function currentVersion() {
|
|
4098
|
-
try {
|
|
4099
|
-
const pkg = JSON.parse(readFileSync6(join8(dirname3(fileURLToPath3(import.meta.url)), "..", "package.json"), "utf-8"));
|
|
4100
|
-
return pkg.version ?? "0.0.0";
|
|
4101
|
-
} catch {
|
|
4102
|
-
return "0.0.0";
|
|
4103
|
-
}
|
|
4104
|
-
}
|
|
4105
|
-
function newerThan(b, a) {
|
|
4106
|
-
const pa = a.split(".").map((n) => parseInt(n, 10) || 0);
|
|
4107
|
-
const pb = b.split(".").map((n) => parseInt(n, 10) || 0);
|
|
4108
|
-
for (let i = 0; i < 3; i++) {
|
|
4109
|
-
if ((pb[i] ?? 0) > (pa[i] ?? 0)) return true;
|
|
4110
|
-
if ((pb[i] ?? 0) < (pa[i] ?? 0)) return false;
|
|
4111
|
-
}
|
|
4112
|
-
return false;
|
|
4113
|
-
}
|
|
4114
|
-
async function fetchLatest() {
|
|
4115
|
-
try {
|
|
4116
|
-
const res = await fetch(`https://registry.npmjs.org/${PKG}`, {
|
|
4117
|
-
headers: { accept: "application/vnd.npm.install-v1+json" },
|
|
4118
|
-
signal: AbortSignal.timeout(3e3)
|
|
4119
|
-
});
|
|
4120
|
-
if (!res.ok) return null;
|
|
4121
|
-
const j = await res.json();
|
|
4122
|
-
const latest = j["dist-tags"]?.latest;
|
|
4123
|
-
if (typeof latest !== "string") return null;
|
|
4124
|
-
if (!j.versions || !(latest in j.versions)) return null;
|
|
4125
|
-
return latest;
|
|
4126
|
-
} catch {
|
|
4127
|
-
return null;
|
|
4128
|
-
}
|
|
4129
|
-
}
|
|
4130
|
-
function runGlobalInstall(version) {
|
|
4131
|
-
return new Promise((resolve3) => {
|
|
4132
|
-
try {
|
|
4133
|
-
mkdirSync6(join8(homedir8(), ".solongate"), { recursive: true });
|
|
4134
|
-
execFile(
|
|
4135
|
-
"npm",
|
|
4136
|
-
["install", "-g", `${PKG}@${version}`],
|
|
4137
|
-
{ timeout: 3e5, windowsHide: true, shell: process.platform === "win32" },
|
|
4138
|
-
(err, stdout, stderr) => {
|
|
4139
|
-
try {
|
|
4140
|
-
writeFileSync7(LOG_FILE2, `${(/* @__PURE__ */ new Date()).toISOString()} install ${version}: ${err ? "FAILED" : "ok"}
|
|
4141
|
-
${stdout}
|
|
4142
|
-
${stderr}
|
|
4143
|
-
`, { flag: "a" });
|
|
4144
|
-
} catch {
|
|
4145
|
-
}
|
|
4146
|
-
resolve3(!err);
|
|
4147
|
-
}
|
|
4148
|
-
);
|
|
4149
|
-
} catch {
|
|
4150
|
-
resolve3(false);
|
|
4151
|
-
}
|
|
4152
|
-
});
|
|
4153
|
-
}
|
|
4154
|
-
async function tuiUpdateFlow(onStatus) {
|
|
4155
|
-
try {
|
|
4156
|
-
const current = currentVersion();
|
|
4157
|
-
const latest = await fetchLatest();
|
|
4158
|
-
const state = readState2();
|
|
4159
|
-
if (latest) writeState2({ ...state, lastCheckAt: Date.now(), latestSeen: latest });
|
|
4160
|
-
if (!latest || !newerThan(latest, current)) return;
|
|
4161
|
-
if (readState2().installed === latest) {
|
|
4162
|
-
onStatus({ kind: "updated", version: latest });
|
|
4163
|
-
return;
|
|
4164
|
-
}
|
|
4165
|
-
onStatus({ kind: "updating", version: latest });
|
|
4166
|
-
if (await runGlobalInstall(latest)) {
|
|
4167
|
-
writeState2({ ...readState2(), installed: latest });
|
|
4168
|
-
onStatus({ kind: "updated", version: latest });
|
|
4169
|
-
}
|
|
4170
|
-
} catch {
|
|
4171
|
-
}
|
|
4172
|
-
}
|
|
4173
|
-
|
|
4174
4196
|
// src/tui/App.tsx
|
|
4175
4197
|
import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
4176
4198
|
function LiveHint() {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@solongate/proxy",
|
|
3
|
-
"version": "0.81.
|
|
3
|
+
"version": "0.81.92",
|
|
4
4
|
"description": "AI tool security proxy: protect any AI tool server with customizable policies, path/command constraints, rate limiting, and audit logging. No code changes required.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|