@solongate/proxy 0.81.50 → 0.81.51
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 +272 -147
- package/dist/logs-server-daemon.d.ts +19 -0
- package/dist/logs-server.js +121 -9
- package/dist/tui/index.js +120 -25
- package/package.json +1 -1
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export declare const LOGS_SERVER_PORT = 8788;
|
|
2
|
+
export interface LogsServerStatus {
|
|
3
|
+
desired: 'on' | 'off';
|
|
4
|
+
running: boolean;
|
|
5
|
+
pid?: number;
|
|
6
|
+
port: number;
|
|
7
|
+
}
|
|
8
|
+
export declare function logsServerStatus(): LogsServerStatus;
|
|
9
|
+
/** Called from runLogsServer when a (foreground or daemon) server starts. */
|
|
10
|
+
export declare function recordLogsServerStarted(port: number): void;
|
|
11
|
+
/** Spawn the detached daemon (idempotent — no-op when already running). */
|
|
12
|
+
export declare function startLogsServerDaemon(): LogsServerStatus;
|
|
13
|
+
/** Explicit disable — the ONLY thing that flips desired to 'off'. */
|
|
14
|
+
export declare function stopLogsServerDaemon(): LogsServerStatus;
|
|
15
|
+
/**
|
|
16
|
+
* Resurrect the daemon when it SHOULD be running but isn't (machine reboot,
|
|
17
|
+
* Ctrl+C on a foreground run, crash). Called from every human CLI startup.
|
|
18
|
+
*/
|
|
19
|
+
export declare function ensureLogsServerDaemon(): void;
|
package/dist/logs-server.js
CHANGED
|
@@ -1,8 +1,118 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
3
|
+
var __esm = (fn, res) => function __init() {
|
|
4
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
5
|
+
};
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
// src/logs-server-daemon.ts
|
|
12
|
+
var logs_server_daemon_exports = {};
|
|
13
|
+
__export(logs_server_daemon_exports, {
|
|
14
|
+
LOGS_SERVER_PORT: () => LOGS_SERVER_PORT,
|
|
15
|
+
ensureLogsServerDaemon: () => ensureLogsServerDaemon,
|
|
16
|
+
logsServerStatus: () => logsServerStatus,
|
|
17
|
+
recordLogsServerStarted: () => recordLogsServerStarted,
|
|
18
|
+
startLogsServerDaemon: () => startLogsServerDaemon,
|
|
19
|
+
stopLogsServerDaemon: () => stopLogsServerDaemon
|
|
20
|
+
});
|
|
21
|
+
import { spawn } from "child_process";
|
|
22
|
+
import { mkdirSync, openSync, readFileSync, writeFileSync } from "fs";
|
|
23
|
+
import { homedir } from "os";
|
|
24
|
+
import { dirname, join } from "path";
|
|
25
|
+
import { fileURLToPath } from "url";
|
|
26
|
+
function readState() {
|
|
27
|
+
try {
|
|
28
|
+
const s = JSON.parse(readFileSync(STATE_FILE, "utf-8"));
|
|
29
|
+
return s && typeof s === "object" ? s : {};
|
|
30
|
+
} catch {
|
|
31
|
+
return {};
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
function writeState(s) {
|
|
35
|
+
try {
|
|
36
|
+
mkdirSync(DIR, { recursive: true });
|
|
37
|
+
writeFileSync(STATE_FILE, JSON.stringify(s));
|
|
38
|
+
} catch {
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
function pidAlive(pid) {
|
|
42
|
+
if (!pid || pid <= 0) return false;
|
|
43
|
+
try {
|
|
44
|
+
process.kill(pid, 0);
|
|
45
|
+
return true;
|
|
46
|
+
} catch (e) {
|
|
47
|
+
return e.code === "EPERM";
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
function logsServerStatus() {
|
|
51
|
+
const s = readState();
|
|
52
|
+
const running = pidAlive(s.pid);
|
|
53
|
+
return { desired: s.desired === "on" ? "on" : "off", running, pid: running ? s.pid : void 0, port: s.port || LOGS_SERVER_PORT };
|
|
54
|
+
}
|
|
55
|
+
function recordLogsServerStarted(port) {
|
|
56
|
+
writeState({ desired: "on", pid: process.pid, port, startedAt: Date.now() });
|
|
57
|
+
}
|
|
58
|
+
function startLogsServerDaemon() {
|
|
59
|
+
const cur = logsServerStatus();
|
|
60
|
+
if (cur.running) {
|
|
61
|
+
writeState({ ...readState(), desired: "on" });
|
|
62
|
+
return { ...cur, desired: "on" };
|
|
63
|
+
}
|
|
64
|
+
try {
|
|
65
|
+
mkdirSync(DIR, { recursive: true });
|
|
66
|
+
const log = openSync(LOG_FILE, "a");
|
|
67
|
+
const cli = join(dirname(fileURLToPath(import.meta.url)), "index.js");
|
|
68
|
+
const p = spawn(process.execPath, [cli, "logs-server"], {
|
|
69
|
+
detached: true,
|
|
70
|
+
stdio: ["ignore", log, log],
|
|
71
|
+
windowsHide: true
|
|
72
|
+
});
|
|
73
|
+
p.on("error", () => {
|
|
74
|
+
});
|
|
75
|
+
p.unref();
|
|
76
|
+
writeState({ desired: "on", pid: p.pid, port: LOGS_SERVER_PORT, startedAt: Date.now() });
|
|
77
|
+
return { desired: "on", running: true, pid: p.pid, port: LOGS_SERVER_PORT };
|
|
78
|
+
} catch {
|
|
79
|
+
return { ...cur, desired: "on", running: false };
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
function stopLogsServerDaemon() {
|
|
83
|
+
const s = readState();
|
|
84
|
+
if (pidAlive(s.pid)) {
|
|
85
|
+
try {
|
|
86
|
+
process.kill(s.pid);
|
|
87
|
+
} catch {
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
writeState({ desired: "off", port: s.port });
|
|
91
|
+
return { desired: "off", running: false, port: s.port || LOGS_SERVER_PORT };
|
|
92
|
+
}
|
|
93
|
+
function ensureLogsServerDaemon() {
|
|
94
|
+
try {
|
|
95
|
+
const s = logsServerStatus();
|
|
96
|
+
if (s.desired === "on" && !s.running) startLogsServerDaemon();
|
|
97
|
+
} catch {
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
var DIR, STATE_FILE, LOG_FILE, LOGS_SERVER_PORT;
|
|
101
|
+
var init_logs_server_daemon = __esm({
|
|
102
|
+
"src/logs-server-daemon.ts"() {
|
|
103
|
+
"use strict";
|
|
104
|
+
DIR = join(homedir(), ".solongate");
|
|
105
|
+
STATE_FILE = join(DIR, ".logs-server.json");
|
|
106
|
+
LOG_FILE = join(DIR, "logs-server.log");
|
|
107
|
+
LOGS_SERVER_PORT = 8788;
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
|
|
1
111
|
// src/logs-server.ts
|
|
2
112
|
import { createServer } from "http";
|
|
3
|
-
import { readFileSync, statSync } from "fs";
|
|
4
|
-
import { resolve, join, isAbsolute } from "path";
|
|
5
|
-
import { homedir } from "os";
|
|
113
|
+
import { readFileSync as readFileSync2, statSync } from "fs";
|
|
114
|
+
import { resolve, join as join2, isAbsolute } from "path";
|
|
115
|
+
import { homedir as homedir2 } from "os";
|
|
6
116
|
import { readdirSync } from "fs";
|
|
7
117
|
var LOG_FILENAME = "solongate-audit.jsonl";
|
|
8
118
|
var DEFAULT_PORT = 8788;
|
|
@@ -21,15 +131,15 @@ function resolveLocalLogDir(rawPath) {
|
|
|
21
131
|
const dir = String(rawPath || "").trim().replace(/[\\/]+$/, "");
|
|
22
132
|
if (!dir) return null;
|
|
23
133
|
if (isAbsolute(dir)) return dir;
|
|
24
|
-
return resolve(
|
|
134
|
+
return resolve(homedir2(), ".solongate", "local-logs");
|
|
25
135
|
}
|
|
26
136
|
async function findLogDir() {
|
|
27
|
-
const base = resolve(
|
|
137
|
+
const base = resolve(homedir2(), ".solongate");
|
|
28
138
|
try {
|
|
29
139
|
const files = readdirSync(base).filter((f) => f.startsWith(".policy-cache-") && f.endsWith(".json"));
|
|
30
140
|
for (const f of files) {
|
|
31
141
|
try {
|
|
32
|
-
const c = JSON.parse(
|
|
142
|
+
const c = JSON.parse(readFileSync2(join2(base, f), "utf-8"));
|
|
33
143
|
const p = c?.security?.localLogs?.path;
|
|
34
144
|
if (typeof p === "string" && p.trim()) return { dir: resolveLocalLogDir(p), configured: p };
|
|
35
145
|
} catch {
|
|
@@ -38,7 +148,7 @@ async function findLogDir() {
|
|
|
38
148
|
} catch {
|
|
39
149
|
}
|
|
40
150
|
try {
|
|
41
|
-
const cfgRaw =
|
|
151
|
+
const cfgRaw = readFileSync2(join2(base, "cloud-guard.json"), "utf-8");
|
|
42
152
|
const { apiKey, apiUrl } = JSON.parse(cfgRaw);
|
|
43
153
|
if (apiKey) {
|
|
44
154
|
const url = `${apiUrl || "https://api.solongate.com"}/api/v1/policies/active`;
|
|
@@ -67,7 +177,7 @@ function setCors(req, res) {
|
|
|
67
177
|
}
|
|
68
178
|
function fileInfo(dir) {
|
|
69
179
|
if (!dir) return { file: null, exists: false, size: 0, mtimeMs: 0 };
|
|
70
|
-
const file =
|
|
180
|
+
const file = join2(dir, LOG_FILENAME);
|
|
71
181
|
try {
|
|
72
182
|
const st = statSync(file);
|
|
73
183
|
return { file, exists: true, size: st.size, mtimeMs: st.mtimeMs };
|
|
@@ -128,7 +238,7 @@ async function runLogsServer() {
|
|
|
128
238
|
return;
|
|
129
239
|
}
|
|
130
240
|
try {
|
|
131
|
-
const text =
|
|
241
|
+
const text = readFileSync2(info.file, "utf-8");
|
|
132
242
|
res.writeHead(200, { "Content-Type": "text/plain; charset=utf-8", "Last-Modified": lastMod, "X-Solongate-Exists": "1" });
|
|
133
243
|
res.end(text);
|
|
134
244
|
} catch {
|
|
@@ -141,6 +251,8 @@ async function runLogsServer() {
|
|
|
141
251
|
res.end("not found");
|
|
142
252
|
});
|
|
143
253
|
server.listen(port, "127.0.0.1", async () => {
|
|
254
|
+
const { recordLogsServerStarted: recordLogsServerStarted2 } = await Promise.resolve().then(() => (init_logs_server_daemon(), logs_server_daemon_exports));
|
|
255
|
+
recordLogsServerStarted2(port);
|
|
144
256
|
const { dir, configured } = await findLogDir();
|
|
145
257
|
process.stdout.write(`[SolonGate] Local logs agent listening on http://127.0.0.1:${port}
|
|
146
258
|
`);
|
package/dist/tui/index.js
CHANGED
|
@@ -5,9 +5,9 @@ var __export = (target, all) => {
|
|
|
5
5
|
};
|
|
6
6
|
|
|
7
7
|
// src/tui/index.tsx
|
|
8
|
-
import { appendFileSync, mkdirSync as
|
|
9
|
-
import { homedir as
|
|
10
|
-
import { join as
|
|
8
|
+
import { appendFileSync, mkdirSync as mkdirSync6 } from "fs";
|
|
9
|
+
import { homedir as homedir8 } from "os";
|
|
10
|
+
import { join as join8 } from "path";
|
|
11
11
|
import { render } from "ink";
|
|
12
12
|
|
|
13
13
|
// src/tui/App.tsx
|
|
@@ -3091,6 +3091,83 @@ function Detail({ label, value, color }) {
|
|
|
3091
3091
|
import { Box as Box7, Text as Text7, useInput as useInput6 } from "ink";
|
|
3092
3092
|
import TextInput5 from "ink-text-input";
|
|
3093
3093
|
import { useEffect as useEffect6, useRef as useRef3, useState as useState7 } from "react";
|
|
3094
|
+
|
|
3095
|
+
// src/logs-server-daemon.ts
|
|
3096
|
+
import { spawn as spawn3 } from "child_process";
|
|
3097
|
+
import { mkdirSync as mkdirSync4, openSync as openSync2, readFileSync as readFileSync4, writeFileSync as writeFileSync5 } from "fs";
|
|
3098
|
+
import { homedir as homedir6 } from "os";
|
|
3099
|
+
import { dirname, join as join6 } from "path";
|
|
3100
|
+
import { fileURLToPath } from "url";
|
|
3101
|
+
var DIR = join6(homedir6(), ".solongate");
|
|
3102
|
+
var STATE_FILE = join6(DIR, ".logs-server.json");
|
|
3103
|
+
var LOG_FILE = join6(DIR, "logs-server.log");
|
|
3104
|
+
var LOGS_SERVER_PORT = 8788;
|
|
3105
|
+
function readState() {
|
|
3106
|
+
try {
|
|
3107
|
+
const s = JSON.parse(readFileSync4(STATE_FILE, "utf-8"));
|
|
3108
|
+
return s && typeof s === "object" ? s : {};
|
|
3109
|
+
} catch {
|
|
3110
|
+
return {};
|
|
3111
|
+
}
|
|
3112
|
+
}
|
|
3113
|
+
function writeState(s) {
|
|
3114
|
+
try {
|
|
3115
|
+
mkdirSync4(DIR, { recursive: true });
|
|
3116
|
+
writeFileSync5(STATE_FILE, JSON.stringify(s));
|
|
3117
|
+
} catch {
|
|
3118
|
+
}
|
|
3119
|
+
}
|
|
3120
|
+
function pidAlive(pid) {
|
|
3121
|
+
if (!pid || pid <= 0) return false;
|
|
3122
|
+
try {
|
|
3123
|
+
process.kill(pid, 0);
|
|
3124
|
+
return true;
|
|
3125
|
+
} catch (e) {
|
|
3126
|
+
return e.code === "EPERM";
|
|
3127
|
+
}
|
|
3128
|
+
}
|
|
3129
|
+
function logsServerStatus() {
|
|
3130
|
+
const s = readState();
|
|
3131
|
+
const running = pidAlive(s.pid);
|
|
3132
|
+
return { desired: s.desired === "on" ? "on" : "off", running, pid: running ? s.pid : void 0, port: s.port || LOGS_SERVER_PORT };
|
|
3133
|
+
}
|
|
3134
|
+
function startLogsServerDaemon() {
|
|
3135
|
+
const cur = logsServerStatus();
|
|
3136
|
+
if (cur.running) {
|
|
3137
|
+
writeState({ ...readState(), desired: "on" });
|
|
3138
|
+
return { ...cur, desired: "on" };
|
|
3139
|
+
}
|
|
3140
|
+
try {
|
|
3141
|
+
mkdirSync4(DIR, { recursive: true });
|
|
3142
|
+
const log = openSync2(LOG_FILE, "a");
|
|
3143
|
+
const cli = join6(dirname(fileURLToPath(import.meta.url)), "index.js");
|
|
3144
|
+
const p = spawn3(process.execPath, [cli, "logs-server"], {
|
|
3145
|
+
detached: true,
|
|
3146
|
+
stdio: ["ignore", log, log],
|
|
3147
|
+
windowsHide: true
|
|
3148
|
+
});
|
|
3149
|
+
p.on("error", () => {
|
|
3150
|
+
});
|
|
3151
|
+
p.unref();
|
|
3152
|
+
writeState({ desired: "on", pid: p.pid, port: LOGS_SERVER_PORT, startedAt: Date.now() });
|
|
3153
|
+
return { desired: "on", running: true, pid: p.pid, port: LOGS_SERVER_PORT };
|
|
3154
|
+
} catch {
|
|
3155
|
+
return { ...cur, desired: "on", running: false };
|
|
3156
|
+
}
|
|
3157
|
+
}
|
|
3158
|
+
function stopLogsServerDaemon() {
|
|
3159
|
+
const s = readState();
|
|
3160
|
+
if (pidAlive(s.pid)) {
|
|
3161
|
+
try {
|
|
3162
|
+
process.kill(s.pid);
|
|
3163
|
+
} catch {
|
|
3164
|
+
}
|
|
3165
|
+
}
|
|
3166
|
+
writeState({ desired: "off", port: s.port });
|
|
3167
|
+
return { desired: "off", running: false, port: s.port || LOGS_SERVER_PORT };
|
|
3168
|
+
}
|
|
3169
|
+
|
|
3170
|
+
// src/tui/panels/Settings.tsx
|
|
3094
3171
|
import { Fragment as Fragment5, jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
3095
3172
|
var EVENTS = ["denials", "allowed", "all"];
|
|
3096
3173
|
var SPIN2 = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
@@ -3122,6 +3199,11 @@ function SettingsPanel({
|
|
|
3122
3199
|
const abort = useRef3(false);
|
|
3123
3200
|
const refreshAccounts = () => setAccounts(listAccounts());
|
|
3124
3201
|
const locked = accounts.length === 0;
|
|
3202
|
+
const [srv, setSrv] = useState7(() => logsServerStatus());
|
|
3203
|
+
useEffect6(() => {
|
|
3204
|
+
const t = setInterval(() => setSrv(logsServerStatus()), 3e3);
|
|
3205
|
+
return () => clearInterval(t);
|
|
3206
|
+
}, []);
|
|
3125
3207
|
useEffect6(() => {
|
|
3126
3208
|
if (!login || login.phase === "done" || login.phase === "error") return;
|
|
3127
3209
|
const t = setInterval(() => setTick((n) => n + 1), 120);
|
|
@@ -3139,6 +3221,7 @@ function SettingsPanel({
|
|
|
3139
3221
|
...locked ? [] : [
|
|
3140
3222
|
{ kind: "ll-enabled" },
|
|
3141
3223
|
{ kind: "ll-path" },
|
|
3224
|
+
{ kind: "ll-server" },
|
|
3142
3225
|
...webhooks.map((wh) => ({ kind: "wh", wh })),
|
|
3143
3226
|
{ kind: "wh-add" },
|
|
3144
3227
|
...alerts.map((rule) => ({ kind: "alert", rule })),
|
|
@@ -3214,6 +3297,12 @@ function SettingsPanel({
|
|
|
3214
3297
|
} else if (r.kind === "ll-path") {
|
|
3215
3298
|
setInput(local?.path ?? "");
|
|
3216
3299
|
setEditing("path");
|
|
3300
|
+
} else if (r.kind === "ll-server") {
|
|
3301
|
+
const next = srv.running ? stopLogsServerDaemon() : startLogsServerDaemon();
|
|
3302
|
+
setSrv(next);
|
|
3303
|
+
setMsg(
|
|
3304
|
+
next.running ? { text: `\u2713 dashboard link running on 127.0.0.1:${next.port} \u2014 keeps running after you close the dataroom`, level: "ok" } : { text: "\u2713 dashboard link stopped (disabled until you start it again)", level: "ok" }
|
|
3305
|
+
);
|
|
3217
3306
|
} else if (r.kind === "wh") {
|
|
3218
3307
|
run(r.wh.enabled ? "webhook disabled" : "webhook enabled", () => api.settings.updateWebhook(r.wh.id, { enabled: !r.wh.enabled }), whQ.reload);
|
|
3219
3308
|
} else if (r.kind === "wh-add") {
|
|
@@ -3357,7 +3446,7 @@ function SettingsPanel({
|
|
|
3357
3446
|
] }) : null
|
|
3358
3447
|
] }),
|
|
3359
3448
|
locked ? null : /* @__PURE__ */ jsxs7(Fragment5, { children: [
|
|
3360
|
-
inWindow({ kind: "ll-enabled" }) || inWindow({ kind: "ll-path" }) ? /* @__PURE__ */ jsxs7(Box7, { marginTop: 1, flexDirection: "column", children: [
|
|
3449
|
+
inWindow({ kind: "ll-enabled" }) || inWindow({ kind: "ll-path" }) || inWindow({ kind: "ll-server" }) ? /* @__PURE__ */ jsxs7(Box7, { marginTop: 1, flexDirection: "column", children: [
|
|
3361
3450
|
/* @__PURE__ */ jsxs7(Text7, { bold: true, color: theme.accentBright, children: [
|
|
3362
3451
|
"LOCAL LOGS ",
|
|
3363
3452
|
/* @__PURE__ */ jsx7(Text7, { color: theme.dim, children: "\u2014 hooks mirror every decision to a file on the agent machine" })
|
|
@@ -3372,6 +3461,12 @@ function SettingsPanel({
|
|
|
3372
3461
|
/* @__PURE__ */ jsx7(Text7, { color: keyOf(cur) === "ll-path" && focused ? theme.accentBright : theme.dim, children: mark({ kind: "ll-path" }) }),
|
|
3373
3462
|
/* @__PURE__ */ jsx7(Text7, { color: theme.dim, children: "path ".padEnd(10) }),
|
|
3374
3463
|
local?.path ? /* @__PURE__ */ jsx7(Text7, { color: theme.accent, children: truncate(local.path, cols - 14) }) : /* @__PURE__ */ jsx7(Text7, { color: theme.dim, children: "not set \u2014 enter to edit" })
|
|
3464
|
+
] }),
|
|
3465
|
+
/* @__PURE__ */ jsxs7(Text7, { wrap: "truncate", children: [
|
|
3466
|
+
/* @__PURE__ */ jsx7(Text7, { color: keyOf(cur) === "ll-server" && focused ? theme.accentBright : theme.dim, children: mark({ kind: "ll-server" }) }),
|
|
3467
|
+
/* @__PURE__ */ jsx7(Text7, { color: theme.dim, children: "dashboard".padEnd(10) }),
|
|
3468
|
+
srv.running ? /* @__PURE__ */ jsx7(Text7, { color: theme.ok, children: `running 127.0.0.1:${srv.port}` }) : /* @__PURE__ */ jsx7(Text7, { color: theme.dim, children: "stopped" }),
|
|
3469
|
+
/* @__PURE__ */ jsx7(Text7, { color: theme.dim, children: srv.running ? " serves local logs to the dashboard \xB7 survives closing the dataroom \xB7 enter stops" : " enter starts the local-logs link for the dashboard" })
|
|
3375
3470
|
] })
|
|
3376
3471
|
] }) : null,
|
|
3377
3472
|
/* @__PURE__ */ jsxs7(Box7, { marginTop: 1, flexDirection: "column", children: [
|
|
@@ -3420,34 +3515,34 @@ function SettingsPanel({
|
|
|
3420
3515
|
}
|
|
3421
3516
|
|
|
3422
3517
|
// src/self-update.ts
|
|
3423
|
-
import { execFile, spawn as
|
|
3424
|
-
import { mkdirSync as
|
|
3425
|
-
import { homedir as
|
|
3426
|
-
import { dirname, join as
|
|
3427
|
-
import { fileURLToPath } from "url";
|
|
3518
|
+
import { execFile, spawn as spawn4 } from "child_process";
|
|
3519
|
+
import { mkdirSync as mkdirSync5, openSync as openSync3, readFileSync as readFileSync5, realpathSync, writeFileSync as writeFileSync6 } from "fs";
|
|
3520
|
+
import { homedir as homedir7 } from "os";
|
|
3521
|
+
import { dirname as dirname2, join as join7 } from "path";
|
|
3522
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
3428
3523
|
var PKG = "@solongate/proxy";
|
|
3429
3524
|
var CHECK_EVERY_MS = 30 * 60 * 1e3;
|
|
3430
3525
|
var ATTEMPT_EVERY_MS = 6 * 60 * 60 * 1e3;
|
|
3431
|
-
var
|
|
3432
|
-
var
|
|
3433
|
-
function
|
|
3526
|
+
var STATE_FILE2 = join7(homedir7(), ".solongate", ".self-update.json");
|
|
3527
|
+
var LOG_FILE2 = join7(homedir7(), ".solongate", "self-update.log");
|
|
3528
|
+
function readState2() {
|
|
3434
3529
|
try {
|
|
3435
|
-
const s = JSON.parse(
|
|
3530
|
+
const s = JSON.parse(readFileSync5(STATE_FILE2, "utf-8"));
|
|
3436
3531
|
return s && typeof s === "object" ? s : {};
|
|
3437
3532
|
} catch {
|
|
3438
3533
|
return {};
|
|
3439
3534
|
}
|
|
3440
3535
|
}
|
|
3441
|
-
function
|
|
3536
|
+
function writeState2(s) {
|
|
3442
3537
|
try {
|
|
3443
|
-
|
|
3444
|
-
|
|
3538
|
+
mkdirSync5(join7(homedir7(), ".solongate"), { recursive: true });
|
|
3539
|
+
writeFileSync6(STATE_FILE2, JSON.stringify(s));
|
|
3445
3540
|
} catch {
|
|
3446
3541
|
}
|
|
3447
3542
|
}
|
|
3448
3543
|
function currentVersion() {
|
|
3449
3544
|
try {
|
|
3450
|
-
const pkg = JSON.parse(
|
|
3545
|
+
const pkg = JSON.parse(readFileSync5(join7(dirname2(fileURLToPath2(import.meta.url)), "..", "package.json"), "utf-8"));
|
|
3451
3546
|
return pkg.version ?? "0.0.0";
|
|
3452
3547
|
} catch {
|
|
3453
3548
|
return "0.0.0";
|
|
@@ -3497,14 +3592,14 @@ async function isGlobalInstall() {
|
|
|
3497
3592
|
function runGlobalInstall(version) {
|
|
3498
3593
|
return new Promise((resolve2) => {
|
|
3499
3594
|
try {
|
|
3500
|
-
|
|
3595
|
+
mkdirSync5(join7(homedir7(), ".solongate"), { recursive: true });
|
|
3501
3596
|
execFile(
|
|
3502
3597
|
"npm",
|
|
3503
3598
|
["install", "-g", `${PKG}@${version}`],
|
|
3504
3599
|
{ timeout: 3e5, windowsHide: true, shell: process.platform === "win32" },
|
|
3505
3600
|
(err, stdout, stderr) => {
|
|
3506
3601
|
try {
|
|
3507
|
-
|
|
3602
|
+
writeFileSync6(LOG_FILE2, `${(/* @__PURE__ */ new Date()).toISOString()} install ${version}: ${err ? "FAILED" : "ok"}
|
|
3508
3603
|
${stdout}
|
|
3509
3604
|
${stderr}
|
|
3510
3605
|
`, { flag: "a" });
|
|
@@ -3522,13 +3617,13 @@ async function tuiUpdateFlow(onStatus) {
|
|
|
3522
3617
|
try {
|
|
3523
3618
|
const current = currentVersion();
|
|
3524
3619
|
const latest = await fetchLatest();
|
|
3525
|
-
const state =
|
|
3526
|
-
if (latest)
|
|
3620
|
+
const state = readState2();
|
|
3621
|
+
if (latest) writeState2({ ...state, lastCheckAt: Date.now(), latestSeen: latest });
|
|
3527
3622
|
if (!latest || !newerThan(latest, current)) return;
|
|
3528
|
-
const attempts =
|
|
3623
|
+
const attempts = readState2().attempts ?? {};
|
|
3529
3624
|
const canRetry = Date.now() - (attempts[latest] ?? 0) >= ATTEMPT_EVERY_MS;
|
|
3530
3625
|
if (await isGlobalInstall() && canRetry) {
|
|
3531
|
-
|
|
3626
|
+
writeState2({ ...readState2(), attempts: { [latest]: Date.now() } });
|
|
3532
3627
|
onStatus({ kind: "updating", version: latest });
|
|
3533
3628
|
if (await runGlobalInstall(latest)) {
|
|
3534
3629
|
onStatus({ kind: "updated", version: latest });
|
|
@@ -3713,11 +3808,11 @@ async function launchTui() {
|
|
|
3713
3808
|
return;
|
|
3714
3809
|
}
|
|
3715
3810
|
process.stdout.write("\x1B[?1049h\x1B[H");
|
|
3716
|
-
const debugLog =
|
|
3811
|
+
const debugLog = join8(homedir8(), ".solongate", "dataroom-debug.log");
|
|
3717
3812
|
const saved = { log: console.log, warn: console.warn, error: console.error, info: console.info, debug: console.debug };
|
|
3718
3813
|
const toFile = (level) => (...args) => {
|
|
3719
3814
|
try {
|
|
3720
|
-
|
|
3815
|
+
mkdirSync6(join8(homedir8(), ".solongate"), { recursive: true });
|
|
3721
3816
|
appendFileSync(debugLog, `${(/* @__PURE__ */ new Date()).toISOString()} [${level}] ${args.map((a) => typeof a === "string" ? a : JSON.stringify(a)).join(" ")}
|
|
3722
3817
|
`);
|
|
3723
3818
|
} catch {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@solongate/proxy",
|
|
3
|
-
"version": "0.81.
|
|
3
|
+
"version": "0.81.51",
|
|
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": {
|