@solongate/proxy 0.81.49 → 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 +521 -409
- package/dist/logs-server-daemon.d.ts +19 -0
- package/dist/logs-server.js +121 -9
- package/dist/tui/index.js +366 -276
- 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
|
@@ -6736,15 +6736,115 @@ var init_self_update = __esm({
|
|
|
6736
6736
|
}
|
|
6737
6737
|
});
|
|
6738
6738
|
|
|
6739
|
-
// src/
|
|
6740
|
-
|
|
6739
|
+
// src/logs-server-daemon.ts
|
|
6740
|
+
var logs_server_daemon_exports = {};
|
|
6741
|
+
__export(logs_server_daemon_exports, {
|
|
6742
|
+
LOGS_SERVER_PORT: () => LOGS_SERVER_PORT,
|
|
6743
|
+
ensureLogsServerDaemon: () => ensureLogsServerDaemon,
|
|
6744
|
+
logsServerStatus: () => logsServerStatus,
|
|
6745
|
+
recordLogsServerStarted: () => recordLogsServerStarted,
|
|
6746
|
+
startLogsServerDaemon: () => startLogsServerDaemon,
|
|
6747
|
+
stopLogsServerDaemon: () => stopLogsServerDaemon
|
|
6748
|
+
});
|
|
6749
|
+
import { spawn as spawn2 } from "child_process";
|
|
6750
|
+
import { mkdirSync as mkdirSync4, openSync as openSync2, readFileSync as readFileSync5, writeFileSync as writeFileSync4 } from "fs";
|
|
6741
6751
|
import { homedir as homedir3 } from "os";
|
|
6742
|
-
import { join as join5 } from "path";
|
|
6752
|
+
import { dirname as dirname2, join as join5 } from "path";
|
|
6753
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
6754
|
+
function readState2() {
|
|
6755
|
+
try {
|
|
6756
|
+
const s = JSON.parse(readFileSync5(STATE_FILE2, "utf-8"));
|
|
6757
|
+
return s && typeof s === "object" ? s : {};
|
|
6758
|
+
} catch {
|
|
6759
|
+
return {};
|
|
6760
|
+
}
|
|
6761
|
+
}
|
|
6762
|
+
function writeState2(s) {
|
|
6763
|
+
try {
|
|
6764
|
+
mkdirSync4(DIR, { recursive: true });
|
|
6765
|
+
writeFileSync4(STATE_FILE2, JSON.stringify(s));
|
|
6766
|
+
} catch {
|
|
6767
|
+
}
|
|
6768
|
+
}
|
|
6769
|
+
function pidAlive(pid) {
|
|
6770
|
+
if (!pid || pid <= 0) return false;
|
|
6771
|
+
try {
|
|
6772
|
+
process.kill(pid, 0);
|
|
6773
|
+
return true;
|
|
6774
|
+
} catch (e) {
|
|
6775
|
+
return e.code === "EPERM";
|
|
6776
|
+
}
|
|
6777
|
+
}
|
|
6778
|
+
function logsServerStatus() {
|
|
6779
|
+
const s = readState2();
|
|
6780
|
+
const running = pidAlive(s.pid);
|
|
6781
|
+
return { desired: s.desired === "on" ? "on" : "off", running, pid: running ? s.pid : void 0, port: s.port || LOGS_SERVER_PORT };
|
|
6782
|
+
}
|
|
6783
|
+
function recordLogsServerStarted(port) {
|
|
6784
|
+
writeState2({ desired: "on", pid: process.pid, port, startedAt: Date.now() });
|
|
6785
|
+
}
|
|
6786
|
+
function startLogsServerDaemon() {
|
|
6787
|
+
const cur = logsServerStatus();
|
|
6788
|
+
if (cur.running) {
|
|
6789
|
+
writeState2({ ...readState2(), desired: "on" });
|
|
6790
|
+
return { ...cur, desired: "on" };
|
|
6791
|
+
}
|
|
6792
|
+
try {
|
|
6793
|
+
mkdirSync4(DIR, { recursive: true });
|
|
6794
|
+
const log6 = openSync2(LOG_FILE2, "a");
|
|
6795
|
+
const cli = join5(dirname2(fileURLToPath2(import.meta.url)), "index.js");
|
|
6796
|
+
const p = spawn2(process.execPath, [cli, "logs-server"], {
|
|
6797
|
+
detached: true,
|
|
6798
|
+
stdio: ["ignore", log6, log6],
|
|
6799
|
+
windowsHide: true
|
|
6800
|
+
});
|
|
6801
|
+
p.on("error", () => {
|
|
6802
|
+
});
|
|
6803
|
+
p.unref();
|
|
6804
|
+
writeState2({ desired: "on", pid: p.pid, port: LOGS_SERVER_PORT, startedAt: Date.now() });
|
|
6805
|
+
return { desired: "on", running: true, pid: p.pid, port: LOGS_SERVER_PORT };
|
|
6806
|
+
} catch {
|
|
6807
|
+
return { ...cur, desired: "on", running: false };
|
|
6808
|
+
}
|
|
6809
|
+
}
|
|
6810
|
+
function stopLogsServerDaemon() {
|
|
6811
|
+
const s = readState2();
|
|
6812
|
+
if (pidAlive(s.pid)) {
|
|
6813
|
+
try {
|
|
6814
|
+
process.kill(s.pid);
|
|
6815
|
+
} catch {
|
|
6816
|
+
}
|
|
6817
|
+
}
|
|
6818
|
+
writeState2({ desired: "off", port: s.port });
|
|
6819
|
+
return { desired: "off", running: false, port: s.port || LOGS_SERVER_PORT };
|
|
6820
|
+
}
|
|
6821
|
+
function ensureLogsServerDaemon() {
|
|
6822
|
+
try {
|
|
6823
|
+
const s = logsServerStatus();
|
|
6824
|
+
if (s.desired === "on" && !s.running) startLogsServerDaemon();
|
|
6825
|
+
} catch {
|
|
6826
|
+
}
|
|
6827
|
+
}
|
|
6828
|
+
var DIR, STATE_FILE2, LOG_FILE2, LOGS_SERVER_PORT;
|
|
6829
|
+
var init_logs_server_daemon = __esm({
|
|
6830
|
+
"src/logs-server-daemon.ts"() {
|
|
6831
|
+
"use strict";
|
|
6832
|
+
DIR = join5(homedir3(), ".solongate");
|
|
6833
|
+
STATE_FILE2 = join5(DIR, ".logs-server.json");
|
|
6834
|
+
LOG_FILE2 = join5(DIR, "logs-server.log");
|
|
6835
|
+
LOGS_SERVER_PORT = 8788;
|
|
6836
|
+
}
|
|
6837
|
+
});
|
|
6838
|
+
|
|
6839
|
+
// src/tui/config.ts
|
|
6840
|
+
import { readFileSync as readFileSync6 } from "fs";
|
|
6841
|
+
import { homedir as homedir4 } from "os";
|
|
6842
|
+
import { join as join6 } from "path";
|
|
6743
6843
|
function loadConfig() {
|
|
6744
6844
|
if (cached) return cached;
|
|
6745
6845
|
const defaults = { notifications: true };
|
|
6746
6846
|
try {
|
|
6747
|
-
const raw =
|
|
6847
|
+
const raw = readFileSync6(join6(homedir4(), ".solongate", "tui-config.json"), "utf-8");
|
|
6748
6848
|
const j = JSON.parse(raw);
|
|
6749
6849
|
cached = {
|
|
6750
6850
|
notifications: j.notifications !== false,
|
|
@@ -6870,14 +6970,14 @@ var init_components = __esm({
|
|
|
6870
6970
|
});
|
|
6871
6971
|
|
|
6872
6972
|
// src/tui/local-log.ts
|
|
6873
|
-
import { closeSync, openSync as
|
|
6874
|
-
import { homedir as
|
|
6875
|
-
import { join as
|
|
6973
|
+
import { closeSync, openSync as openSync3, readFileSync as readFileSync7, readSync, statSync, writeFileSync as writeFileSync5 } from "fs";
|
|
6974
|
+
import { homedir as homedir5 } from "os";
|
|
6975
|
+
import { join as join7 } from "path";
|
|
6876
6976
|
function tailLines(file, maxBytes = 131072) {
|
|
6877
6977
|
try {
|
|
6878
6978
|
const size = statSync(file).size;
|
|
6879
6979
|
const start = Math.max(0, size - maxBytes);
|
|
6880
|
-
const fd =
|
|
6980
|
+
const fd = openSync3(file, "r");
|
|
6881
6981
|
const buf = Buffer.alloc(size - start);
|
|
6882
6982
|
readSync(fd, buf, 0, buf.length, start);
|
|
6883
6983
|
closeSync(fd);
|
|
@@ -6890,7 +6990,7 @@ function tailLines(file, maxBytes = 131072) {
|
|
|
6890
6990
|
}
|
|
6891
6991
|
function deleteLocalEntry(at, tool, session) {
|
|
6892
6992
|
try {
|
|
6893
|
-
const lines =
|
|
6993
|
+
const lines = readFileSync7(LOCAL_LOG, "utf-8").split("\n");
|
|
6894
6994
|
let removed = 0;
|
|
6895
6995
|
const kept = lines.filter((line) => {
|
|
6896
6996
|
if (!line.trim()) return false;
|
|
@@ -6906,7 +7006,7 @@ function deleteLocalEntry(at, tool, session) {
|
|
|
6906
7006
|
}
|
|
6907
7007
|
return true;
|
|
6908
7008
|
});
|
|
6909
|
-
if (removed)
|
|
7009
|
+
if (removed) writeFileSync5(LOCAL_LOG, kept.length ? kept.join("\n") + "\n" : "");
|
|
6910
7010
|
return removed;
|
|
6911
7011
|
} catch {
|
|
6912
7012
|
return 0;
|
|
@@ -6914,8 +7014,8 @@ function deleteLocalEntry(at, tool, session) {
|
|
|
6914
7014
|
}
|
|
6915
7015
|
function clearLocalLog() {
|
|
6916
7016
|
try {
|
|
6917
|
-
const n =
|
|
6918
|
-
|
|
7017
|
+
const n = readFileSync7(LOCAL_LOG, "utf-8").split("\n").filter(Boolean).length;
|
|
7018
|
+
writeFileSync5(LOCAL_LOG, "");
|
|
6919
7019
|
return n;
|
|
6920
7020
|
} catch {
|
|
6921
7021
|
return 0;
|
|
@@ -6946,20 +7046,20 @@ var LOCAL_LOG, DLP_REASON, RL_REASON;
|
|
|
6946
7046
|
var init_local_log = __esm({
|
|
6947
7047
|
"src/tui/local-log.ts"() {
|
|
6948
7048
|
"use strict";
|
|
6949
|
-
LOCAL_LOG =
|
|
7049
|
+
LOCAL_LOG = join7(homedir5(), ".solongate", "local-logs", "solongate-audit.jsonl");
|
|
6950
7050
|
DLP_REASON = /security layer \(dlp\)/i;
|
|
6951
7051
|
RL_REASON = /security layer \(rate limit\)|rate[- ]?limit(?:ed)?\b.*exceed|exceeded \d+ calls/i;
|
|
6952
7052
|
}
|
|
6953
7053
|
});
|
|
6954
7054
|
|
|
6955
7055
|
// src/api-client/client.ts
|
|
6956
|
-
import { readFileSync as
|
|
6957
|
-
import { resolve as resolve3, join as
|
|
6958
|
-
import { homedir as
|
|
7056
|
+
import { readFileSync as readFileSync8, writeFileSync as writeFileSync6, mkdirSync as mkdirSync5, existsSync as existsSync3 } from "fs";
|
|
7057
|
+
import { resolve as resolve3, join as join8 } from "path";
|
|
7058
|
+
import { homedir as homedir6 } from "os";
|
|
6959
7059
|
function listAccounts() {
|
|
6960
7060
|
let list6 = [];
|
|
6961
7061
|
try {
|
|
6962
|
-
const raw = JSON.parse(
|
|
7062
|
+
const raw = JSON.parse(readFileSync8(accountsFile(), "utf-8"));
|
|
6963
7063
|
if (Array.isArray(raw)) list6 = raw.filter((a) => a && typeof a.apiKey === "string");
|
|
6964
7064
|
} catch {
|
|
6965
7065
|
}
|
|
@@ -6973,7 +7073,7 @@ function saveAccount(acc) {
|
|
|
6973
7073
|
try {
|
|
6974
7074
|
const list6 = (() => {
|
|
6975
7075
|
try {
|
|
6976
|
-
const raw = JSON.parse(
|
|
7076
|
+
const raw = JSON.parse(readFileSync8(accountsFile(), "utf-8"));
|
|
6977
7077
|
return Array.isArray(raw) ? raw.filter((a) => a && a.apiKey) : [];
|
|
6978
7078
|
} catch {
|
|
6979
7079
|
return [];
|
|
@@ -6981,8 +7081,8 @@ function saveAccount(acc) {
|
|
|
6981
7081
|
})();
|
|
6982
7082
|
const next = list6.filter((a) => a.apiKey !== acc.apiKey);
|
|
6983
7083
|
next.unshift({ ...acc, addedAt: acc.addedAt ?? Date.now() });
|
|
6984
|
-
|
|
6985
|
-
|
|
7084
|
+
mkdirSync5(join8(homedir6(), ".solongate"), { recursive: true });
|
|
7085
|
+
writeFileSync6(accountsFile(), JSON.stringify(next, null, 2));
|
|
6986
7086
|
} catch {
|
|
6987
7087
|
}
|
|
6988
7088
|
}
|
|
@@ -6995,15 +7095,15 @@ function isActiveAccount(apiKey) {
|
|
|
6995
7095
|
}
|
|
6996
7096
|
function setActiveAccount(creds) {
|
|
6997
7097
|
try {
|
|
6998
|
-
const dir =
|
|
6999
|
-
|
|
7000
|
-
const p =
|
|
7098
|
+
const dir = join8(homedir6(), ".solongate");
|
|
7099
|
+
mkdirSync5(dir, { recursive: true });
|
|
7100
|
+
const p = join8(dir, ["cloud", "guard.json"].join("-"));
|
|
7001
7101
|
let existing = {};
|
|
7002
7102
|
try {
|
|
7003
|
-
existing = JSON.parse(
|
|
7103
|
+
existing = JSON.parse(readFileSync8(p, "utf-8"));
|
|
7004
7104
|
} catch {
|
|
7005
7105
|
}
|
|
7006
|
-
|
|
7106
|
+
writeFileSync6(p, JSON.stringify({ ...existing, apiKey: creds.apiKey, apiUrl: creds.apiUrl }, null, 2));
|
|
7007
7107
|
cached2 = null;
|
|
7008
7108
|
return true;
|
|
7009
7109
|
} catch {
|
|
@@ -7012,9 +7112,9 @@ function setActiveAccount(creds) {
|
|
|
7012
7112
|
}
|
|
7013
7113
|
function loginCredentialFile() {
|
|
7014
7114
|
try {
|
|
7015
|
-
const p =
|
|
7115
|
+
const p = join8(homedir6(), ".solongate", "cloud-guard.json");
|
|
7016
7116
|
if (!existsSync3(p)) return {};
|
|
7017
|
-
const c2 = JSON.parse(
|
|
7117
|
+
const c2 = JSON.parse(readFileSync8(p, "utf-8"));
|
|
7018
7118
|
return c2 && typeof c2 === "object" ? c2 : {};
|
|
7019
7119
|
} catch {
|
|
7020
7120
|
return {};
|
|
@@ -7024,7 +7124,7 @@ function dotenvApiKey() {
|
|
|
7024
7124
|
try {
|
|
7025
7125
|
const envPath = resolve3(".env");
|
|
7026
7126
|
if (!existsSync3(envPath)) return void 0;
|
|
7027
|
-
for (const line of
|
|
7127
|
+
for (const line of readFileSync8(envPath, "utf-8").split("\n")) {
|
|
7028
7128
|
const trimmed = line.trim();
|
|
7029
7129
|
if (!trimmed || trimmed.startsWith("#")) continue;
|
|
7030
7130
|
const eq = trimmed.indexOf("=");
|
|
@@ -7126,7 +7226,7 @@ var init_client = __esm({
|
|
|
7126
7226
|
"src/api-client/client.ts"() {
|
|
7127
7227
|
"use strict";
|
|
7128
7228
|
DEFAULT_API_URL2 = "https://api.solongate.com";
|
|
7129
|
-
accountsFile = () =>
|
|
7229
|
+
accountsFile = () => join8(homedir6(), ".solongate", "accounts.json");
|
|
7130
7230
|
viewOverride = null;
|
|
7131
7231
|
ApiError = class extends Error {
|
|
7132
7232
|
status;
|
|
@@ -7156,12 +7256,12 @@ var init_types = __esm({
|
|
|
7156
7256
|
});
|
|
7157
7257
|
|
|
7158
7258
|
// src/api-client/device-login.ts
|
|
7159
|
-
import { spawn as
|
|
7259
|
+
import { spawn as spawn3 } from "child_process";
|
|
7160
7260
|
function openBrowser(url) {
|
|
7161
7261
|
try {
|
|
7162
7262
|
const cmd = process.platform === "win32" ? "cmd" : process.platform === "darwin" ? "open" : "xdg-open";
|
|
7163
7263
|
const args = process.platform === "win32" ? ["/c", "start", '""', url] : [url];
|
|
7164
|
-
const child =
|
|
7264
|
+
const child = spawn3(cmd, args, { stdio: "ignore", detached: true });
|
|
7165
7265
|
child.on("error", () => {
|
|
7166
7266
|
});
|
|
7167
7267
|
child.unref();
|
|
@@ -7502,24 +7602,24 @@ var init_api_client = __esm({
|
|
|
7502
7602
|
});
|
|
7503
7603
|
|
|
7504
7604
|
// src/tui/notify.ts
|
|
7505
|
-
import { spawn as
|
|
7605
|
+
import { spawn as spawn4 } from "child_process";
|
|
7506
7606
|
function desktopNotify(title, msg) {
|
|
7507
7607
|
try {
|
|
7508
7608
|
if (process.platform === "linux") {
|
|
7509
|
-
const p =
|
|
7609
|
+
const p = spawn4("notify-send", ["-a", "SolonGate", title, msg], { stdio: "ignore", detached: true });
|
|
7510
7610
|
p.on("error", () => {
|
|
7511
7611
|
});
|
|
7512
7612
|
p.unref();
|
|
7513
7613
|
} else if (process.platform === "win32") {
|
|
7514
7614
|
const q = (s) => s.replace(/'/g, "''");
|
|
7515
7615
|
const ps = `Add-Type -AssemblyName System.Windows.Forms;Add-Type -AssemblyName System.Drawing;$n=New-Object System.Windows.Forms.NotifyIcon;$n.Icon=[System.Drawing.SystemIcons]::Information;$n.Visible=$true;$n.ShowBalloonTip(6000,'${q(title)}','${q(msg)}',[System.Windows.Forms.ToolTipIcon]::Warning);Start-Sleep -Milliseconds 6500;$n.Dispose()`;
|
|
7516
|
-
const p =
|
|
7616
|
+
const p = spawn4("powershell", ["-NoProfile", "-NonInteractive", "-Command", ps], { stdio: "ignore", detached: true, windowsHide: true });
|
|
7517
7617
|
p.on("error", () => {
|
|
7518
7618
|
});
|
|
7519
7619
|
p.unref();
|
|
7520
7620
|
} else if (process.platform === "darwin") {
|
|
7521
7621
|
const esc = (s) => s.replace(/"/g, '\\"');
|
|
7522
|
-
const p =
|
|
7622
|
+
const p = spawn4("osascript", ["-e", `display notification "${esc(msg)}" with title "${esc(title)}"`], { stdio: "ignore", detached: true });
|
|
7523
7623
|
p.on("error", () => {
|
|
7524
7624
|
});
|
|
7525
7625
|
p.unref();
|
|
@@ -7605,9 +7705,9 @@ var init_hooks = __esm({
|
|
|
7605
7705
|
// src/tui/panels/Live.tsx
|
|
7606
7706
|
import { Box as Box2, Text as Text2, useInput } from "ink";
|
|
7607
7707
|
import TextInput from "ink-text-input";
|
|
7608
|
-
import { mkdirSync as
|
|
7609
|
-
import { homedir as
|
|
7610
|
-
import { join as
|
|
7708
|
+
import { mkdirSync as mkdirSync6, writeFileSync as writeFileSync7 } from "fs";
|
|
7709
|
+
import { homedir as homedir7 } from "os";
|
|
7710
|
+
import { join as join9 } from "path";
|
|
7611
7711
|
import { useCallback as useCallback2, useEffect as useEffect2, useRef as useRef2, useState as useState2 } from "react";
|
|
7612
7712
|
import { Fragment as Fragment2, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
7613
7713
|
function extractTarget(detail) {
|
|
@@ -8198,10 +8298,10 @@ function LivePanel({ active: active2 }) {
|
|
|
8198
8298
|
else if (input === "x") toggleSignal("dlp");
|
|
8199
8299
|
else if (input === "r") toggleSignal("ratelimit");
|
|
8200
8300
|
else if (input === "e") {
|
|
8201
|
-
const file =
|
|
8301
|
+
const file = join9(homedir7(), ".solongate", "live-export.jsonl");
|
|
8202
8302
|
try {
|
|
8203
|
-
|
|
8204
|
-
|
|
8303
|
+
mkdirSync6(join9(homedir7(), ".solongate"), { recursive: true });
|
|
8304
|
+
writeFileSync7(file, visibleDesc.map((x) => JSON.stringify(x)).join("\n") + "\n");
|
|
8205
8305
|
setActionMsg({ text: `\u2713 exported ${visibleDesc.length} lines \u2192 ${file}`, level: "ok", until: Date.now() + 6e3 });
|
|
8206
8306
|
} catch (err2) {
|
|
8207
8307
|
setActionMsg({ text: "\u2717 export failed: " + (err2 instanceof Error ? err2.message : String(err2)), level: "bad", until: Date.now() + 6e3 });
|
|
@@ -8611,7 +8711,7 @@ var init_Live = __esm({
|
|
|
8611
8711
|
SPIN = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
8612
8712
|
BG = "#12234f";
|
|
8613
8713
|
DIM_FLOOR = "#233457";
|
|
8614
|
-
RING =
|
|
8714
|
+
RING = join9(process.cwd(), ".solongate", ".eval-ring.jsonl");
|
|
8615
8715
|
hhmmss = (ts) => {
|
|
8616
8716
|
const d = new Date(ts);
|
|
8617
8717
|
return Number.isNaN(d.getTime()) ? "--:--:--" : d.toTimeString().slice(0, 8);
|
|
@@ -9301,9 +9401,9 @@ var init_Dlp = __esm({
|
|
|
9301
9401
|
// src/tui/panels/Audit.tsx
|
|
9302
9402
|
import { Box as Box6, Text as Text6, useInput as useInput5 } from "ink";
|
|
9303
9403
|
import TextInput4 from "ink-text-input";
|
|
9304
|
-
import { mkdirSync as
|
|
9305
|
-
import { homedir as
|
|
9306
|
-
import { join as
|
|
9404
|
+
import { mkdirSync as mkdirSync7, writeFileSync as writeFileSync8 } from "fs";
|
|
9405
|
+
import { homedir as homedir8 } from "os";
|
|
9406
|
+
import { join as join10 } from "path";
|
|
9307
9407
|
import { useState as useState6 } from "react";
|
|
9308
9408
|
import { Fragment as Fragment4, jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
9309
9409
|
function loadLocalRows() {
|
|
@@ -9457,16 +9557,16 @@ function AuditPanel({ active: active2, focused }) {
|
|
|
9457
9557
|
const doExport = (kind) => {
|
|
9458
9558
|
setMsg({ text: "exporting\u2026", level: "ok" });
|
|
9459
9559
|
const run12 = async () => {
|
|
9460
|
-
const dir =
|
|
9461
|
-
const file =
|
|
9560
|
+
const dir = join10(homedir8(), ".solongate");
|
|
9561
|
+
const file = join10(dir, `audit-export-${source}.jsonl`);
|
|
9462
9562
|
let rows2;
|
|
9463
9563
|
if (kind === "page") rows2 = pageRows;
|
|
9464
9564
|
else if (source === "cloud") {
|
|
9465
9565
|
const r = await api.audit.list({ ...query, limit: 1e4, offset: 0 });
|
|
9466
9566
|
rows2 = r.entries.map(cloudRow).sort((a, b) => b.at - a.at);
|
|
9467
9567
|
} else rows2 = localFiltered;
|
|
9468
|
-
|
|
9469
|
-
|
|
9568
|
+
mkdirSync7(dir, { recursive: true });
|
|
9569
|
+
writeFileSync8(file, rows2.map((x) => JSON.stringify(x)).join("\n") + (rows2.length ? "\n" : ""));
|
|
9470
9570
|
return { n: rows2.length, file };
|
|
9471
9571
|
};
|
|
9472
9572
|
run12().then(({ n, file }) => setMsg({ text: `\u2713 exported ${n} rows \u2192 ${file}`, level: "ok" })).catch((e) => setMsg({ text: "\u2717 export failed: " + (e instanceof Error ? e.message : String(e)), level: "bad" }));
|
|
@@ -9956,8 +10056,8 @@ var init_Audit = __esm({
|
|
|
9956
10056
|
// src/tui/panels/Settings.tsx
|
|
9957
10057
|
import { Box as Box7, Text as Text7, useInput as useInput6 } from "ink";
|
|
9958
10058
|
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";
|
|
10059
|
+
import { useEffect as useEffect6, useRef as useRef3, useState as useState7 } from "react";
|
|
10060
|
+
import { Fragment as Fragment5, jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
9961
10061
|
function alertBodyFor(channel) {
|
|
9962
10062
|
const c2 = channel.trim();
|
|
9963
10063
|
const base = { name: "dataroom alert", threshold: 5, windowSeconds: 60, signal: "any" };
|
|
@@ -9965,7 +10065,12 @@ function alertBodyFor(channel) {
|
|
|
9965
10065
|
if (c2.includes("@")) return { ...base, emails: [c2] };
|
|
9966
10066
|
return { ...base, telegram: [c2] };
|
|
9967
10067
|
}
|
|
9968
|
-
function SettingsPanel({
|
|
10068
|
+
function SettingsPanel({
|
|
10069
|
+
active: active2,
|
|
10070
|
+
focused,
|
|
10071
|
+
viewApiKey,
|
|
10072
|
+
onView
|
|
10073
|
+
}) {
|
|
9969
10074
|
void active2;
|
|
9970
10075
|
const { cols, rows } = usePanelSize();
|
|
9971
10076
|
const [sel, setSel] = useState7(0);
|
|
@@ -9974,24 +10079,46 @@ function SettingsPanel({ active: active2, focused }) {
|
|
|
9974
10079
|
const [confirmDel, setConfirmDel] = useState7(null);
|
|
9975
10080
|
const [msg, setMsg] = useState7(null);
|
|
9976
10081
|
const [busy, setBusy] = useState7(false);
|
|
9977
|
-
const
|
|
9978
|
-
const
|
|
9979
|
-
const
|
|
10082
|
+
const [accounts, setAccounts] = useState7(() => listAccounts());
|
|
10083
|
+
const [login, setLogin] = useState7(null);
|
|
10084
|
+
const [tick, setTick] = useState7(0);
|
|
10085
|
+
const abort = useRef3(false);
|
|
10086
|
+
const refreshAccounts = () => setAccounts(listAccounts());
|
|
10087
|
+
const locked = accounts.length === 0;
|
|
10088
|
+
const [srv, setSrv] = useState7(() => logsServerStatus());
|
|
10089
|
+
useEffect6(() => {
|
|
10090
|
+
const t = setInterval(() => setSrv(logsServerStatus()), 3e3);
|
|
10091
|
+
return () => clearInterval(t);
|
|
10092
|
+
}, []);
|
|
10093
|
+
useEffect6(() => {
|
|
10094
|
+
if (!login || login.phase === "done" || login.phase === "error") return;
|
|
10095
|
+
const t = setInterval(() => setTick((n) => n + 1), 120);
|
|
10096
|
+
return () => clearInterval(t);
|
|
10097
|
+
}, [login]);
|
|
10098
|
+
const localQ = useLoader(() => listAccounts().length ? api.settings.getLocalLogs() : Promise.resolve(null));
|
|
10099
|
+
const whQ = useLoader(() => listAccounts().length ? api.settings.getWebhooks() : Promise.resolve(null));
|
|
10100
|
+
const alertQ = useLoader(() => listAccounts().length ? api.settings.getAlerts() : Promise.resolve(null));
|
|
9980
10101
|
const local = localQ.data;
|
|
9981
10102
|
const webhooks = whQ.data?.webhooks ?? [];
|
|
9982
10103
|
const alerts = alertQ.data?.rules ?? [];
|
|
9983
10104
|
const rowsAll = [
|
|
9984
|
-
{ kind: "
|
|
9985
|
-
{ kind: "
|
|
9986
|
-
...
|
|
9987
|
-
|
|
9988
|
-
|
|
9989
|
-
|
|
10105
|
+
...accounts.map((acc) => ({ kind: "acct", acc })),
|
|
10106
|
+
{ kind: "acct-add" },
|
|
10107
|
+
...locked ? [] : [
|
|
10108
|
+
{ kind: "ll-enabled" },
|
|
10109
|
+
{ kind: "ll-path" },
|
|
10110
|
+
{ kind: "ll-server" },
|
|
10111
|
+
...webhooks.map((wh) => ({ kind: "wh", wh })),
|
|
10112
|
+
{ kind: "wh-add" },
|
|
10113
|
+
...alerts.map((rule) => ({ kind: "alert", rule })),
|
|
10114
|
+
{ kind: "alert-add" }
|
|
10115
|
+
]
|
|
9990
10116
|
];
|
|
9991
10117
|
const selClamped = Math.min(sel, rowsAll.length - 1);
|
|
9992
10118
|
const cur = rowsAll[selClamped];
|
|
9993
|
-
const keyOf = (r) => r.kind === "wh" ? "wh:" + r.wh.id : r.kind === "alert" ? "alert:" + r.rule.id : r.kind;
|
|
10119
|
+
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
10120
|
const reloadAll = () => {
|
|
10121
|
+
refreshAccounts();
|
|
9995
10122
|
localQ.reload();
|
|
9996
10123
|
whQ.reload();
|
|
9997
10124
|
alertQ.reload();
|
|
@@ -10005,8 +10132,48 @@ function SettingsPanel({ active: active2, focused }) {
|
|
|
10005
10132
|
reload();
|
|
10006
10133
|
}).catch((e) => setMsg({ text: "\u2717 " + (e instanceof Error ? e.message : String(e)), level: "bad" })).finally(() => setBusy(false));
|
|
10007
10134
|
};
|
|
10135
|
+
const beginLogin = () => {
|
|
10136
|
+
if (login && (login.phase === "starting" || login.phase === "waiting")) return;
|
|
10137
|
+
abort.current = false;
|
|
10138
|
+
setLogin({ phase: "starting" });
|
|
10139
|
+
void (async () => {
|
|
10140
|
+
let start2;
|
|
10141
|
+
try {
|
|
10142
|
+
start2 = await startDeviceLogin(DEFAULT_API_URL2);
|
|
10143
|
+
} catch (e) {
|
|
10144
|
+
setLogin({ phase: "error", msg: "could not reach SolonGate: " + (e instanceof Error ? e.message : String(e)) });
|
|
10145
|
+
return;
|
|
10146
|
+
}
|
|
10147
|
+
setLogin({ phase: "waiting", url: start2.verifyUrl });
|
|
10148
|
+
openBrowser(start2.verifyUrl);
|
|
10149
|
+
while (Date.now() < start2.expiresAt && !abort.current) {
|
|
10150
|
+
await new Promise((r) => setTimeout(r, start2.intervalMs));
|
|
10151
|
+
if (abort.current) return;
|
|
10152
|
+
const res = await pollDeviceLogin(DEFAULT_API_URL2, start2.deviceCode);
|
|
10153
|
+
if (res.status === "approved" && res.apiKey) {
|
|
10154
|
+
saveAccount({ apiKey: res.apiKey, apiUrl: DEFAULT_API_URL2, project: res.project, user: res.user, email: res.email });
|
|
10155
|
+
setLogin({ phase: "done", msg: `\u2713 added ${res.email || res.user || res.project || "account"}` });
|
|
10156
|
+
setViewCredentials({ apiKey: res.apiKey, apiUrl: DEFAULT_API_URL2 });
|
|
10157
|
+
onView?.({ apiKey: res.apiKey, apiUrl: DEFAULT_API_URL2, project: res.project, user: res.user, email: res.email });
|
|
10158
|
+
reloadAll();
|
|
10159
|
+
return;
|
|
10160
|
+
}
|
|
10161
|
+
if (res.status === "expired" || res.status === "not_found") {
|
|
10162
|
+
setLogin({ phase: "error", msg: "code expired \u2014 press n to retry" });
|
|
10163
|
+
return;
|
|
10164
|
+
}
|
|
10165
|
+
}
|
|
10166
|
+
if (!abort.current) setLogin({ phase: "error", msg: "timed out \u2014 press n to retry" });
|
|
10167
|
+
})();
|
|
10168
|
+
};
|
|
10008
10169
|
const activate = (r) => {
|
|
10009
|
-
if (r.kind === "
|
|
10170
|
+
if (r.kind === "acct") {
|
|
10171
|
+
setViewCredentials({ apiKey: r.acc.apiKey, apiUrl: r.acc.apiUrl });
|
|
10172
|
+
onView?.(r.acc);
|
|
10173
|
+
setMsg({ text: `viewing ${acctLabel(r.acc)}`, level: "ok" });
|
|
10174
|
+
} else if (r.kind === "acct-add") {
|
|
10175
|
+
beginLogin();
|
|
10176
|
+
} else if (r.kind === "ll-enabled") {
|
|
10010
10177
|
if (!local) return;
|
|
10011
10178
|
if (!local.enabled && !local.path.trim()) {
|
|
10012
10179
|
setMsg({ text: "set a path first (\u2193 then enter)", level: "bad" });
|
|
@@ -10016,6 +10183,12 @@ function SettingsPanel({ active: active2, focused }) {
|
|
|
10016
10183
|
} else if (r.kind === "ll-path") {
|
|
10017
10184
|
setInput(local?.path ?? "");
|
|
10018
10185
|
setEditing("path");
|
|
10186
|
+
} else if (r.kind === "ll-server") {
|
|
10187
|
+
const next = srv.running ? stopLogsServerDaemon() : startLogsServerDaemon();
|
|
10188
|
+
setSrv(next);
|
|
10189
|
+
setMsg(
|
|
10190
|
+
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" }
|
|
10191
|
+
);
|
|
10019
10192
|
} else if (r.kind === "wh") {
|
|
10020
10193
|
run12(r.wh.enabled ? "webhook disabled" : "webhook enabled", () => api.settings.updateWebhook(r.wh.id, { enabled: !r.wh.enabled }), whQ.reload);
|
|
10021
10194
|
} else if (r.kind === "wh-add") {
|
|
@@ -10045,6 +10218,13 @@ function SettingsPanel({ active: active2, focused }) {
|
|
|
10045
10218
|
};
|
|
10046
10219
|
useInput6(
|
|
10047
10220
|
(inp, key) => {
|
|
10221
|
+
if (login && (login.phase === "starting" || login.phase === "waiting")) {
|
|
10222
|
+
if (key.escape) {
|
|
10223
|
+
abort.current = true;
|
|
10224
|
+
setLogin(null);
|
|
10225
|
+
}
|
|
10226
|
+
return;
|
|
10227
|
+
}
|
|
10048
10228
|
setMsg(null);
|
|
10049
10229
|
if (key.upArrow) {
|
|
10050
10230
|
setSel((n) => Math.max(0, n - 1));
|
|
@@ -10053,6 +10233,11 @@ function SettingsPanel({ active: active2, focused }) {
|
|
|
10053
10233
|
setSel((n) => Math.min(rowsAll.length - 1, n + 1));
|
|
10054
10234
|
setConfirmDel(null);
|
|
10055
10235
|
} else if (key.return || inp === " ") activate(cur);
|
|
10236
|
+
else if (inp === "m" && cur.kind === "acct") {
|
|
10237
|
+
const ok = setActiveAccount({ apiKey: cur.acc.apiKey, apiUrl: cur.acc.apiUrl });
|
|
10238
|
+
setMsg(ok ? { text: `\u2713 ${acctLabel(cur.acc)} is now the ACTIVE key (guard + logging)`, level: "ok" } : { text: "\u2717 could not set active", level: "bad" });
|
|
10239
|
+
refreshAccounts();
|
|
10240
|
+
} else if (inp === "n") beginLogin();
|
|
10056
10241
|
else if (inp === "e" && cur.kind === "wh") {
|
|
10057
10242
|
const next = EVENTS[(EVENTS.indexOf(cur.wh.events) + 1) % EVENTS.length];
|
|
10058
10243
|
run12(`webhook events \u2192 ${next}`, () => api.settings.updateWebhook(cur.wh.id, { events: next }), whQ.reload);
|
|
@@ -10079,247 +10264,170 @@ function SettingsPanel({ active: active2, focused }) {
|
|
|
10079
10264
|
},
|
|
10080
10265
|
{ isActive: focused && !editing }
|
|
10081
10266
|
);
|
|
10082
|
-
const
|
|
10083
|
-
|
|
10267
|
+
const spin = SPIN2[tick % SPIN2.length];
|
|
10268
|
+
if (login && (login.phase === "starting" || login.phase === "waiting")) {
|
|
10269
|
+
return /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
|
|
10270
|
+
/* @__PURE__ */ jsx7(Text7, { bold: true, color: theme.accentBright, children: "Add an account" }),
|
|
10271
|
+
login.phase === "starting" ? /* @__PURE__ */ jsxs7(Text7, { color: theme.dim, children: [
|
|
10272
|
+
spin,
|
|
10273
|
+
" starting device pairing\u2026"
|
|
10274
|
+
] }) : /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", marginTop: 1, children: [
|
|
10275
|
+
/* @__PURE__ */ jsx7(Text7, { color: theme.dim, children: "Opening your browser to authorize. If it didn't open, visit:" }),
|
|
10276
|
+
/* @__PURE__ */ jsx7(Text7, { color: theme.accentBright, bold: true, wrap: "truncate", children: login.url }),
|
|
10277
|
+
/* @__PURE__ */ jsxs7(Box7, { marginTop: 1, children: [
|
|
10278
|
+
/* @__PURE__ */ jsxs7(Text7, { color: theme.warn, children: [
|
|
10279
|
+
spin,
|
|
10280
|
+
" waiting for authorization\u2026 "
|
|
10281
|
+
] }),
|
|
10282
|
+
/* @__PURE__ */ jsx7(Text7, { color: theme.dim, children: "esc to cancel" })
|
|
10283
|
+
] })
|
|
10284
|
+
] })
|
|
10285
|
+
] });
|
|
10286
|
+
}
|
|
10287
|
+
const loading = !locked && (localQ.loading && !localQ.data || whQ.loading && !whQ.data || alertQ.loading && !alertQ.data);
|
|
10288
|
+
const error = locked ? null : localQ.error ?? whQ.error ?? alertQ.error;
|
|
10084
10289
|
const mark = (r) => keyOf(r) === keyOf(cur) && focused ? "\u25B8 " : " ";
|
|
10085
10290
|
const onOff = (on) => on ? /* @__PURE__ */ jsx7(Text7, { color: theme.ok, children: "on " }) : /* @__PURE__ */ jsx7(Text7, { color: theme.dim, children: "off" });
|
|
10086
10291
|
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 -
|
|
10292
|
+
const listBudget = Math.max(4, rows - 10);
|
|
10088
10293
|
const start = Math.min(Math.max(0, selClamped - Math.floor(listBudget / 2)), Math.max(0, rowsAll.length - listBudget));
|
|
10089
10294
|
const inWindow = (r) => {
|
|
10090
10295
|
const i = rowsAll.findIndex((x) => keyOf(x) === keyOf(r));
|
|
10091
10296
|
return i >= start && i < start + listBudget;
|
|
10092
10297
|
};
|
|
10093
10298
|
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
|
|
10299
|
+
/* @__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
10300
|
editing ? /* @__PURE__ */ jsxs7(Box7, { children: [
|
|
10096
10301
|
/* @__PURE__ */ jsx7(Text7, { color: theme.warn, children: editing === "path" ? "local log path: " : editing === "wh-url" ? "webhook url: " : "channel (slack url / email / telegram id): " }),
|
|
10097
10302
|
/* @__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,
|
|
10303
|
+
] }) : 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
10304
|
/* @__PURE__ */ jsxs7(Box7, { marginTop: 1, flexDirection: "column", children: [
|
|
10117
10305
|
/* @__PURE__ */ jsxs7(Text7, { bold: true, color: theme.accentBright, children: [
|
|
10118
|
-
"
|
|
10306
|
+
"ACCOUNTS ",
|
|
10119
10307
|
/* @__PURE__ */ jsxs7(Text7, { color: theme.dim, children: [
|
|
10120
|
-
"\u2014
|
|
10121
|
-
|
|
10122
|
-
")"
|
|
10308
|
+
"\u2014 logged in on this device (",
|
|
10309
|
+
accounts.length,
|
|
10310
|
+
") \xB7 \u25CF viewing = shown here \xB7 ACTIVE = key the guard uses"
|
|
10123
10311
|
] })
|
|
10124
10312
|
] }),
|
|
10125
|
-
|
|
10126
|
-
/* @__PURE__ */ jsx7(Text7, { color:
|
|
10127
|
-
|
|
10128
|
-
/* @__PURE__ */ jsx7(Text7, { color: theme.
|
|
10129
|
-
|
|
10130
|
-
|
|
10131
|
-
|
|
10132
|
-
|
|
10133
|
-
/* @__PURE__ */
|
|
10313
|
+
accounts.length === 0 ? /* @__PURE__ */ jsxs7(Text7, { children: [
|
|
10314
|
+
/* @__PURE__ */ jsx7(Text7, { color: theme.dim, children: " no accounts yet \u2014 " }),
|
|
10315
|
+
/* @__PURE__ */ jsx7(Text7, { color: theme.accent, children: "n" }),
|
|
10316
|
+
/* @__PURE__ */ jsx7(Text7, { color: theme.dim, children: " (or enter) logs in, pairs this device and unlocks the dataroom" })
|
|
10317
|
+
] }) : null,
|
|
10318
|
+
accounts.filter((acc) => inWindow({ kind: "acct", acc })).map((a) => {
|
|
10319
|
+
const isView = viewApiKey ? a.apiKey === viewApiKey : accounts[0]?.apiKey === a.apiKey;
|
|
10320
|
+
const isActive = isActiveAccount(a.apiKey);
|
|
10321
|
+
return /* @__PURE__ */ jsxs7(Text7, { wrap: "truncate", children: [
|
|
10322
|
+
/* @__PURE__ */ jsx7(Text7, { color: keyOf(cur) === "acct:" + a.apiKey && focused ? theme.accentBright : theme.dim, children: mark({ kind: "acct", acc: a }) }),
|
|
10323
|
+
/* @__PURE__ */ jsx7(Text7, { color: theme.accent, children: truncate2(acctLabel(a), 30).padEnd(31) }),
|
|
10324
|
+
isView ? /* @__PURE__ */ jsx7(Text7, { color: theme.ok, children: "\u25CF viewing " }) : /* @__PURE__ */ jsx7(Text7, { color: theme.dim, children: " " }),
|
|
10325
|
+
isActive ? /* @__PURE__ */ jsx7(Text7, { color: theme.warn, children: "ACTIVE " }) : /* @__PURE__ */ jsx7(Text7, { color: theme.dim, children: " " }),
|
|
10326
|
+
/* @__PURE__ */ jsx7(Text7, { color: theme.dim, children: a.project ? truncate2(a.project, 24) : "" })
|
|
10327
|
+
] }, a.apiKey);
|
|
10328
|
+
}),
|
|
10329
|
+
inWindow({ kind: "acct-add" }) ? /* @__PURE__ */ jsxs7(Text7, { children: [
|
|
10330
|
+
/* @__PURE__ */ jsx7(Text7, { color: cur.kind === "acct-add" && focused ? theme.accentBright : theme.dim, children: mark({ kind: "acct-add" }) }),
|
|
10331
|
+
/* @__PURE__ */ jsx7(Text7, { color: theme.dim, children: "+ add account (enter \u2014 device login in the browser)" })
|
|
10134
10332
|
] }) : null
|
|
10135
10333
|
] }),
|
|
10136
|
-
/* @__PURE__ */ jsxs7(
|
|
10137
|
-
/* @__PURE__ */ jsxs7(
|
|
10138
|
-
|
|
10139
|
-
|
|
10140
|
-
"\u2014
|
|
10141
|
-
|
|
10142
|
-
|
|
10334
|
+
locked ? null : /* @__PURE__ */ jsxs7(Fragment5, { children: [
|
|
10335
|
+
inWindow({ kind: "ll-enabled" }) || inWindow({ kind: "ll-path" }) || inWindow({ kind: "ll-server" }) ? /* @__PURE__ */ jsxs7(Box7, { marginTop: 1, flexDirection: "column", children: [
|
|
10336
|
+
/* @__PURE__ */ jsxs7(Text7, { bold: true, color: theme.accentBright, children: [
|
|
10337
|
+
"LOCAL LOGS ",
|
|
10338
|
+
/* @__PURE__ */ jsx7(Text7, { color: theme.dim, children: "\u2014 hooks mirror every decision to a file on the agent machine" })
|
|
10339
|
+
] }),
|
|
10340
|
+
/* @__PURE__ */ jsxs7(Text7, { wrap: "truncate", children: [
|
|
10341
|
+
/* @__PURE__ */ jsx7(Text7, { color: keyOf(cur) === "ll-enabled" && focused ? theme.accentBright : theme.dim, children: mark({ kind: "ll-enabled" }) }),
|
|
10342
|
+
/* @__PURE__ */ jsx7(Text7, { color: theme.dim, children: "enabled ".padEnd(10) }),
|
|
10343
|
+
onOff(!!local?.enabled),
|
|
10344
|
+
/* @__PURE__ */ jsx7(Text7, { color: theme.dim, children: " enter toggles" })
|
|
10345
|
+
] }),
|
|
10346
|
+
/* @__PURE__ */ jsxs7(Text7, { wrap: "truncate", children: [
|
|
10347
|
+
/* @__PURE__ */ jsx7(Text7, { color: keyOf(cur) === "ll-path" && focused ? theme.accentBright : theme.dim, children: mark({ kind: "ll-path" }) }),
|
|
10348
|
+
/* @__PURE__ */ jsx7(Text7, { color: theme.dim, children: "path ".padEnd(10) }),
|
|
10349
|
+
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" })
|
|
10350
|
+
] }),
|
|
10351
|
+
/* @__PURE__ */ jsxs7(Text7, { wrap: "truncate", children: [
|
|
10352
|
+
/* @__PURE__ */ jsx7(Text7, { color: keyOf(cur) === "ll-server" && focused ? theme.accentBright : theme.dim, children: mark({ kind: "ll-server" }) }),
|
|
10353
|
+
/* @__PURE__ */ jsx7(Text7, { color: theme.dim, children: "dashboard".padEnd(10) }),
|
|
10354
|
+
srv.running ? /* @__PURE__ */ jsx7(Text7, { color: theme.ok, children: `running 127.0.0.1:${srv.port}` }) : /* @__PURE__ */ jsx7(Text7, { color: theme.dim, children: "stopped" }),
|
|
10355
|
+
/* @__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" })
|
|
10143
10356
|
] })
|
|
10357
|
+
] }) : null,
|
|
10358
|
+
/* @__PURE__ */ jsxs7(Box7, { marginTop: 1, flexDirection: "column", children: [
|
|
10359
|
+
/* @__PURE__ */ jsxs7(Text7, { bold: true, color: theme.accentBright, children: [
|
|
10360
|
+
"WEBHOOKS ",
|
|
10361
|
+
/* @__PURE__ */ jsxs7(Text7, { color: theme.dim, children: [
|
|
10362
|
+
"\u2014 POST every matching event to your endpoint (",
|
|
10363
|
+
webhooks.length,
|
|
10364
|
+
")"
|
|
10365
|
+
] })
|
|
10366
|
+
] }),
|
|
10367
|
+
webhooks.filter((wh) => inWindow({ kind: "wh", wh })).map((wh) => /* @__PURE__ */ jsxs7(Text7, { wrap: "truncate", children: [
|
|
10368
|
+
/* @__PURE__ */ jsx7(Text7, { color: keyOf(cur) === "wh:" + wh.id && focused ? theme.accentBright : theme.dim, children: mark({ kind: "wh", wh }) }),
|
|
10369
|
+
onOff(wh.enabled),
|
|
10370
|
+
/* @__PURE__ */ jsx7(Text7, { color: theme.warn, children: (" " + wh.events).padEnd(9) }),
|
|
10371
|
+
/* @__PURE__ */ jsx7(Text7, { color: theme.accent, children: truncate2(wh.url, cols - 16) })
|
|
10372
|
+
] }, wh.id)),
|
|
10373
|
+
inWindow({ kind: "wh-add" }) ? /* @__PURE__ */ jsxs7(Text7, { children: [
|
|
10374
|
+
/* @__PURE__ */ jsx7(Text7, { color: cur.kind === "wh-add" && focused ? theme.accentBright : theme.dim, children: mark({ kind: "wh-add" }) }),
|
|
10375
|
+
/* @__PURE__ */ jsx7(Text7, { color: theme.dim, children: "+ add webhook (enter)" })
|
|
10376
|
+
] }) : null
|
|
10144
10377
|
] }),
|
|
10145
|
-
|
|
10146
|
-
/* @__PURE__ */
|
|
10147
|
-
|
|
10148
|
-
|
|
10149
|
-
|
|
10150
|
-
|
|
10151
|
-
|
|
10152
|
-
|
|
10153
|
-
|
|
10154
|
-
|
|
10155
|
-
|
|
10378
|
+
/* @__PURE__ */ jsxs7(Box7, { marginTop: 1, flexDirection: "column", children: [
|
|
10379
|
+
/* @__PURE__ */ jsxs7(Text7, { bold: true, color: theme.accentBright, children: [
|
|
10380
|
+
"ALERTS ",
|
|
10381
|
+
/* @__PURE__ */ jsxs7(Text7, { color: theme.dim, children: [
|
|
10382
|
+
"\u2014 notify on a signal spike (",
|
|
10383
|
+
alerts.length,
|
|
10384
|
+
")"
|
|
10385
|
+
] })
|
|
10386
|
+
] }),
|
|
10387
|
+
alerts.filter((rule) => inWindow({ kind: "alert", rule })).map((rule) => /* @__PURE__ */ jsxs7(Text7, { wrap: "truncate", children: [
|
|
10388
|
+
/* @__PURE__ */ jsx7(Text7, { color: keyOf(cur) === "alert:" + rule.id && focused ? theme.accentBright : theme.dim, children: mark({ kind: "alert", rule }) }),
|
|
10389
|
+
onOff(rule.enabled),
|
|
10390
|
+
/* @__PURE__ */ jsx7(Text7, { color: theme.warn, children: (" " + rule.signal).padEnd(11) }),
|
|
10391
|
+
/* @__PURE__ */ jsx7(Text7, { children: `\u2265${rule.threshold}/${rule.windowSeconds}s ` }),
|
|
10392
|
+
/* @__PURE__ */ jsx7(Text7, { color: theme.accent, children: truncate2(chanOf(rule), cols - 26) })
|
|
10393
|
+
] }, rule.id)),
|
|
10394
|
+
inWindow({ kind: "alert-add" }) ? /* @__PURE__ */ jsxs7(Text7, { children: [
|
|
10395
|
+
/* @__PURE__ */ jsx7(Text7, { color: cur.kind === "alert-add" && focused ? theme.accentBright : theme.dim, children: mark({ kind: "alert-add" }) }),
|
|
10396
|
+
/* @__PURE__ */ jsx7(Text7, { color: theme.dim, children: "+ add alert (enter \u2014 one channel: slack url, email or telegram chat id)" })
|
|
10397
|
+
] }) : null
|
|
10398
|
+
] })
|
|
10156
10399
|
] })
|
|
10157
10400
|
] }) });
|
|
10158
10401
|
}
|
|
10159
|
-
var EVENTS;
|
|
10402
|
+
var EVENTS, SPIN2, acctLabel;
|
|
10160
10403
|
var init_Settings = __esm({
|
|
10161
10404
|
"src/tui/panels/Settings.tsx"() {
|
|
10162
10405
|
"use strict";
|
|
10163
10406
|
init_api_client();
|
|
10407
|
+
init_client();
|
|
10408
|
+
init_device_login();
|
|
10409
|
+
init_logs_server_daemon();
|
|
10164
10410
|
init_components();
|
|
10165
10411
|
init_hooks();
|
|
10166
10412
|
init_theme();
|
|
10167
10413
|
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
10414
|
SPIN2 = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
10415
|
+
acctLabel = (a) => a.email || a.user || "account \u2026" + a.apiKey.slice(-4);
|
|
10308
10416
|
}
|
|
10309
10417
|
});
|
|
10310
10418
|
|
|
10311
10419
|
// src/tui/App.tsx
|
|
10312
|
-
import { Box as
|
|
10313
|
-
import { useEffect as useEffect7, useState as
|
|
10314
|
-
import { jsx as
|
|
10420
|
+
import { Box as Box8, Text as Text8, useApp, useInput as useInput7 } from "ink";
|
|
10421
|
+
import { useEffect as useEffect7, useState as useState8 } from "react";
|
|
10422
|
+
import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
10315
10423
|
function LiveHint() {
|
|
10316
|
-
return /* @__PURE__ */
|
|
10317
|
-
/* @__PURE__ */
|
|
10318
|
-
/* @__PURE__ */
|
|
10319
|
-
/* @__PURE__ */
|
|
10320
|
-
/* @__PURE__ */
|
|
10424
|
+
return /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", children: [
|
|
10425
|
+
/* @__PURE__ */ jsx8(Text8, { color: theme.accentBright, bold: true, children: "\u25B6 REALTIME CONSOLE" }),
|
|
10426
|
+
/* @__PURE__ */ jsx8(Text8, { color: theme.dim, children: "Fullscreen live monitor \u2014 streaming tool calls, active charts," }),
|
|
10427
|
+
/* @__PURE__ */ jsx8(Text8, { color: theme.dim, children: "counters, DLP hits and denial alerts. Updates every 2s." }),
|
|
10428
|
+
/* @__PURE__ */ jsx8(Box8, { marginTop: 1, children: /* @__PURE__ */ jsxs8(Text8, { children: [
|
|
10321
10429
|
"press ",
|
|
10322
|
-
/* @__PURE__ */
|
|
10430
|
+
/* @__PURE__ */ jsx8(Text8, { color: theme.accent, children: "enter" }),
|
|
10323
10431
|
" to go live"
|
|
10324
10432
|
] }) })
|
|
10325
10433
|
] });
|
|
@@ -10327,25 +10435,25 @@ function LiveHint() {
|
|
|
10327
10435
|
function Banner({ cols }) {
|
|
10328
10436
|
const wide = cols >= 82;
|
|
10329
10437
|
if (!wide) {
|
|
10330
|
-
return /* @__PURE__ */
|
|
10331
|
-
/* @__PURE__ */
|
|
10332
|
-
/* @__PURE__ */
|
|
10438
|
+
return /* @__PURE__ */ jsxs8(Box8, { children: [
|
|
10439
|
+
/* @__PURE__ */ jsx8(Text8, { bold: true, color: theme.accentBright, children: "SolonGate" }),
|
|
10440
|
+
/* @__PURE__ */ jsx8(Text8, { color: theme.dim, children: " \u2014 security control center" })
|
|
10333
10441
|
] });
|
|
10334
10442
|
}
|
|
10335
|
-
return /* @__PURE__ */
|
|
10336
|
-
BANNER_FULL.map((line, i) => /* @__PURE__ */
|
|
10337
|
-
/* @__PURE__ */
|
|
10443
|
+
return /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", children: [
|
|
10444
|
+
BANNER_FULL.map((line, i) => /* @__PURE__ */ jsx8(Text8, { bold: true, color: BANNER_HEX[i], children: line }, i)),
|
|
10445
|
+
/* @__PURE__ */ jsx8(Text8, { color: theme.dim, children: " security control center \xB7 manage policies, rate limits, DLP & more" })
|
|
10338
10446
|
] });
|
|
10339
10447
|
}
|
|
10340
10448
|
function App() {
|
|
10341
10449
|
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] =
|
|
10450
|
+
const [accounts, setAccounts] = useState8(() => listAccounts());
|
|
10451
|
+
const [viewKey, setViewKey] = useState8(() => accounts[0]?.apiKey);
|
|
10452
|
+
const [viewNonce, setViewNonce] = useState8(0);
|
|
10453
|
+
const [section, setSection] = useState8(accounts.length === 0 ? SETTINGS_SECTION : 0);
|
|
10454
|
+
const [focus, setFocus] = useState8("nav");
|
|
10455
|
+
const [help, setHelp] = useState8(false);
|
|
10456
|
+
const [update2, setUpdate] = useState8({ kind: "idle" });
|
|
10349
10457
|
useEffect7(() => {
|
|
10350
10458
|
let alive = true;
|
|
10351
10459
|
const run12 = () => void tuiUpdateFlow((s) => alive && setUpdate(s));
|
|
@@ -10358,7 +10466,7 @@ function App() {
|
|
|
10358
10466
|
}, []);
|
|
10359
10467
|
const acctIdx = Math.max(0, accounts.findIndex((a) => a.apiKey === viewKey));
|
|
10360
10468
|
const cur = accounts[acctIdx];
|
|
10361
|
-
const
|
|
10469
|
+
const acctLabel2 = cur ? cur.email || cur.user || cur.project || `account \u2026${cur.apiKey.slice(-4)}` : "not logged in";
|
|
10362
10470
|
useEffect7(() => {
|
|
10363
10471
|
if (!cur || cur.email) return;
|
|
10364
10472
|
let alive = true;
|
|
@@ -10386,8 +10494,8 @@ function App() {
|
|
|
10386
10494
|
viewAccount(accounts[(acctIdx + 1) % accounts.length]);
|
|
10387
10495
|
};
|
|
10388
10496
|
const locked = accounts.length === 0;
|
|
10389
|
-
const effectiveSection = locked ?
|
|
10390
|
-
|
|
10497
|
+
const effectiveSection = locked ? SETTINGS_SECTION : section;
|
|
10498
|
+
useInput7((input, key) => {
|
|
10391
10499
|
if (help) {
|
|
10392
10500
|
setHelp(false);
|
|
10393
10501
|
return;
|
|
@@ -10415,45 +10523,45 @@ function App() {
|
|
|
10415
10523
|
});
|
|
10416
10524
|
const { cols, rows } = useTermSize();
|
|
10417
10525
|
const current = SECTIONS[effectiveSection];
|
|
10418
|
-
if (help) return /* @__PURE__ */
|
|
10526
|
+
if (help) return /* @__PURE__ */ jsx8(HelpOverlay, { cols, rows });
|
|
10419
10527
|
if (current.label === "Live" && focus === "panel") {
|
|
10420
|
-
return /* @__PURE__ */
|
|
10528
|
+
return /* @__PURE__ */ jsx8(Box8, { flexDirection: "column", width: cols, height: rows - 1, overflow: "hidden", children: /* @__PURE__ */ jsx8(LivePanel, { active: true, focused: true }, viewNonce) });
|
|
10421
10529
|
}
|
|
10422
10530
|
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__ */
|
|
10531
|
+
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" });
|
|
10532
|
+
return /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", width: cols, height: rows, paddingX: 1, paddingTop: 1, children: [
|
|
10533
|
+
/* @__PURE__ */ jsx8(Banner, { cols }),
|
|
10534
|
+
/* @__PURE__ */ jsxs8(Text8, { wrap: "truncate", children: [
|
|
10535
|
+
/* @__PURE__ */ jsx8(Text8, { color: theme.dim, children: "account: " }),
|
|
10536
|
+
/* @__PURE__ */ jsx8(Text8, { color: locked ? theme.warn : theme.accentBright, bold: true, children: acctLabel2 }),
|
|
10537
|
+
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" }),
|
|
10538
|
+
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
10539
|
] }),
|
|
10432
|
-
/* @__PURE__ */
|
|
10433
|
-
/* @__PURE__ */
|
|
10540
|
+
/* @__PURE__ */ jsxs8(Box8, { marginTop: 1, flexGrow: 1, children: [
|
|
10541
|
+
/* @__PURE__ */ jsx8(Box8, { flexDirection: "column", width: 16, borderStyle: "round", borderColor: focus === "nav" ? theme.accent : "gray", paddingX: 1, children: SECTIONS.map((s, i) => {
|
|
10434
10542
|
const isCur = i === effectiveSection;
|
|
10435
|
-
const disabled = locked && s.label !== "
|
|
10436
|
-
return /* @__PURE__ */
|
|
10543
|
+
const disabled = locked && s.label !== "Settings";
|
|
10544
|
+
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
10545
|
}) }),
|
|
10438
|
-
/* @__PURE__ */
|
|
10546
|
+
/* @__PURE__ */ jsx8(Box8, { flexGrow: 1, borderStyle: "round", borderColor: focus === "panel" ? theme.accent : "gray", paddingX: 1, paddingY: 0, children: panelBody })
|
|
10439
10547
|
] }, viewNonce),
|
|
10440
|
-
/* @__PURE__ */
|
|
10548
|
+
/* @__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
10549
|
] });
|
|
10442
10550
|
}
|
|
10443
10551
|
function HelpOverlay({ cols, rows }) {
|
|
10444
|
-
return /* @__PURE__ */
|
|
10445
|
-
/* @__PURE__ */
|
|
10446
|
-
/* @__PURE__ */
|
|
10447
|
-
/* @__PURE__ */
|
|
10448
|
-
keys.map(([k, desc]) => /* @__PURE__ */
|
|
10449
|
-
/* @__PURE__ */
|
|
10450
|
-
/* @__PURE__ */
|
|
10552
|
+
return /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", width: cols, height: rows, paddingX: 2, paddingTop: 1, children: [
|
|
10553
|
+
/* @__PURE__ */ jsx8(Text8, { bold: true, color: theme.accentBright, children: "SolonGate \u2014 keyboard shortcuts" }),
|
|
10554
|
+
/* @__PURE__ */ jsx8(Box8, { marginTop: 1, flexDirection: "column", children: HELP.map(([group, keys]) => /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", marginBottom: 1, children: [
|
|
10555
|
+
/* @__PURE__ */ jsx8(Text8, { bold: true, color: theme.accent, children: group }),
|
|
10556
|
+
keys.map(([k, desc]) => /* @__PURE__ */ jsxs8(Text8, { children: [
|
|
10557
|
+
/* @__PURE__ */ jsx8(Text8, { color: theme.accentBright, children: (" " + k).padEnd(16) }),
|
|
10558
|
+
/* @__PURE__ */ jsx8(Text8, { color: theme.dim, children: desc })
|
|
10451
10559
|
] }, k))
|
|
10452
10560
|
] }, group)) }),
|
|
10453
|
-
/* @__PURE__ */
|
|
10561
|
+
/* @__PURE__ */ jsx8(Text8, { color: theme.dim, children: "press any key to close" })
|
|
10454
10562
|
] });
|
|
10455
10563
|
}
|
|
10456
|
-
var SECTIONS, BANNER_HEX,
|
|
10564
|
+
var SECTIONS, BANNER_HEX, SETTINGS_SECTION, HELP;
|
|
10457
10565
|
var init_App = __esm({
|
|
10458
10566
|
"src/tui/App.tsx"() {
|
|
10459
10567
|
"use strict";
|
|
@@ -10466,7 +10574,6 @@ var init_App = __esm({
|
|
|
10466
10574
|
init_Dlp();
|
|
10467
10575
|
init_Audit();
|
|
10468
10576
|
init_Settings();
|
|
10469
|
-
init_Accounts();
|
|
10470
10577
|
init_hooks();
|
|
10471
10578
|
init_client();
|
|
10472
10579
|
init_api_client();
|
|
@@ -10477,11 +10584,10 @@ var init_App = __esm({
|
|
|
10477
10584
|
{ label: "Rate Limit", Panel: RateLimitPanel },
|
|
10478
10585
|
{ label: "DLP", Panel: DlpPanel },
|
|
10479
10586
|
{ label: "Audit", Panel: AuditPanel },
|
|
10480
|
-
{ label: "Settings", Panel: SettingsPanel }
|
|
10481
|
-
{ label: "Accounts", Panel: AccountsPanel }
|
|
10587
|
+
{ label: "Settings", Panel: SettingsPanel }
|
|
10482
10588
|
];
|
|
10483
10589
|
BANNER_HEX = ["white", "white", "white", "white", "white", "white"];
|
|
10484
|
-
|
|
10590
|
+
SETTINGS_SECTION = SECTIONS.findIndex((s) => s.label === "Settings");
|
|
10485
10591
|
HELP = [
|
|
10486
10592
|
["Global", [["\u2191\u2193", "move between sections"], ["\u2192 / enter", "open a section"], ["\u2190 / esc", "back to the menu"], ["?", "this help"], ["q", "quit"]]],
|
|
10487
10593
|
["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)"]]],
|
|
@@ -10499,11 +10605,11 @@ var tui_exports = {};
|
|
|
10499
10605
|
__export(tui_exports, {
|
|
10500
10606
|
launchTui: () => launchTui
|
|
10501
10607
|
});
|
|
10502
|
-
import { appendFileSync as appendFileSync2, mkdirSync as
|
|
10503
|
-
import { homedir as
|
|
10504
|
-
import { join as
|
|
10608
|
+
import { appendFileSync as appendFileSync2, mkdirSync as mkdirSync8 } from "fs";
|
|
10609
|
+
import { homedir as homedir9 } from "os";
|
|
10610
|
+
import { join as join11 } from "path";
|
|
10505
10611
|
import { render } from "ink";
|
|
10506
|
-
import { jsx as
|
|
10612
|
+
import { jsx as jsx9 } from "react/jsx-runtime";
|
|
10507
10613
|
async function launchTui() {
|
|
10508
10614
|
if (!process.stdout.isTTY || !process.stdin.isTTY) {
|
|
10509
10615
|
process.stderr.write(
|
|
@@ -10512,11 +10618,11 @@ async function launchTui() {
|
|
|
10512
10618
|
return;
|
|
10513
10619
|
}
|
|
10514
10620
|
process.stdout.write("\x1B[?1049h\x1B[H");
|
|
10515
|
-
const debugLog =
|
|
10621
|
+
const debugLog = join11(homedir9(), ".solongate", "dataroom-debug.log");
|
|
10516
10622
|
const saved = { log: console.log, warn: console.warn, error: console.error, info: console.info, debug: console.debug };
|
|
10517
10623
|
const toFile = (level) => (...args) => {
|
|
10518
10624
|
try {
|
|
10519
|
-
|
|
10625
|
+
mkdirSync8(join11(homedir9(), ".solongate"), { recursive: true });
|
|
10520
10626
|
appendFileSync2(debugLog, `${(/* @__PURE__ */ new Date()).toISOString()} [${level}] ${args.map((a) => typeof a === "string" ? a : JSON.stringify(a)).join(" ")}
|
|
10521
10627
|
`);
|
|
10522
10628
|
} catch {
|
|
@@ -10528,7 +10634,7 @@ async function launchTui() {
|
|
|
10528
10634
|
console.info = toFile("info");
|
|
10529
10635
|
console.debug = toFile("debug");
|
|
10530
10636
|
try {
|
|
10531
|
-
const { waitUntilExit } = render(/* @__PURE__ */
|
|
10637
|
+
const { waitUntilExit } = render(/* @__PURE__ */ jsx9(App, {}), { patchConsole: false });
|
|
10532
10638
|
await waitUntilExit();
|
|
10533
10639
|
} finally {
|
|
10534
10640
|
Object.assign(console, saved);
|
|
@@ -10640,7 +10746,7 @@ var init_args = __esm({
|
|
|
10640
10746
|
});
|
|
10641
10747
|
|
|
10642
10748
|
// src/commands/policy.ts
|
|
10643
|
-
import { readFileSync as
|
|
10749
|
+
import { readFileSync as readFileSync9 } from "fs";
|
|
10644
10750
|
async function run(argv) {
|
|
10645
10751
|
const { positionals, flags } = parse(argv);
|
|
10646
10752
|
const sub = positionals[0];
|
|
@@ -10815,7 +10921,7 @@ function printRules(rules) {
|
|
|
10815
10921
|
}
|
|
10816
10922
|
async function resolveRules(target) {
|
|
10817
10923
|
if (target.endsWith(".json")) {
|
|
10818
|
-
const parsed = JSON.parse(
|
|
10924
|
+
const parsed = JSON.parse(readFileSync9(target, "utf-8"));
|
|
10819
10925
|
return parsed.rules ?? [];
|
|
10820
10926
|
}
|
|
10821
10927
|
const p = await api.policies.get(target);
|
|
@@ -11231,8 +11337,8 @@ var init_agents2 = __esm({
|
|
|
11231
11337
|
|
|
11232
11338
|
// src/commands/doctor.ts
|
|
11233
11339
|
import { existsSync as existsSync4, statSync as statSync2 } from "fs";
|
|
11234
|
-
import { homedir as
|
|
11235
|
-
import { join as
|
|
11340
|
+
import { homedir as homedir10 } from "os";
|
|
11341
|
+
import { join as join12 } from "path";
|
|
11236
11342
|
async function run6(argv) {
|
|
11237
11343
|
const { flags } = parse(argv);
|
|
11238
11344
|
const json = flagBool(flags, "json");
|
|
@@ -11292,19 +11398,19 @@ var init_doctor = __esm({
|
|
|
11292
11398
|
init_api_client();
|
|
11293
11399
|
init_format();
|
|
11294
11400
|
init_args();
|
|
11295
|
-
LOCAL_LOG2 =
|
|
11401
|
+
LOCAL_LOG2 = join12(homedir10(), ".solongate", "local-logs", "solongate-audit.jsonl");
|
|
11296
11402
|
}
|
|
11297
11403
|
});
|
|
11298
11404
|
|
|
11299
11405
|
// src/commands/watch.ts
|
|
11300
|
-
import { closeSync as closeSync2, existsSync as existsSync5, openSync as
|
|
11301
|
-
import { homedir as
|
|
11302
|
-
import { join as
|
|
11406
|
+
import { closeSync as closeSync2, existsSync as existsSync5, openSync as openSync4, readSync as readSync2, statSync as statSync3 } from "fs";
|
|
11407
|
+
import { homedir as homedir11 } from "os";
|
|
11408
|
+
import { join as join13 } from "path";
|
|
11303
11409
|
function tailLocal(file, maxBytes = 131072) {
|
|
11304
11410
|
try {
|
|
11305
11411
|
const size = statSync3(file).size;
|
|
11306
11412
|
const start = Math.max(0, size - maxBytes);
|
|
11307
|
-
const fd =
|
|
11413
|
+
const fd = openSync4(file, "r");
|
|
11308
11414
|
const buf = Buffer.alloc(size - start);
|
|
11309
11415
|
readSync2(fd, buf, 0, buf.length, start);
|
|
11310
11416
|
closeSync2(fd);
|
|
@@ -11406,7 +11512,7 @@ var init_watch = __esm({
|
|
|
11406
11512
|
init_cli_utils();
|
|
11407
11513
|
init_args();
|
|
11408
11514
|
init_format();
|
|
11409
|
-
LOCAL_LOG3 =
|
|
11515
|
+
LOCAL_LOG3 = join13(homedir11(), ".solongate", "local-logs", "solongate-audit.jsonl");
|
|
11410
11516
|
trunc = (s, n) => s.length <= n ? s : s.slice(0, n - 1) + "\u2026";
|
|
11411
11517
|
time = (ms) => new Date(ms).toTimeString().slice(0, 8);
|
|
11412
11518
|
}
|
|
@@ -11697,10 +11803,10 @@ var init_commands = __esm({
|
|
|
11697
11803
|
});
|
|
11698
11804
|
|
|
11699
11805
|
// src/global-install.ts
|
|
11700
|
-
import { readFileSync as
|
|
11701
|
-
import { resolve as resolve4, join as
|
|
11702
|
-
import { homedir as
|
|
11703
|
-
import { fileURLToPath as
|
|
11806
|
+
import { readFileSync as readFileSync10, writeFileSync as writeFileSync9, existsSync as existsSync6, mkdirSync as mkdirSync9 } from "fs";
|
|
11807
|
+
import { resolve as resolve4, join as join14, dirname as dirname3 } from "path";
|
|
11808
|
+
import { homedir as homedir12 } from "os";
|
|
11809
|
+
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
11704
11810
|
import { createInterface } from "readline";
|
|
11705
11811
|
import { execFileSync as execFileSync2 } from "child_process";
|
|
11706
11812
|
function lockFile(file) {
|
|
@@ -11762,10 +11868,10 @@ function unlockFile(file) {
|
|
|
11762
11868
|
function protectedTargets() {
|
|
11763
11869
|
const p = globalPaths();
|
|
11764
11870
|
return [
|
|
11765
|
-
|
|
11766
|
-
|
|
11767
|
-
|
|
11768
|
-
|
|
11871
|
+
join14(p.hooksDir, "guard.mjs"),
|
|
11872
|
+
join14(p.hooksDir, "audit.mjs"),
|
|
11873
|
+
join14(p.hooksDir, "stop.mjs"),
|
|
11874
|
+
join14(p.hooksDir, "shield.mjs"),
|
|
11769
11875
|
p.configPath,
|
|
11770
11876
|
p.settingsPath
|
|
11771
11877
|
];
|
|
@@ -11777,26 +11883,26 @@ function unlockProtected() {
|
|
|
11777
11883
|
for (const f of protectedTargets()) unlockFile(f);
|
|
11778
11884
|
}
|
|
11779
11885
|
function globalPaths() {
|
|
11780
|
-
const home =
|
|
11781
|
-
const sgDir =
|
|
11782
|
-
const hooksDir =
|
|
11783
|
-
const claudeDir =
|
|
11886
|
+
const home = homedir12();
|
|
11887
|
+
const sgDir = join14(home, ".solongate");
|
|
11888
|
+
const hooksDir = join14(sgDir, "hooks");
|
|
11889
|
+
const claudeDir = join14(home, ".claude");
|
|
11784
11890
|
return {
|
|
11785
11891
|
home,
|
|
11786
11892
|
sgDir,
|
|
11787
11893
|
hooksDir,
|
|
11788
11894
|
claudeDir,
|
|
11789
|
-
settingsPath:
|
|
11790
|
-
backupPath:
|
|
11791
|
-
configPath:
|
|
11895
|
+
settingsPath: join14(claudeDir, "settings.json"),
|
|
11896
|
+
backupPath: join14(claudeDir, "settings.solongate.bak"),
|
|
11897
|
+
configPath: join14(sgDir, "cloud-guard.json")
|
|
11792
11898
|
};
|
|
11793
11899
|
}
|
|
11794
11900
|
function readHook(filename) {
|
|
11795
|
-
return
|
|
11901
|
+
return readFileSync10(join14(HOOKS_DIR, filename), "utf-8");
|
|
11796
11902
|
}
|
|
11797
11903
|
function readGuard() {
|
|
11798
|
-
const bundled =
|
|
11799
|
-
return existsSync6(bundled) ?
|
|
11904
|
+
const bundled = join14(HOOKS_DIR, "guard.bundled.mjs");
|
|
11905
|
+
return existsSync6(bundled) ? readFileSync10(bundled, "utf-8") : readHook("guard.mjs");
|
|
11800
11906
|
}
|
|
11801
11907
|
function ask(question) {
|
|
11802
11908
|
const rl = createInterface({ input: process.stdin, output: process.stderr });
|
|
@@ -11830,18 +11936,18 @@ function shimTargets() {
|
|
|
11830
11936
|
return [];
|
|
11831
11937
|
}
|
|
11832
11938
|
}
|
|
11833
|
-
return [".bashrc", ".zshrc", ".profile"].map((f) =>
|
|
11939
|
+
return [".bashrc", ".zshrc", ".profile"].map((f) => join14(homedir12(), f)).filter((f) => existsSync6(f));
|
|
11834
11940
|
}
|
|
11835
11941
|
function writeShimBlock(file, block2) {
|
|
11836
11942
|
const re = new RegExp(escapeRe(SHIM_BEGIN) + "[\\s\\S]*?" + escapeRe(SHIM_END) + "\\r?\\n?", "g");
|
|
11837
|
-
let content = existsSync6(file) ?
|
|
11943
|
+
let content = existsSync6(file) ? readFileSync10(file, "utf-8") : "";
|
|
11838
11944
|
content = content.replace(re, "");
|
|
11839
11945
|
if (block2) {
|
|
11840
11946
|
if (content.length && !content.endsWith("\n")) content += "\n";
|
|
11841
11947
|
content += block2 + "\n";
|
|
11842
11948
|
}
|
|
11843
|
-
|
|
11844
|
-
|
|
11949
|
+
mkdirSync9(dirname3(file), { recursive: true });
|
|
11950
|
+
writeFileSync9(file, content);
|
|
11845
11951
|
}
|
|
11846
11952
|
function installClaudeShim(shieldPath) {
|
|
11847
11953
|
const real = resolveRealClaude();
|
|
@@ -11871,7 +11977,7 @@ async function runGlobalInstall2(opts = {}) {
|
|
|
11871
11977
|
let apiKey = opts.apiKey || process.env["SOLONGATE_API_KEY"] || "";
|
|
11872
11978
|
if (!apiKey || apiKey === "sg_live_your_key_here") {
|
|
11873
11979
|
try {
|
|
11874
|
-
const cfg = JSON.parse(
|
|
11980
|
+
const cfg = JSON.parse(readFileSync10(p.configPath, "utf-8"));
|
|
11875
11981
|
if (cfg && typeof cfg.apiKey === "string") apiKey = cfg.apiKey;
|
|
11876
11982
|
} catch {
|
|
11877
11983
|
}
|
|
@@ -11884,22 +11990,22 @@ async function runGlobalInstall2(opts = {}) {
|
|
|
11884
11990
|
process.exit(1);
|
|
11885
11991
|
}
|
|
11886
11992
|
const apiUrl = opts.apiUrl || process.env["SOLONGATE_API_URL"] || "https://api.solongate.com";
|
|
11887
|
-
|
|
11888
|
-
|
|
11993
|
+
mkdirSync9(p.hooksDir, { recursive: true });
|
|
11994
|
+
mkdirSync9(p.claudeDir, { recursive: true });
|
|
11889
11995
|
unlockProtected();
|
|
11890
|
-
|
|
11891
|
-
|
|
11892
|
-
|
|
11893
|
-
|
|
11996
|
+
writeFileSync9(join14(p.hooksDir, "guard.mjs"), readGuard());
|
|
11997
|
+
writeFileSync9(join14(p.hooksDir, "audit.mjs"), readHook("audit.mjs"));
|
|
11998
|
+
writeFileSync9(join14(p.hooksDir, "stop.mjs"), readHook("stop.mjs"));
|
|
11999
|
+
writeFileSync9(join14(p.hooksDir, "shield.mjs"), readHook("shield.mjs"));
|
|
11894
12000
|
console.log(` Installed hooks \u2192 ${p.hooksDir}`);
|
|
11895
|
-
installClaudeShim(
|
|
11896
|
-
|
|
12001
|
+
installClaudeShim(join14(p.hooksDir, "shield.mjs"));
|
|
12002
|
+
writeFileSync9(p.configPath, JSON.stringify({ apiKey, apiUrl }, null, 2) + "\n");
|
|
11897
12003
|
console.log(` Wrote ${p.configPath}`);
|
|
11898
12004
|
let existing = {};
|
|
11899
12005
|
if (existsSync6(p.settingsPath)) {
|
|
11900
|
-
const raw =
|
|
12006
|
+
const raw = readFileSync10(p.settingsPath, "utf-8");
|
|
11901
12007
|
if (!existsSync6(p.backupPath)) {
|
|
11902
|
-
|
|
12008
|
+
writeFileSync9(p.backupPath, raw);
|
|
11903
12009
|
console.log(` Backed up existing settings \u2192 ${p.backupPath}`);
|
|
11904
12010
|
}
|
|
11905
12011
|
try {
|
|
@@ -11908,9 +12014,9 @@ async function runGlobalInstall2(opts = {}) {
|
|
|
11908
12014
|
existing = {};
|
|
11909
12015
|
}
|
|
11910
12016
|
}
|
|
11911
|
-
const guardAbs =
|
|
11912
|
-
const auditAbs =
|
|
11913
|
-
const stopAbs =
|
|
12017
|
+
const guardAbs = join14(p.hooksDir, "guard.mjs").replace(/\\/g, "/");
|
|
12018
|
+
const auditAbs = join14(p.hooksDir, "audit.mjs").replace(/\\/g, "/");
|
|
12019
|
+
const stopAbs = join14(p.hooksDir, "stop.mjs").replace(/\\/g, "/");
|
|
11914
12020
|
const nodeBin = process.execPath.replace(/\\/g, "/");
|
|
11915
12021
|
const call = process.platform === "win32" ? "& " : "";
|
|
11916
12022
|
const hookCmd = (script) => `${call}"${nodeBin}" "${script}" claude-code "Claude Code"`;
|
|
@@ -11922,7 +12028,7 @@ async function runGlobalInstall2(opts = {}) {
|
|
|
11922
12028
|
Stop: [{ matcher: "", hooks: [{ type: "command", command: hookCmd(stopAbs) }] }]
|
|
11923
12029
|
}
|
|
11924
12030
|
};
|
|
11925
|
-
|
|
12031
|
+
writeFileSync9(p.settingsPath, JSON.stringify(merged, null, 2) + "\n");
|
|
11926
12032
|
console.log(` Registered global hooks \u2192 ${p.settingsPath}`);
|
|
11927
12033
|
if (process.env["SOLONGATE_OS_LOCK"] === "1") {
|
|
11928
12034
|
lockProtected();
|
|
@@ -11933,7 +12039,7 @@ var __dirname, HOOKS_DIR, SHIM_BEGIN, SHIM_END;
|
|
|
11933
12039
|
var init_global_install = __esm({
|
|
11934
12040
|
"src/global-install.ts"() {
|
|
11935
12041
|
"use strict";
|
|
11936
|
-
__dirname =
|
|
12042
|
+
__dirname = dirname3(fileURLToPath3(import.meta.url));
|
|
11937
12043
|
HOOKS_DIR = resolve4(__dirname, "..", "hooks");
|
|
11938
12044
|
SHIM_BEGIN = "# >>> SolonGate shield (auto secret redaction) >>>";
|
|
11939
12045
|
SHIM_END = "# <<< SolonGate shield <<<";
|
|
@@ -11942,7 +12048,7 @@ var init_global_install = __esm({
|
|
|
11942
12048
|
|
|
11943
12049
|
// src/login.ts
|
|
11944
12050
|
var login_exports = {};
|
|
11945
|
-
import { spawn as
|
|
12051
|
+
import { spawn as spawn5 } from "child_process";
|
|
11946
12052
|
function startSpinner(text) {
|
|
11947
12053
|
if (!process.stderr.isTTY) {
|
|
11948
12054
|
process.stderr.write(` ${text}
|
|
@@ -11978,7 +12084,7 @@ function openBrowser2(url) {
|
|
|
11978
12084
|
try {
|
|
11979
12085
|
const cmd = process.platform === "win32" ? "cmd" : process.platform === "darwin" ? "open" : "xdg-open";
|
|
11980
12086
|
const args = process.platform === "win32" ? ["/c", "start", '""', url] : [url];
|
|
11981
|
-
const child =
|
|
12087
|
+
const child = spawn5(cmd, args, { stdio: "ignore", detached: true });
|
|
11982
12088
|
child.on("error", () => {
|
|
11983
12089
|
});
|
|
11984
12090
|
child.unref();
|
|
@@ -12098,13 +12204,13 @@ __export(shield_exports, {
|
|
|
12098
12204
|
});
|
|
12099
12205
|
import { createServer, request as httpRequest } from "http";
|
|
12100
12206
|
import { request as httpsRequest } from "https";
|
|
12101
|
-
import { spawn as
|
|
12207
|
+
import { spawn as spawn6 } from "child_process";
|
|
12102
12208
|
import { URL as URL2 } from "url";
|
|
12103
|
-
import { readFileSync as
|
|
12209
|
+
import { readFileSync as readFileSync11, existsSync as existsSync7, readdirSync, statSync as statSync4 } from "fs";
|
|
12104
12210
|
import { resolve as resolve5 } from "path";
|
|
12105
|
-
import { homedir as
|
|
12211
|
+
import { homedir as homedir13 } from "os";
|
|
12106
12212
|
function findCacheFile() {
|
|
12107
|
-
const dir = resolve5(
|
|
12213
|
+
const dir = resolve5(homedir13(), ".solongate");
|
|
12108
12214
|
const envSel = process.env.SOLONGATE_AGENT_ID;
|
|
12109
12215
|
if (envSel) {
|
|
12110
12216
|
const f = resolve5(dir, ".policy-cache-" + envSel.replace(/[^a-zA-Z0-9_-]/g, "_") + ".json");
|
|
@@ -12130,7 +12236,7 @@ function loadCfg() {
|
|
|
12130
12236
|
try {
|
|
12131
12237
|
const f = findCacheFile();
|
|
12132
12238
|
if (f && existsSync7(f)) {
|
|
12133
|
-
const c2 = JSON.parse(
|
|
12239
|
+
const c2 = JSON.parse(readFileSync11(f, "utf-8"));
|
|
12134
12240
|
const d = c2?.security?.dlpRedact;
|
|
12135
12241
|
const g = c2?.security?.ghost;
|
|
12136
12242
|
const ghost = g && Array.isArray(g.patterns) ? g.patterns : [];
|
|
@@ -12358,7 +12464,7 @@ async function runShield() {
|
|
|
12358
12464
|
const upstream = pickUpstream();
|
|
12359
12465
|
const { port, close } = await startProxy(upstream);
|
|
12360
12466
|
log4(`redacting secrets on the LLM path \u2192 masking before ${upstream.host} (127.0.0.1:${port})`);
|
|
12361
|
-
const child =
|
|
12467
|
+
const child = spawn6(cmd[0], cmd.slice(1), {
|
|
12362
12468
|
stdio: "inherit",
|
|
12363
12469
|
env: { ...process.env, ANTHROPIC_BASE_URL: `http://127.0.0.1:${port}` },
|
|
12364
12470
|
shell: process.platform === "win32"
|
|
@@ -12418,9 +12524,9 @@ __export(logs_server_exports, {
|
|
|
12418
12524
|
runLogsServer: () => runLogsServer
|
|
12419
12525
|
});
|
|
12420
12526
|
import { createServer as createServer2 } from "http";
|
|
12421
|
-
import { readFileSync as
|
|
12422
|
-
import { resolve as resolve6, join as
|
|
12423
|
-
import { homedir as
|
|
12527
|
+
import { readFileSync as readFileSync12, statSync as statSync5 } from "fs";
|
|
12528
|
+
import { resolve as resolve6, join as join15, isAbsolute } from "path";
|
|
12529
|
+
import { homedir as homedir14 } from "os";
|
|
12424
12530
|
import { readdirSync as readdirSync2 } from "fs";
|
|
12425
12531
|
function allowedOrigins() {
|
|
12426
12532
|
const base = [
|
|
@@ -12437,15 +12543,15 @@ function resolveLocalLogDir(rawPath) {
|
|
|
12437
12543
|
const dir = String(rawPath || "").trim().replace(/[\\/]+$/, "");
|
|
12438
12544
|
if (!dir) return null;
|
|
12439
12545
|
if (isAbsolute(dir)) return dir;
|
|
12440
|
-
return resolve6(
|
|
12546
|
+
return resolve6(homedir14(), ".solongate", "local-logs");
|
|
12441
12547
|
}
|
|
12442
12548
|
async function findLogDir() {
|
|
12443
|
-
const base = resolve6(
|
|
12549
|
+
const base = resolve6(homedir14(), ".solongate");
|
|
12444
12550
|
try {
|
|
12445
12551
|
const files = readdirSync2(base).filter((f) => f.startsWith(".policy-cache-") && f.endsWith(".json"));
|
|
12446
12552
|
for (const f of files) {
|
|
12447
12553
|
try {
|
|
12448
|
-
const c2 = JSON.parse(
|
|
12554
|
+
const c2 = JSON.parse(readFileSync12(join15(base, f), "utf-8"));
|
|
12449
12555
|
const p = c2?.security?.localLogs?.path;
|
|
12450
12556
|
if (typeof p === "string" && p.trim()) return { dir: resolveLocalLogDir(p), configured: p };
|
|
12451
12557
|
} catch {
|
|
@@ -12454,7 +12560,7 @@ async function findLogDir() {
|
|
|
12454
12560
|
} catch {
|
|
12455
12561
|
}
|
|
12456
12562
|
try {
|
|
12457
|
-
const cfgRaw =
|
|
12563
|
+
const cfgRaw = readFileSync12(join15(base, "cloud-guard.json"), "utf-8");
|
|
12458
12564
|
const { apiKey, apiUrl } = JSON.parse(cfgRaw);
|
|
12459
12565
|
if (apiKey) {
|
|
12460
12566
|
const url = `${apiUrl || "https://api.solongate.com"}/api/v1/policies/active`;
|
|
@@ -12483,7 +12589,7 @@ function setCors(req, res) {
|
|
|
12483
12589
|
}
|
|
12484
12590
|
function fileInfo(dir) {
|
|
12485
12591
|
if (!dir) return { file: null, exists: false, size: 0, mtimeMs: 0 };
|
|
12486
|
-
const file =
|
|
12592
|
+
const file = join15(dir, LOG_FILENAME);
|
|
12487
12593
|
try {
|
|
12488
12594
|
const st = statSync5(file);
|
|
12489
12595
|
return { file, exists: true, size: st.size, mtimeMs: st.mtimeMs };
|
|
@@ -12544,7 +12650,7 @@ async function runLogsServer() {
|
|
|
12544
12650
|
return;
|
|
12545
12651
|
}
|
|
12546
12652
|
try {
|
|
12547
|
-
const text =
|
|
12653
|
+
const text = readFileSync12(info.file, "utf-8");
|
|
12548
12654
|
res.writeHead(200, { "Content-Type": "text/plain; charset=utf-8", "Last-Modified": lastMod, "X-Solongate-Exists": "1" });
|
|
12549
12655
|
res.end(text);
|
|
12550
12656
|
} catch {
|
|
@@ -12557,6 +12663,8 @@ async function runLogsServer() {
|
|
|
12557
12663
|
res.end("not found");
|
|
12558
12664
|
});
|
|
12559
12665
|
server.listen(port, "127.0.0.1", async () => {
|
|
12666
|
+
const { recordLogsServerStarted: recordLogsServerStarted2 } = await Promise.resolve().then(() => (init_logs_server_daemon(), logs_server_daemon_exports));
|
|
12667
|
+
recordLogsServerStarted2(port);
|
|
12560
12668
|
const { dir, configured } = await findLogDir();
|
|
12561
12669
|
process.stdout.write(`[SolonGate] Local logs agent listening on http://127.0.0.1:${port}
|
|
12562
12670
|
`);
|
|
@@ -12596,7 +12704,7 @@ var init_logs_server = __esm({
|
|
|
12596
12704
|
|
|
12597
12705
|
// src/inject.ts
|
|
12598
12706
|
var inject_exports = {};
|
|
12599
|
-
import { readFileSync as
|
|
12707
|
+
import { readFileSync as readFileSync13, writeFileSync as writeFileSync10, existsSync as existsSync8, copyFileSync } from "fs";
|
|
12600
12708
|
import { resolve as resolve7 } from "path";
|
|
12601
12709
|
import { execSync } from "child_process";
|
|
12602
12710
|
function parseInjectArgs(argv) {
|
|
@@ -12656,7 +12764,7 @@ WHAT IT DOES
|
|
|
12656
12764
|
function detectProject() {
|
|
12657
12765
|
if (!existsSync8(resolve7("package.json"))) return false;
|
|
12658
12766
|
try {
|
|
12659
|
-
const pkg = JSON.parse(
|
|
12767
|
+
const pkg = JSON.parse(readFileSync13(resolve7("package.json"), "utf-8"));
|
|
12660
12768
|
const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
12661
12769
|
return !!(allDeps["@modelcontextprotocol/sdk"] || allDeps["@modelcontextprotocol/server"]);
|
|
12662
12770
|
} catch {
|
|
@@ -12665,7 +12773,7 @@ function detectProject() {
|
|
|
12665
12773
|
}
|
|
12666
12774
|
function findTsEntryFile() {
|
|
12667
12775
|
try {
|
|
12668
|
-
const pkg = JSON.parse(
|
|
12776
|
+
const pkg = JSON.parse(readFileSync13(resolve7("package.json"), "utf-8"));
|
|
12669
12777
|
if (pkg.bin) {
|
|
12670
12778
|
const binPath = typeof pkg.bin === "string" ? pkg.bin : Object.values(pkg.bin)[0];
|
|
12671
12779
|
if (typeof binPath === "string") {
|
|
@@ -12692,7 +12800,7 @@ function findTsEntryFile() {
|
|
|
12692
12800
|
const full = resolve7(c2);
|
|
12693
12801
|
if (existsSync8(full)) {
|
|
12694
12802
|
try {
|
|
12695
|
-
const content =
|
|
12803
|
+
const content = readFileSync13(full, "utf-8");
|
|
12696
12804
|
if (content.includes("McpServer") || content.includes("McpServer")) {
|
|
12697
12805
|
return full;
|
|
12698
12806
|
}
|
|
@@ -12712,7 +12820,7 @@ function detectPackageManager() {
|
|
|
12712
12820
|
}
|
|
12713
12821
|
function installSdk() {
|
|
12714
12822
|
try {
|
|
12715
|
-
const pkg = JSON.parse(
|
|
12823
|
+
const pkg = JSON.parse(readFileSync13(resolve7("package.json"), "utf-8"));
|
|
12716
12824
|
const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
12717
12825
|
if (allDeps["@solongate/proxy"]) {
|
|
12718
12826
|
log3(" @solongate/proxy already installed");
|
|
@@ -12733,7 +12841,7 @@ function installSdk() {
|
|
|
12733
12841
|
}
|
|
12734
12842
|
}
|
|
12735
12843
|
function injectTypeScript(filePath) {
|
|
12736
|
-
const original =
|
|
12844
|
+
const original = readFileSync13(filePath, "utf-8");
|
|
12737
12845
|
const changes = [];
|
|
12738
12846
|
let modified = original;
|
|
12739
12847
|
if (modified.includes("SecureMcpServer")) {
|
|
@@ -12904,7 +13012,7 @@ async function main2() {
|
|
|
12904
13012
|
log3("");
|
|
12905
13013
|
log3(` Backup: ${backupPath}`);
|
|
12906
13014
|
}
|
|
12907
|
-
|
|
13015
|
+
writeFileSync10(entryFile, result.modified);
|
|
12908
13016
|
log3("");
|
|
12909
13017
|
log3(" \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510");
|
|
12910
13018
|
log3(" \u2502 SolonGate SDK injected successfully! \u2502");
|
|
@@ -12933,8 +13041,8 @@ var init_inject = __esm({
|
|
|
12933
13041
|
|
|
12934
13042
|
// src/create.ts
|
|
12935
13043
|
var create_exports = {};
|
|
12936
|
-
import { mkdirSync as
|
|
12937
|
-
import { resolve as resolve8, join as
|
|
13044
|
+
import { mkdirSync as mkdirSync10, writeFileSync as writeFileSync11, existsSync as existsSync9 } from "fs";
|
|
13045
|
+
import { resolve as resolve8, join as join16 } from "path";
|
|
12938
13046
|
import { execSync as execSync2 } from "child_process";
|
|
12939
13047
|
function withSpinner(message, fn) {
|
|
12940
13048
|
const frames = ["\u28FE", "\u28FD", "\u28FB", "\u28BF", "\u287F", "\u28DF", "\u28EF", "\u28F7"];
|
|
@@ -13013,8 +13121,8 @@ EXAMPLES
|
|
|
13013
13121
|
`);
|
|
13014
13122
|
}
|
|
13015
13123
|
function createProject(dir, name, _policy) {
|
|
13016
|
-
|
|
13017
|
-
|
|
13124
|
+
writeFileSync11(
|
|
13125
|
+
join16(dir, "package.json"),
|
|
13018
13126
|
JSON.stringify(
|
|
13019
13127
|
{
|
|
13020
13128
|
name,
|
|
@@ -13043,8 +13151,8 @@ function createProject(dir, name, _policy) {
|
|
|
13043
13151
|
2
|
|
13044
13152
|
) + "\n"
|
|
13045
13153
|
);
|
|
13046
|
-
|
|
13047
|
-
|
|
13154
|
+
writeFileSync11(
|
|
13155
|
+
join16(dir, "tsconfig.json"),
|
|
13048
13156
|
JSON.stringify(
|
|
13049
13157
|
{
|
|
13050
13158
|
compilerOptions: {
|
|
@@ -13064,9 +13172,9 @@ function createProject(dir, name, _policy) {
|
|
|
13064
13172
|
2
|
|
13065
13173
|
) + "\n"
|
|
13066
13174
|
);
|
|
13067
|
-
|
|
13068
|
-
|
|
13069
|
-
|
|
13175
|
+
mkdirSync10(join16(dir, "src"), { recursive: true });
|
|
13176
|
+
writeFileSync11(
|
|
13177
|
+
join16(dir, "src", "index.ts"),
|
|
13070
13178
|
`#!/usr/bin/env node
|
|
13071
13179
|
|
|
13072
13180
|
console.log = (...args: unknown[]) => {
|
|
@@ -13107,8 +13215,8 @@ console.log('');
|
|
|
13107
13215
|
console.log('Press Ctrl+C to stop.');
|
|
13108
13216
|
`
|
|
13109
13217
|
);
|
|
13110
|
-
|
|
13111
|
-
|
|
13218
|
+
writeFileSync11(
|
|
13219
|
+
join16(dir, ".mcp.json"),
|
|
13112
13220
|
JSON.stringify(
|
|
13113
13221
|
{
|
|
13114
13222
|
mcpServers: {
|
|
@@ -13125,13 +13233,13 @@ console.log('Press Ctrl+C to stop.');
|
|
|
13125
13233
|
2
|
|
13126
13234
|
) + "\n"
|
|
13127
13235
|
);
|
|
13128
|
-
|
|
13129
|
-
|
|
13236
|
+
writeFileSync11(
|
|
13237
|
+
join16(dir, ".env"),
|
|
13130
13238
|
`SOLONGATE_API_KEY=sg_live_YOUR_KEY_HERE
|
|
13131
13239
|
`
|
|
13132
13240
|
);
|
|
13133
|
-
|
|
13134
|
-
|
|
13241
|
+
writeFileSync11(
|
|
13242
|
+
join16(dir, ".gitignore"),
|
|
13135
13243
|
`node_modules/
|
|
13136
13244
|
dist/
|
|
13137
13245
|
*.solongate-backup
|
|
@@ -13150,7 +13258,7 @@ async function main3() {
|
|
|
13150
13258
|
process.exit(1);
|
|
13151
13259
|
}
|
|
13152
13260
|
withSpinner(`Setting up ${opts.name}...`, () => {
|
|
13153
|
-
|
|
13261
|
+
mkdirSync10(dir, { recursive: true });
|
|
13154
13262
|
createProject(dir, opts.name, opts.policy);
|
|
13155
13263
|
});
|
|
13156
13264
|
if (!opts.noInstall) {
|
|
@@ -13224,14 +13332,14 @@ var init_create = __esm({
|
|
|
13224
13332
|
|
|
13225
13333
|
// src/pull-push.ts
|
|
13226
13334
|
var pull_push_exports = {};
|
|
13227
|
-
import { readFileSync as
|
|
13335
|
+
import { readFileSync as readFileSync14, writeFileSync as writeFileSync12, existsSync as existsSync10 } from "fs";
|
|
13228
13336
|
import { resolve as resolve9 } from "path";
|
|
13229
13337
|
function loadEnv() {
|
|
13230
13338
|
if (process.env.SOLONGATE_API_KEY) return;
|
|
13231
13339
|
const envPath = resolve9(".env");
|
|
13232
13340
|
if (!existsSync10(envPath)) return;
|
|
13233
13341
|
try {
|
|
13234
|
-
const content =
|
|
13342
|
+
const content = readFileSync14(envPath, "utf-8");
|
|
13235
13343
|
for (const line of content.split("\n")) {
|
|
13236
13344
|
const trimmed = line.trim();
|
|
13237
13345
|
if (!trimmed || trimmed.startsWith("#")) continue;
|
|
@@ -13419,7 +13527,7 @@ async function pull(apiKey, file, policyId) {
|
|
|
13419
13527
|
const policy = await fetchCloudPolicy(apiKey, API_URL, policyId);
|
|
13420
13528
|
const { id: _id, ...policyWithoutId } = policy;
|
|
13421
13529
|
const json = JSON.stringify(policyWithoutId, null, 2) + "\n";
|
|
13422
|
-
|
|
13530
|
+
writeFileSync12(file, json, "utf-8");
|
|
13423
13531
|
log5("");
|
|
13424
13532
|
log5(green2(" Saved to: ") + file);
|
|
13425
13533
|
log5(` ${dim2("Name:")} ${policy.name}`);
|
|
@@ -13448,7 +13556,7 @@ async function push(apiKey, file, policyId) {
|
|
|
13448
13556
|
log5(" solongate-proxy list");
|
|
13449
13557
|
process.exit(1);
|
|
13450
13558
|
}
|
|
13451
|
-
const content =
|
|
13559
|
+
const content = readFileSync14(file, "utf-8");
|
|
13452
13560
|
let policy;
|
|
13453
13561
|
try {
|
|
13454
13562
|
policy = JSON.parse(content);
|
|
@@ -16604,6 +16712,10 @@ async function main5() {
|
|
|
16604
16712
|
const { maybeSelfUpdate: maybeSelfUpdate2 } = await Promise.resolve().then(() => (init_self_update(), self_update_exports));
|
|
16605
16713
|
maybeSelfUpdate2();
|
|
16606
16714
|
}
|
|
16715
|
+
if (subcommand !== "logs-server" && subcommand !== "local-logs") {
|
|
16716
|
+
const { ensureLogsServerDaemon: ensureLogsServerDaemon2 } = await Promise.resolve().then(() => (init_logs_server_daemon(), logs_server_daemon_exports));
|
|
16717
|
+
ensureLogsServerDaemon2();
|
|
16718
|
+
}
|
|
16607
16719
|
}
|
|
16608
16720
|
if (process.argv.length <= 2) {
|
|
16609
16721
|
if (process.stdout.isTTY && process.stdin.isTTY) {
|