@solongate/proxy 0.81.91 → 0.81.93

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 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}`, {
@@ -9193,14 +9198,14 @@ function RateLimitPanel({ focused }) {
9193
9198
  /* @__PURE__ */ jsx4(BusiestRow, { label: "hour", peak: peaks.hour, limit: draft.perHour }),
9194
9199
  /* @__PURE__ */ jsx4(BusiestRow, { label: "day", peak: peaks.day, limit: draft.perDay }),
9195
9200
  /* @__PURE__ */ jsx4(Text4, { color: theme.dim, wrap: "truncate", children: `activity`.padEnd(11) + ` last 24h \xB7 ${last24h} calls \xB7 busiest hour ${peaks.hour}/hr` }),
9196
- /* @__PURE__ */ jsxs4(Box4, { marginTop: 1, flexDirection: "column", children: [
9201
+ /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", children: [
9197
9202
  /* @__PURE__ */ jsxs4(Text4, { color: theme.accentBright, bold: true, wrap: "truncate", children: [
9198
9203
  `Recent bursts 7d${anomalies2.length ? ` (${anomalies2.length})` : ""}`,
9199
9204
  /* @__PURE__ */ jsx4(Text4, { color: theme.dim, children: " over the per-minute limit \xB7 Bypassed = detect (not blocked)" })
9200
9205
  ] }),
9201
9206
  anomalies2.length === 0 ? /* @__PURE__ */ jsxs4(Text4, { color: theme.dim, children: [
9202
9207
  " ",
9203
- 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"
9204
9209
  ] }) : /* @__PURE__ */ jsx4(
9205
9210
  Table,
9206
9211
  {
@@ -10358,6 +10363,18 @@ function SettingsPanel({
10358
10363
  const [msg, setMsg] = useState7(null);
10359
10364
  const [busy, setBusy] = useState7(false);
10360
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
+ }, []);
10361
10378
  const [accounts, setAccounts] = useState7(() => listAccounts());
10362
10379
  const [login, setLogin] = useState7(null);
10363
10380
  const [tick, setTick] = useState7(0);
@@ -10911,6 +10928,15 @@ function SettingsPanel({
10911
10928
  );
10912
10929
  lineKey.push("");
10913
10930
  }
10931
+ lineEls.push(/* @__PURE__ */ jsx7(Text7, { children: " " }, "ver-sp"));
10932
+ lineKey.push("");
10933
+ lineEls.push(
10934
+ /* @__PURE__ */ jsxs7(Text7, { wrap: "truncate", color: theme.dim, children: [
10935
+ `solongate v${ver}`,
10936
+ 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
10937
+ ] }, "ver")
10938
+ );
10939
+ lineKey.push("");
10914
10940
  const budget = Math.max(4, rows - 2);
10915
10941
  const selLine = Math.max(0, lineKey.indexOf(keyOf(cur)));
10916
10942
  const maxStart = Math.max(0, lineEls.length - budget);
@@ -10936,6 +10962,7 @@ var init_Settings = __esm({
10936
10962
  init_device_login();
10937
10963
  init_global_install();
10938
10964
  init_logs_server_daemon();
10965
+ init_self_update();
10939
10966
  init_components();
10940
10967
  init_hooks();
10941
10968
  init_theme();
@@ -14976,9 +15003,9 @@ var PolicyStore = class {
14976
15003
  saveVersion(policySet, reason, createdBy) {
14977
15004
  const id = policySet.id;
14978
15005
  const history = this.versions.get(id) ?? [];
14979
- const latestVersion = history.length > 0 ? history[history.length - 1].version : 0;
15006
+ const latestVersion2 = history.length > 0 ? history[history.length - 1].version : 0;
14980
15007
  const version = {
14981
- version: latestVersion + 1,
15008
+ version: latestVersion2 + 1,
14982
15009
  policySet: Object.freeze({ ...policySet }),
14983
15010
  hash: this.computeHash(policySet),
14984
15011
  reason,
@@ -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
@@ -2286,14 +2286,14 @@ function RateLimitPanel({ focused }) {
2286
2286
  /* @__PURE__ */ jsx4(BusiestRow, { label: "hour", peak: peaks.hour, limit: draft.perHour }),
2287
2287
  /* @__PURE__ */ jsx4(BusiestRow, { label: "day", peak: peaks.day, limit: draft.perDay }),
2288
2288
  /* @__PURE__ */ jsx4(Text4, { color: theme.dim, wrap: "truncate", children: `activity`.padEnd(11) + ` last 24h \xB7 ${last24h} calls \xB7 busiest hour ${peaks.hour}/hr` }),
2289
- /* @__PURE__ */ jsxs4(Box4, { marginTop: 1, flexDirection: "column", children: [
2289
+ /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", children: [
2290
2290
  /* @__PURE__ */ jsxs4(Text4, { color: theme.accentBright, bold: true, wrap: "truncate", children: [
2291
2291
  `Recent bursts 7d${anomalies2.length ? ` (${anomalies2.length})` : ""}`,
2292
2292
  /* @__PURE__ */ jsx4(Text4, { color: theme.dim, children: " over the per-minute limit \xB7 Bypassed = detect (not blocked)" })
2293
2293
  ] }),
2294
2294
  anomalies2.length === 0 ? /* @__PURE__ */ jsxs4(Text4, { color: theme.dim, children: [
2295
2295
  " ",
2296
- 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"
2297
2297
  ] }) : /* @__PURE__ */ jsx4(
2298
2298
  Table,
2299
2299
  {
@@ -3467,6 +3467,112 @@ function stopLogsServerDaemon() {
3467
3467
  return { desired: "off", running: false, port: s.port || LOGS_SERVER_PORT };
3468
3468
  }
3469
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
+
3470
3576
  // src/tui/panels/Settings.tsx
3471
3577
  import { Fragment as Fragment4, jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
3472
3578
  var EVENTS = ["denials", "allowed", "all"];
@@ -3501,6 +3607,18 @@ function SettingsPanel({
3501
3607
  const [msg, setMsg] = useState7(null);
3502
3608
  const [busy, setBusy] = useState7(false);
3503
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
+ }, []);
3504
3622
  const [accounts, setAccounts] = useState7(() => listAccounts());
3505
3623
  const [login, setLogin] = useState7(null);
3506
3624
  const [tick, setTick] = useState7(0);
@@ -4054,6 +4172,15 @@ function SettingsPanel({
4054
4172
  );
4055
4173
  lineKey.push("");
4056
4174
  }
4175
+ lineEls.push(/* @__PURE__ */ jsx7(Text7, { children: " " }, "ver-sp"));
4176
+ lineKey.push("");
4177
+ lineEls.push(
4178
+ /* @__PURE__ */ jsxs7(Text7, { wrap: "truncate", color: theme.dim, children: [
4179
+ `solongate v${ver}`,
4180
+ 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
4181
+ ] }, "ver")
4182
+ );
4183
+ lineKey.push("");
4057
4184
  const budget = Math.max(4, rows - 2);
4058
4185
  const selLine = Math.max(0, lineKey.indexOf(keyOf(cur)));
4059
4186
  const maxStart = Math.max(0, lineEls.length - budget);
@@ -4071,109 +4198,6 @@ function SettingsPanel({
4071
4198
  ] }) });
4072
4199
  }
4073
4200
 
4074
- // src/self-update.ts
4075
- import { execFile, spawn as spawn4 } from "child_process";
4076
- import { mkdirSync as mkdirSync6, openSync as openSync3, readFileSync as readFileSync6, writeFileSync as writeFileSync7 } from "fs";
4077
- import { homedir as homedir8 } from "os";
4078
- import { dirname as dirname3, join as join8 } from "path";
4079
- import { fileURLToPath as fileURLToPath3 } from "url";
4080
- var PKG = "@solongate/proxy";
4081
- var CHECK_EVERY_MS = 30 * 60 * 1e3;
4082
- var ATTEMPT_EVERY_MS = 6 * 60 * 60 * 1e3;
4083
- var STATE_FILE2 = join8(homedir8(), ".solongate", ".self-update.json");
4084
- var LOG_FILE2 = join8(homedir8(), ".solongate", "self-update.log");
4085
- function readState2() {
4086
- try {
4087
- const s = JSON.parse(readFileSync6(STATE_FILE2, "utf-8"));
4088
- return s && typeof s === "object" ? s : {};
4089
- } catch {
4090
- return {};
4091
- }
4092
- }
4093
- function writeState2(s) {
4094
- try {
4095
- mkdirSync6(join8(homedir8(), ".solongate"), { recursive: true });
4096
- writeFileSync7(STATE_FILE2, JSON.stringify(s));
4097
- } catch {
4098
- }
4099
- }
4100
- function currentVersion() {
4101
- try {
4102
- const pkg = JSON.parse(readFileSync6(join8(dirname3(fileURLToPath3(import.meta.url)), "..", "package.json"), "utf-8"));
4103
- return pkg.version ?? "0.0.0";
4104
- } catch {
4105
- return "0.0.0";
4106
- }
4107
- }
4108
- function newerThan(b, a) {
4109
- const pa = a.split(".").map((n) => parseInt(n, 10) || 0);
4110
- const pb = b.split(".").map((n) => parseInt(n, 10) || 0);
4111
- for (let i = 0; i < 3; i++) {
4112
- if ((pb[i] ?? 0) > (pa[i] ?? 0)) return true;
4113
- if ((pb[i] ?? 0) < (pa[i] ?? 0)) return false;
4114
- }
4115
- return false;
4116
- }
4117
- async function fetchLatest() {
4118
- try {
4119
- const res = await fetch(`https://registry.npmjs.org/${PKG}`, {
4120
- headers: { accept: "application/vnd.npm.install-v1+json" },
4121
- signal: AbortSignal.timeout(3e3)
4122
- });
4123
- if (!res.ok) return null;
4124
- const j = await res.json();
4125
- const latest = j["dist-tags"]?.latest;
4126
- if (typeof latest !== "string") return null;
4127
- if (!j.versions || !(latest in j.versions)) return null;
4128
- return latest;
4129
- } catch {
4130
- return null;
4131
- }
4132
- }
4133
- function runGlobalInstall(version) {
4134
- return new Promise((resolve3) => {
4135
- try {
4136
- mkdirSync6(join8(homedir8(), ".solongate"), { recursive: true });
4137
- execFile(
4138
- "npm",
4139
- ["install", "-g", `${PKG}@${version}`],
4140
- { timeout: 3e5, windowsHide: true, shell: process.platform === "win32" },
4141
- (err, stdout, stderr) => {
4142
- try {
4143
- writeFileSync7(LOG_FILE2, `${(/* @__PURE__ */ new Date()).toISOString()} install ${version}: ${err ? "FAILED" : "ok"}
4144
- ${stdout}
4145
- ${stderr}
4146
- `, { flag: "a" });
4147
- } catch {
4148
- }
4149
- resolve3(!err);
4150
- }
4151
- );
4152
- } catch {
4153
- resolve3(false);
4154
- }
4155
- });
4156
- }
4157
- async function tuiUpdateFlow(onStatus) {
4158
- try {
4159
- const current = currentVersion();
4160
- const latest = await fetchLatest();
4161
- const state = readState2();
4162
- if (latest) writeState2({ ...state, lastCheckAt: Date.now(), latestSeen: latest });
4163
- if (!latest || !newerThan(latest, current)) return;
4164
- if (readState2().installed === latest) {
4165
- onStatus({ kind: "updated", version: latest });
4166
- return;
4167
- }
4168
- onStatus({ kind: "updating", version: latest });
4169
- if (await runGlobalInstall(latest)) {
4170
- writeState2({ ...readState2(), installed: latest });
4171
- onStatus({ kind: "updated", version: latest });
4172
- }
4173
- } catch {
4174
- }
4175
- }
4176
-
4177
4201
  // src/tui/App.tsx
4178
4202
  import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
4179
4203
  function LiveHint() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@solongate/proxy",
3
- "version": "0.81.91",
3
+ "version": "0.81.93",
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": {