@solongate/proxy 0.82.42 → 0.82.43
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 +583 -385
- package/dist/self-update.d.ts +7 -0
- package/dist/tui/index.js +930 -919
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -6187,6 +6187,476 @@ var init_cli_utils = __esm({
|
|
|
6187
6187
|
}
|
|
6188
6188
|
});
|
|
6189
6189
|
|
|
6190
|
+
// src/global-install.ts
|
|
6191
|
+
var global_install_exports = {};
|
|
6192
|
+
__export(global_install_exports, {
|
|
6193
|
+
clearGuardUpdateCheck: () => clearGuardUpdateCheck,
|
|
6194
|
+
globalPaths: () => globalPaths,
|
|
6195
|
+
guardHookOutdated: () => guardHookOutdated,
|
|
6196
|
+
installClaudeShim: () => installClaudeShim,
|
|
6197
|
+
installGlobalQuiet: () => installGlobalQuiet,
|
|
6198
|
+
installGlobalWithKey: () => installGlobalWithKey,
|
|
6199
|
+
installedGuardVersion: () => installedGuardVersion,
|
|
6200
|
+
isGuardInstalled: () => isGuardInstalled,
|
|
6201
|
+
lockProtected: () => lockProtected,
|
|
6202
|
+
removeClaudeShim: () => removeClaudeShim,
|
|
6203
|
+
runGlobalInstall: () => runGlobalInstall,
|
|
6204
|
+
runGlobalRestore: () => runGlobalRestore,
|
|
6205
|
+
uninstallGlobalQuiet: () => uninstallGlobalQuiet,
|
|
6206
|
+
unlockProtected: () => unlockProtected
|
|
6207
|
+
});
|
|
6208
|
+
import { readFileSync as readFileSync4, writeFileSync as writeFileSync3, existsSync as existsSync3, mkdirSync as mkdirSync3, rmSync as rmSync2 } from "fs";
|
|
6209
|
+
import { resolve as resolve3, join as join4, dirname } from "path";
|
|
6210
|
+
import { homedir as homedir2 } from "os";
|
|
6211
|
+
import { fileURLToPath } from "url";
|
|
6212
|
+
import { createInterface } from "readline";
|
|
6213
|
+
import { execFileSync as execFileSync2 } from "child_process";
|
|
6214
|
+
function lockFile(file) {
|
|
6215
|
+
if (!existsSync3(file)) return;
|
|
6216
|
+
try {
|
|
6217
|
+
if (process.platform === "win32") {
|
|
6218
|
+
try {
|
|
6219
|
+
execFileSync2("icacls", [file, "/deny", "*S-1-1-0:(WD,AD,DC,DE)"], { stdio: "ignore" });
|
|
6220
|
+
} catch {
|
|
6221
|
+
}
|
|
6222
|
+
try {
|
|
6223
|
+
execFileSync2("attrib", ["+R", file], { stdio: "ignore" });
|
|
6224
|
+
} catch {
|
|
6225
|
+
}
|
|
6226
|
+
} else if (process.platform === "darwin") {
|
|
6227
|
+
try {
|
|
6228
|
+
execFileSync2("chflags", ["uchg", file], { stdio: "ignore" });
|
|
6229
|
+
} catch {
|
|
6230
|
+
}
|
|
6231
|
+
} else {
|
|
6232
|
+
try {
|
|
6233
|
+
execFileSync2("chattr", ["+i", file], { stdio: "ignore" });
|
|
6234
|
+
} catch {
|
|
6235
|
+
}
|
|
6236
|
+
}
|
|
6237
|
+
} catch {
|
|
6238
|
+
}
|
|
6239
|
+
}
|
|
6240
|
+
function unlockFile(file) {
|
|
6241
|
+
if (!existsSync3(file)) return;
|
|
6242
|
+
try {
|
|
6243
|
+
if (process.platform === "win32") {
|
|
6244
|
+
try {
|
|
6245
|
+
execFileSync2("icacls", [file, "/remove:d", "*S-1-1-0"], { stdio: "ignore" });
|
|
6246
|
+
} catch {
|
|
6247
|
+
}
|
|
6248
|
+
try {
|
|
6249
|
+
execFileSync2("icacls", [file, "/reset"], { stdio: "ignore" });
|
|
6250
|
+
} catch {
|
|
6251
|
+
}
|
|
6252
|
+
try {
|
|
6253
|
+
execFileSync2("attrib", ["-R", file], { stdio: "ignore" });
|
|
6254
|
+
} catch {
|
|
6255
|
+
}
|
|
6256
|
+
} else if (process.platform === "darwin") {
|
|
6257
|
+
try {
|
|
6258
|
+
execFileSync2("chflags", ["nouchg", file], { stdio: "ignore" });
|
|
6259
|
+
} catch {
|
|
6260
|
+
}
|
|
6261
|
+
} else {
|
|
6262
|
+
try {
|
|
6263
|
+
execFileSync2("chattr", ["-i", file], { stdio: "ignore" });
|
|
6264
|
+
} catch {
|
|
6265
|
+
}
|
|
6266
|
+
}
|
|
6267
|
+
} catch {
|
|
6268
|
+
}
|
|
6269
|
+
}
|
|
6270
|
+
function protectedTargets() {
|
|
6271
|
+
const p = globalPaths();
|
|
6272
|
+
return [
|
|
6273
|
+
join4(p.hooksDir, "guard.mjs"),
|
|
6274
|
+
join4(p.hooksDir, "audit.mjs"),
|
|
6275
|
+
join4(p.hooksDir, "stop.mjs"),
|
|
6276
|
+
join4(p.hooksDir, "shield.mjs"),
|
|
6277
|
+
p.configPath,
|
|
6278
|
+
p.settingsPath,
|
|
6279
|
+
p.antigravityHooksPath
|
|
6280
|
+
];
|
|
6281
|
+
}
|
|
6282
|
+
function lockProtected() {
|
|
6283
|
+
for (const f of protectedTargets()) lockFile(f);
|
|
6284
|
+
}
|
|
6285
|
+
function unlockProtected() {
|
|
6286
|
+
for (const f of protectedTargets()) unlockFile(f);
|
|
6287
|
+
}
|
|
6288
|
+
function globalPaths() {
|
|
6289
|
+
const home = homedir2();
|
|
6290
|
+
const sgDir = join4(home, ".solongate");
|
|
6291
|
+
const hooksDir = join4(sgDir, "hooks");
|
|
6292
|
+
const claudeDir = join4(home, ".claude");
|
|
6293
|
+
const antigravityDir = join4(home, ".gemini", "config");
|
|
6294
|
+
return {
|
|
6295
|
+
home,
|
|
6296
|
+
sgDir,
|
|
6297
|
+
hooksDir,
|
|
6298
|
+
claudeDir,
|
|
6299
|
+
antigravityDir,
|
|
6300
|
+
settingsPath: join4(claudeDir, "settings.json"),
|
|
6301
|
+
backupPath: join4(claudeDir, "settings.solongate.bak"),
|
|
6302
|
+
configPath: join4(sgDir, "cloud-guard.json"),
|
|
6303
|
+
// Antigravity reads global hooks from ~/.gemini/config/hooks.json. Only the
|
|
6304
|
+
// guard is registered there (PreToolUse); Antigravity's ALLOW-path audit is
|
|
6305
|
+
// covered by the passive session-log collector, not a hook.
|
|
6306
|
+
antigravityHooksPath: join4(antigravityDir, "hooks.json"),
|
|
6307
|
+
antigravityBackupPath: join4(antigravityDir, "hooks.solongate.bak")
|
|
6308
|
+
};
|
|
6309
|
+
}
|
|
6310
|
+
function clearGuardUpdateCheck() {
|
|
6311
|
+
try {
|
|
6312
|
+
rmSync2(join4(globalPaths().sgDir, ".hook-update-check"), { force: true });
|
|
6313
|
+
return true;
|
|
6314
|
+
} catch {
|
|
6315
|
+
return false;
|
|
6316
|
+
}
|
|
6317
|
+
}
|
|
6318
|
+
function readHook(filename) {
|
|
6319
|
+
return readFileSync4(join4(HOOKS_DIR, filename), "utf-8");
|
|
6320
|
+
}
|
|
6321
|
+
function firstAccountCredential() {
|
|
6322
|
+
try {
|
|
6323
|
+
const raw = JSON.parse(readFileSync4(join4(homedir2(), ".solongate", "accounts.json"), "utf-8"));
|
|
6324
|
+
if (Array.isArray(raw)) {
|
|
6325
|
+
const acc = raw.find((a) => a && typeof a.apiKey === "string" && a.apiKey);
|
|
6326
|
+
if (acc) return { apiKey: acc.apiKey, apiUrl: typeof acc.apiUrl === "string" ? acc.apiUrl : void 0 };
|
|
6327
|
+
}
|
|
6328
|
+
} catch {
|
|
6329
|
+
}
|
|
6330
|
+
return {};
|
|
6331
|
+
}
|
|
6332
|
+
function readGuard() {
|
|
6333
|
+
const bundled = join4(HOOKS_DIR, "guard.bundled.mjs");
|
|
6334
|
+
return existsSync3(bundled) ? readFileSync4(bundled, "utf-8") : readHook("guard.mjs");
|
|
6335
|
+
}
|
|
6336
|
+
function antigravityHookCommand(guardAbs) {
|
|
6337
|
+
const nodeBin = process.execPath.replace(/\\/g, "/");
|
|
6338
|
+
const call = process.platform === "win32" ? "& " : "";
|
|
6339
|
+
return `${call}"${nodeBin}" "${guardAbs.replace(/\\/g, "/")}" antigravity "Antigravity"`;
|
|
6340
|
+
}
|
|
6341
|
+
function installAntigravityGuard(p, guardAbs) {
|
|
6342
|
+
mkdirSync3(p.antigravityDir, { recursive: true });
|
|
6343
|
+
let existing = {};
|
|
6344
|
+
if (existsSync3(p.antigravityHooksPath)) {
|
|
6345
|
+
const raw = readFileSync4(p.antigravityHooksPath, "utf-8");
|
|
6346
|
+
if (!existsSync3(p.antigravityBackupPath)) writeFileSync3(p.antigravityBackupPath, raw);
|
|
6347
|
+
try {
|
|
6348
|
+
existing = JSON.parse(raw);
|
|
6349
|
+
} catch {
|
|
6350
|
+
existing = {};
|
|
6351
|
+
}
|
|
6352
|
+
}
|
|
6353
|
+
const merged = {
|
|
6354
|
+
...existing,
|
|
6355
|
+
[ANTIGRAVITY_GROUP]: {
|
|
6356
|
+
PreToolUse: [{ matcher: "", hooks: [{ type: "command", command: antigravityHookCommand(guardAbs) }] }]
|
|
6357
|
+
}
|
|
6358
|
+
};
|
|
6359
|
+
writeFileSync3(p.antigravityHooksPath, JSON.stringify(merged, null, 2) + "\n");
|
|
6360
|
+
}
|
|
6361
|
+
function removeAntigravityGuard(p) {
|
|
6362
|
+
if (!existsSync3(p.antigravityHooksPath)) return;
|
|
6363
|
+
try {
|
|
6364
|
+
const s = JSON.parse(readFileSync4(p.antigravityHooksPath, "utf-8"));
|
|
6365
|
+
if (!(ANTIGRAVITY_GROUP in s)) return;
|
|
6366
|
+
delete s[ANTIGRAVITY_GROUP];
|
|
6367
|
+
writeFileSync3(p.antigravityHooksPath, JSON.stringify(s, null, 2) + "\n");
|
|
6368
|
+
} catch {
|
|
6369
|
+
}
|
|
6370
|
+
}
|
|
6371
|
+
function ask(question) {
|
|
6372
|
+
const rl = createInterface({ input: process.stdin, output: process.stderr });
|
|
6373
|
+
return new Promise((res) => rl.question(question, (a) => {
|
|
6374
|
+
rl.close();
|
|
6375
|
+
res(a.trim());
|
|
6376
|
+
}));
|
|
6377
|
+
}
|
|
6378
|
+
function runGlobalRestore() {
|
|
6379
|
+
const p = globalPaths();
|
|
6380
|
+
unlockProtected();
|
|
6381
|
+
removeClaudeShim();
|
|
6382
|
+
removeAntigravityGuard(p);
|
|
6383
|
+
if (existsSync3(p.backupPath)) {
|
|
6384
|
+
writeFileSync3(p.settingsPath, readFileSync4(p.backupPath, "utf-8"));
|
|
6385
|
+
console.log(` Restored ${p.settingsPath} from backup.`);
|
|
6386
|
+
} else if (existsSync3(p.settingsPath)) {
|
|
6387
|
+
try {
|
|
6388
|
+
const s = JSON.parse(readFileSync4(p.settingsPath, "utf-8"));
|
|
6389
|
+
delete s.hooks;
|
|
6390
|
+
writeFileSync3(p.settingsPath, JSON.stringify(s, null, 2) + "\n");
|
|
6391
|
+
console.log(` Removed SolonGate hooks from ${p.settingsPath}.`);
|
|
6392
|
+
} catch {
|
|
6393
|
+
}
|
|
6394
|
+
} else {
|
|
6395
|
+
console.log(" Nothing to restore \u2014 no global Claude Code settings found.");
|
|
6396
|
+
}
|
|
6397
|
+
console.log(" Global SolonGate enforcement uninstalled. Restart Claude Code.");
|
|
6398
|
+
}
|
|
6399
|
+
function installGlobalQuiet() {
|
|
6400
|
+
try {
|
|
6401
|
+
const p = globalPaths();
|
|
6402
|
+
let apiKey = process.env["SOLONGATE_API_KEY"] || "";
|
|
6403
|
+
let apiUrl = process.env["SOLONGATE_API_URL"] || "https://api.solongate.com";
|
|
6404
|
+
try {
|
|
6405
|
+
const cfg = JSON.parse(readFileSync4(p.configPath, "utf-8"));
|
|
6406
|
+
if (cfg && typeof cfg.apiKey === "string") apiKey = apiKey || cfg.apiKey;
|
|
6407
|
+
if (cfg && typeof cfg.apiUrl === "string") apiUrl = cfg.apiUrl;
|
|
6408
|
+
} catch {
|
|
6409
|
+
}
|
|
6410
|
+
if (!apiKey) {
|
|
6411
|
+
const acc = firstAccountCredential();
|
|
6412
|
+
if (acc.apiKey) {
|
|
6413
|
+
apiKey = acc.apiKey;
|
|
6414
|
+
if (acc.apiUrl) apiUrl = acc.apiUrl;
|
|
6415
|
+
}
|
|
6416
|
+
}
|
|
6417
|
+
if (!apiKey) return { ok: false, message: "no login on this device \u2014 add an account first (Accounts \u2192 + add)" };
|
|
6418
|
+
mkdirSync3(p.hooksDir, { recursive: true });
|
|
6419
|
+
mkdirSync3(p.claudeDir, { recursive: true });
|
|
6420
|
+
unlockProtected();
|
|
6421
|
+
writeFileSync3(join4(p.hooksDir, "guard.mjs"), readGuard());
|
|
6422
|
+
writeFileSync3(join4(p.hooksDir, "audit.mjs"), readHook("audit.mjs"));
|
|
6423
|
+
writeFileSync3(join4(p.hooksDir, "stop.mjs"), readHook("stop.mjs"));
|
|
6424
|
+
writeFileSync3(join4(p.hooksDir, "shield.mjs"), readHook("shield.mjs"));
|
|
6425
|
+
writeFileSync3(p.configPath, JSON.stringify({ apiKey, apiUrl }, null, 2) + "\n");
|
|
6426
|
+
let existing = {};
|
|
6427
|
+
if (existsSync3(p.settingsPath)) {
|
|
6428
|
+
const raw = readFileSync4(p.settingsPath, "utf-8");
|
|
6429
|
+
if (!existsSync3(p.backupPath)) writeFileSync3(p.backupPath, raw);
|
|
6430
|
+
try {
|
|
6431
|
+
existing = JSON.parse(raw);
|
|
6432
|
+
} catch {
|
|
6433
|
+
existing = {};
|
|
6434
|
+
}
|
|
6435
|
+
}
|
|
6436
|
+
const nodeBin = process.execPath.replace(/\\/g, "/");
|
|
6437
|
+
const call = process.platform === "win32" ? "& " : "";
|
|
6438
|
+
const hookCmd = (script) => `${call}"${nodeBin}" "${join4(p.hooksDir, script).replace(/\\/g, "/")}" claude-code "Claude Code"`;
|
|
6439
|
+
const merged = {
|
|
6440
|
+
...existing,
|
|
6441
|
+
hooks: {
|
|
6442
|
+
PreToolUse: [{ matcher: "", hooks: [{ type: "command", command: hookCmd("guard.mjs") }] }],
|
|
6443
|
+
PostToolUse: [{ matcher: "", hooks: [{ type: "command", command: hookCmd("audit.mjs") }] }],
|
|
6444
|
+
Stop: [{ matcher: "", hooks: [{ type: "command", command: hookCmd("stop.mjs") }] }]
|
|
6445
|
+
}
|
|
6446
|
+
};
|
|
6447
|
+
writeFileSync3(p.settingsPath, JSON.stringify(merged, null, 2) + "\n");
|
|
6448
|
+
try {
|
|
6449
|
+
installAntigravityGuard(p, join4(p.hooksDir, "guard.mjs").replace(/\\/g, "/"));
|
|
6450
|
+
} catch {
|
|
6451
|
+
}
|
|
6452
|
+
if (process.env["SOLONGATE_OS_LOCK"] === "1") lockProtected();
|
|
6453
|
+
return { ok: true, message: "guard installed (open a new session)" };
|
|
6454
|
+
} catch (e) {
|
|
6455
|
+
return { ok: false, message: e instanceof Error ? e.message : String(e) };
|
|
6456
|
+
}
|
|
6457
|
+
}
|
|
6458
|
+
function installedGuardVersion() {
|
|
6459
|
+
try {
|
|
6460
|
+
const p = globalPaths();
|
|
6461
|
+
const s = readFileSync4(join4(p.hooksDir, "guard.mjs"), "utf-8");
|
|
6462
|
+
const m = s.match(/HOOK_VERSION\s*=\s*(\d+)/);
|
|
6463
|
+
return m ? parseInt(m[1], 10) : null;
|
|
6464
|
+
} catch {
|
|
6465
|
+
return null;
|
|
6466
|
+
}
|
|
6467
|
+
}
|
|
6468
|
+
function guardHookOutdated() {
|
|
6469
|
+
try {
|
|
6470
|
+
const p = globalPaths();
|
|
6471
|
+
return readFileSync4(join4(p.hooksDir, "guard.mjs"), "utf-8") !== readGuard();
|
|
6472
|
+
} catch {
|
|
6473
|
+
return false;
|
|
6474
|
+
}
|
|
6475
|
+
}
|
|
6476
|
+
function isGuardInstalled() {
|
|
6477
|
+
try {
|
|
6478
|
+
const p = globalPaths();
|
|
6479
|
+
if (!existsSync3(p.settingsPath)) return false;
|
|
6480
|
+
const s = JSON.parse(readFileSync4(p.settingsPath, "utf-8"));
|
|
6481
|
+
return !!s.hooks && JSON.stringify(s.hooks).includes(".solongate");
|
|
6482
|
+
} catch {
|
|
6483
|
+
return false;
|
|
6484
|
+
}
|
|
6485
|
+
}
|
|
6486
|
+
function uninstallGlobalQuiet() {
|
|
6487
|
+
try {
|
|
6488
|
+
const p = globalPaths();
|
|
6489
|
+
unlockProtected();
|
|
6490
|
+
removeClaudeShim();
|
|
6491
|
+
try {
|
|
6492
|
+
removeAntigravityGuard(p);
|
|
6493
|
+
} catch {
|
|
6494
|
+
}
|
|
6495
|
+
if (!existsSync3(p.settingsPath)) return { ok: true, message: "guard removed (open a new session)" };
|
|
6496
|
+
const s = JSON.parse(readFileSync4(p.settingsPath, "utf-8"));
|
|
6497
|
+
delete s.hooks;
|
|
6498
|
+
writeFileSync3(p.settingsPath, JSON.stringify(s, null, 2) + "\n");
|
|
6499
|
+
return { ok: true, message: "guard removed (open a new session)" };
|
|
6500
|
+
} catch (e) {
|
|
6501
|
+
return { ok: false, message: e instanceof Error ? e.message : String(e) };
|
|
6502
|
+
}
|
|
6503
|
+
}
|
|
6504
|
+
function escapeRe(s) {
|
|
6505
|
+
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
6506
|
+
}
|
|
6507
|
+
function resolveRealClaude() {
|
|
6508
|
+
try {
|
|
6509
|
+
const finder = process.platform === "win32" ? "where" : "which";
|
|
6510
|
+
const out2 = execFileSync2(finder, ["claude"], { encoding: "utf-8" }).split(/\r?\n/).map((s) => s.trim()).filter(Boolean);
|
|
6511
|
+
if (process.platform === "win32") {
|
|
6512
|
+
const low = (s) => s.toLowerCase();
|
|
6513
|
+
return out2.find((l) => low(l).endsWith(".cmd")) || out2.find((l) => low(l).endsWith(".exe")) || out2.find((l) => low(l).endsWith(".bat")) || out2[0] || null;
|
|
6514
|
+
}
|
|
6515
|
+
return out2[0] || null;
|
|
6516
|
+
} catch {
|
|
6517
|
+
return null;
|
|
6518
|
+
}
|
|
6519
|
+
}
|
|
6520
|
+
function shimTargets() {
|
|
6521
|
+
if (process.platform === "win32") {
|
|
6522
|
+
try {
|
|
6523
|
+
const prof = execFileSync2("powershell", ["-NoProfile", "-Command", "$PROFILE.CurrentUserAllHosts"], { encoding: "utf-8" }).trim();
|
|
6524
|
+
return prof ? [prof] : [];
|
|
6525
|
+
} catch {
|
|
6526
|
+
return [];
|
|
6527
|
+
}
|
|
6528
|
+
}
|
|
6529
|
+
return [".bashrc", ".zshrc", ".profile"].map((f) => join4(homedir2(), f)).filter((f) => existsSync3(f));
|
|
6530
|
+
}
|
|
6531
|
+
function writeShimBlock(file, block2) {
|
|
6532
|
+
const re = new RegExp(escapeRe(SHIM_BEGIN) + "[\\s\\S]*?" + escapeRe(SHIM_END) + "\\r?\\n?", "g");
|
|
6533
|
+
let content = existsSync3(file) ? readFileSync4(file, "utf-8") : "";
|
|
6534
|
+
content = content.replace(re, "");
|
|
6535
|
+
if (block2) {
|
|
6536
|
+
if (content.length && !content.endsWith("\n")) content += "\n";
|
|
6537
|
+
content += block2 + "\n";
|
|
6538
|
+
}
|
|
6539
|
+
mkdirSync3(dirname(file), { recursive: true });
|
|
6540
|
+
writeFileSync3(file, content);
|
|
6541
|
+
}
|
|
6542
|
+
function installClaudeShim(shieldPath) {
|
|
6543
|
+
const real = resolveRealClaude();
|
|
6544
|
+
if (!real) {
|
|
6545
|
+
console.log(" (Claude Code not found on PATH \u2014 skipped auto-shield. Install it, then re-open `solongate` \u2192 Settings \u2192 guard.)");
|
|
6546
|
+
return;
|
|
6547
|
+
}
|
|
6548
|
+
const node = process.execPath.replace(/\\/g, "/");
|
|
6549
|
+
const shield = shieldPath.replace(/\\/g, "/");
|
|
6550
|
+
const win = process.platform === "win32";
|
|
6551
|
+
const block2 = win ? `${SHIM_BEGIN}
|
|
6552
|
+
function claude { & "${node}" "${shield}" -- "${real}" @args }
|
|
6553
|
+
${SHIM_END}` : `${SHIM_BEGIN}
|
|
6554
|
+
claude() { "${node}" "${shield}" -- "${real}" "$@"; }
|
|
6555
|
+
${SHIM_END}`;
|
|
6556
|
+
const targets = shimTargets();
|
|
6557
|
+
if (targets.length === 0) return;
|
|
6558
|
+
for (const file of targets) {
|
|
6559
|
+
try {
|
|
6560
|
+
writeShimBlock(file, block2);
|
|
6561
|
+
} catch {
|
|
6562
|
+
}
|
|
6563
|
+
}
|
|
6564
|
+
}
|
|
6565
|
+
function removeClaudeShim() {
|
|
6566
|
+
for (const file of shimTargets()) {
|
|
6567
|
+
try {
|
|
6568
|
+
writeShimBlock(file, null);
|
|
6569
|
+
} catch {
|
|
6570
|
+
}
|
|
6571
|
+
}
|
|
6572
|
+
}
|
|
6573
|
+
async function runGlobalInstall(opts = {}) {
|
|
6574
|
+
const p = globalPaths();
|
|
6575
|
+
let apiKey = opts.apiKey || process.env["SOLONGATE_API_KEY"] || "";
|
|
6576
|
+
if (!apiKey || apiKey === "sg_live_your_key_here") {
|
|
6577
|
+
try {
|
|
6578
|
+
const cfg = JSON.parse(readFileSync4(p.configPath, "utf-8"));
|
|
6579
|
+
if (cfg && typeof cfg.apiKey === "string") apiKey = cfg.apiKey;
|
|
6580
|
+
} catch {
|
|
6581
|
+
}
|
|
6582
|
+
}
|
|
6583
|
+
if (!apiKey || apiKey === "sg_live_your_key_here") {
|
|
6584
|
+
const acc = firstAccountCredential();
|
|
6585
|
+
if (acc.apiKey) apiKey = acc.apiKey;
|
|
6586
|
+
}
|
|
6587
|
+
if (!apiKey || apiKey === "sg_live_your_key_here") {
|
|
6588
|
+
apiKey = await ask(" Enter your SolonGate API key (sg_live_\u2026 from https://dashboard.solongate.com): ");
|
|
6589
|
+
}
|
|
6590
|
+
if (!apiKey.startsWith("sg_live_") && !apiKey.startsWith("sg_test_")) {
|
|
6591
|
+
console.log(" Invalid API key. Must start with sg_live_ or sg_test_");
|
|
6592
|
+
process.exit(1);
|
|
6593
|
+
}
|
|
6594
|
+
const apiUrl = opts.apiUrl || process.env["SOLONGATE_API_URL"] || "https://api.solongate.com";
|
|
6595
|
+
mkdirSync3(p.hooksDir, { recursive: true });
|
|
6596
|
+
mkdirSync3(p.claudeDir, { recursive: true });
|
|
6597
|
+
unlockProtected();
|
|
6598
|
+
writeFileSync3(join4(p.hooksDir, "guard.mjs"), readGuard());
|
|
6599
|
+
writeFileSync3(join4(p.hooksDir, "audit.mjs"), readHook("audit.mjs"));
|
|
6600
|
+
writeFileSync3(join4(p.hooksDir, "stop.mjs"), readHook("stop.mjs"));
|
|
6601
|
+
writeFileSync3(join4(p.hooksDir, "shield.mjs"), readHook("shield.mjs"));
|
|
6602
|
+
console.log(` Installed hooks \u2192 ${p.hooksDir}`);
|
|
6603
|
+
installClaudeShim(join4(p.hooksDir, "shield.mjs"));
|
|
6604
|
+
writeFileSync3(p.configPath, JSON.stringify({ apiKey, apiUrl }, null, 2) + "\n");
|
|
6605
|
+
console.log(` Wrote ${p.configPath}`);
|
|
6606
|
+
let existing = {};
|
|
6607
|
+
if (existsSync3(p.settingsPath)) {
|
|
6608
|
+
const raw = readFileSync4(p.settingsPath, "utf-8");
|
|
6609
|
+
if (!existsSync3(p.backupPath)) {
|
|
6610
|
+
writeFileSync3(p.backupPath, raw);
|
|
6611
|
+
console.log(` Backed up existing settings \u2192 ${p.backupPath}`);
|
|
6612
|
+
}
|
|
6613
|
+
try {
|
|
6614
|
+
existing = JSON.parse(raw);
|
|
6615
|
+
} catch {
|
|
6616
|
+
existing = {};
|
|
6617
|
+
}
|
|
6618
|
+
}
|
|
6619
|
+
const guardAbs = join4(p.hooksDir, "guard.mjs").replace(/\\/g, "/");
|
|
6620
|
+
const auditAbs = join4(p.hooksDir, "audit.mjs").replace(/\\/g, "/");
|
|
6621
|
+
const stopAbs = join4(p.hooksDir, "stop.mjs").replace(/\\/g, "/");
|
|
6622
|
+
const nodeBin = process.execPath.replace(/\\/g, "/");
|
|
6623
|
+
const call = process.platform === "win32" ? "& " : "";
|
|
6624
|
+
const hookCmd = (script) => `${call}"${nodeBin}" "${script}" claude-code "Claude Code"`;
|
|
6625
|
+
const merged = {
|
|
6626
|
+
...existing,
|
|
6627
|
+
hooks: {
|
|
6628
|
+
PreToolUse: [{ matcher: "", hooks: [{ type: "command", command: hookCmd(guardAbs) }] }],
|
|
6629
|
+
PostToolUse: [{ matcher: "", hooks: [{ type: "command", command: hookCmd(auditAbs) }] }],
|
|
6630
|
+
Stop: [{ matcher: "", hooks: [{ type: "command", command: hookCmd(stopAbs) }] }]
|
|
6631
|
+
}
|
|
6632
|
+
};
|
|
6633
|
+
writeFileSync3(p.settingsPath, JSON.stringify(merged, null, 2) + "\n");
|
|
6634
|
+
console.log(` Registered global hooks \u2192 ${p.settingsPath}`);
|
|
6635
|
+
try {
|
|
6636
|
+
installAntigravityGuard(p, guardAbs);
|
|
6637
|
+
console.log(` Registered Antigravity CLI guard \u2192 ${p.antigravityHooksPath}`);
|
|
6638
|
+
} catch {
|
|
6639
|
+
}
|
|
6640
|
+
if (process.env["SOLONGATE_OS_LOCK"] === "1") {
|
|
6641
|
+
lockProtected();
|
|
6642
|
+
console.log(" Locked protection files (OS-level read-only/immutable).");
|
|
6643
|
+
}
|
|
6644
|
+
}
|
|
6645
|
+
async function installGlobalWithKey(apiKey, apiUrl) {
|
|
6646
|
+
await runGlobalInstall({ apiKey, apiUrl });
|
|
6647
|
+
}
|
|
6648
|
+
var __dirname, HOOKS_DIR, ANTIGRAVITY_GROUP, SHIM_BEGIN, SHIM_END;
|
|
6649
|
+
var init_global_install = __esm({
|
|
6650
|
+
"src/global-install.ts"() {
|
|
6651
|
+
"use strict";
|
|
6652
|
+
__dirname = dirname(fileURLToPath(import.meta.url));
|
|
6653
|
+
HOOKS_DIR = resolve3(__dirname, "..", "hooks");
|
|
6654
|
+
ANTIGRAVITY_GROUP = "solongate-guard";
|
|
6655
|
+
SHIM_BEGIN = "# >>> SolonGate shield (auto secret redaction) >>>";
|
|
6656
|
+
SHIM_END = "# <<< SolonGate shield <<<";
|
|
6657
|
+
}
|
|
6658
|
+
});
|
|
6659
|
+
|
|
6190
6660
|
// src/self-update.ts
|
|
6191
6661
|
var self_update_exports = {};
|
|
6192
6662
|
__export(self_update_exports, {
|
|
@@ -6194,16 +6664,17 @@ __export(self_update_exports, {
|
|
|
6194
6664
|
latestVersion: () => latestVersion,
|
|
6195
6665
|
maybeSelfUpdate: () => maybeSelfUpdate,
|
|
6196
6666
|
newerThan: () => newerThan,
|
|
6667
|
+
runUpdateCommand: () => runUpdateCommand,
|
|
6197
6668
|
tuiUpdateFlow: () => tuiUpdateFlow
|
|
6198
6669
|
});
|
|
6199
6670
|
import { execFile, spawn } from "child_process";
|
|
6200
|
-
import { mkdirSync as
|
|
6201
|
-
import { homedir as
|
|
6202
|
-
import { dirname, join as
|
|
6203
|
-
import { fileURLToPath } from "url";
|
|
6671
|
+
import { mkdirSync as mkdirSync4, openSync, readFileSync as readFileSync5, writeFileSync as writeFileSync4 } from "fs";
|
|
6672
|
+
import { homedir as homedir3 } from "os";
|
|
6673
|
+
import { dirname as dirname2, join as join5 } from "path";
|
|
6674
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
6204
6675
|
function readState() {
|
|
6205
6676
|
try {
|
|
6206
|
-
const s = JSON.parse(
|
|
6677
|
+
const s = JSON.parse(readFileSync5(STATE_FILE, "utf-8"));
|
|
6207
6678
|
return s && typeof s === "object" ? s : {};
|
|
6208
6679
|
} catch {
|
|
6209
6680
|
return {};
|
|
@@ -6211,14 +6682,14 @@ function readState() {
|
|
|
6211
6682
|
}
|
|
6212
6683
|
function writeState(s) {
|
|
6213
6684
|
try {
|
|
6214
|
-
|
|
6215
|
-
|
|
6685
|
+
mkdirSync4(join5(homedir3(), ".solongate"), { recursive: true });
|
|
6686
|
+
writeFileSync4(STATE_FILE, JSON.stringify(s));
|
|
6216
6687
|
} catch {
|
|
6217
6688
|
}
|
|
6218
6689
|
}
|
|
6219
6690
|
function currentVersion() {
|
|
6220
6691
|
try {
|
|
6221
|
-
const pkg = JSON.parse(
|
|
6692
|
+
const pkg = JSON.parse(readFileSync5(join5(dirname2(fileURLToPath2(import.meta.url)), "..", "package.json"), "utf-8"));
|
|
6222
6693
|
return pkg.version ?? "0.0.0";
|
|
6223
6694
|
} catch {
|
|
6224
6695
|
return "0.0.0";
|
|
@@ -6254,7 +6725,7 @@ async function fetchLatest() {
|
|
|
6254
6725
|
}
|
|
6255
6726
|
function spawnGlobalInstall(version) {
|
|
6256
6727
|
try {
|
|
6257
|
-
|
|
6728
|
+
mkdirSync4(join5(homedir3(), ".solongate"), { recursive: true });
|
|
6258
6729
|
const log3 = openSync(LOG_FILE, "a");
|
|
6259
6730
|
const p = spawn("npm", ["install", "-g", `${PKG}@${version}`], {
|
|
6260
6731
|
stdio: ["ignore", log3, log3],
|
|
@@ -6270,17 +6741,45 @@ function spawnGlobalInstall(version) {
|
|
|
6270
6741
|
return false;
|
|
6271
6742
|
}
|
|
6272
6743
|
}
|
|
6273
|
-
function
|
|
6744
|
+
async function runUpdateCommand() {
|
|
6745
|
+
const out2 = (s) => void process.stderr.write(s + "\n");
|
|
6746
|
+
const cur = currentVersion();
|
|
6747
|
+
out2(` current ${cur}`);
|
|
6748
|
+
const latest = await latestVersion();
|
|
6749
|
+
if (!latest) {
|
|
6750
|
+
out2(" could not reach the npm registry. Try again, or: npm i -g @solongate/proxy@latest");
|
|
6751
|
+
return 1;
|
|
6752
|
+
}
|
|
6753
|
+
if (newerThan(latest, cur)) {
|
|
6754
|
+
out2(` updating ${cur} -> ${latest} ...`);
|
|
6755
|
+
const ok = await runGlobalInstall2(latest);
|
|
6756
|
+
if (!ok) {
|
|
6757
|
+
out2(" update failed. Try: npm i -g @solongate/proxy@latest");
|
|
6758
|
+
return 1;
|
|
6759
|
+
}
|
|
6760
|
+
out2(` \u2713 updated to ${latest} (open a new session to use it)`);
|
|
6761
|
+
} else {
|
|
6762
|
+
out2(` \u2713 already up to date`);
|
|
6763
|
+
}
|
|
6764
|
+
try {
|
|
6765
|
+
const { installGlobalQuiet: installGlobalQuiet2, installedGuardVersion: installedGuardVersion2 } = await Promise.resolve().then(() => (init_global_install(), global_install_exports));
|
|
6766
|
+
const r = installGlobalQuiet2();
|
|
6767
|
+
out2(r.ok ? ` \u2713 guard hooks refreshed (v${installedGuardVersion2() ?? "?"})` : ` guard: ${r.message}`);
|
|
6768
|
+
} catch {
|
|
6769
|
+
}
|
|
6770
|
+
return 0;
|
|
6771
|
+
}
|
|
6772
|
+
function runGlobalInstall2(version) {
|
|
6274
6773
|
return new Promise((resolve6) => {
|
|
6275
6774
|
try {
|
|
6276
|
-
|
|
6775
|
+
mkdirSync4(join5(homedir3(), ".solongate"), { recursive: true });
|
|
6277
6776
|
execFile(
|
|
6278
6777
|
"npm",
|
|
6279
6778
|
["install", "-g", `${PKG}@${version}`],
|
|
6280
6779
|
{ timeout: 3e5, windowsHide: true, shell: process.platform === "win32" },
|
|
6281
6780
|
(err2, stdout, stderr) => {
|
|
6282
6781
|
try {
|
|
6283
|
-
|
|
6782
|
+
writeFileSync4(LOG_FILE, `${(/* @__PURE__ */ new Date()).toISOString()} install ${version}: ${err2 ? "FAILED" : "ok"}
|
|
6284
6783
|
${stdout}
|
|
6285
6784
|
${stderr}
|
|
6286
6785
|
`, { flag: "a" });
|
|
@@ -6306,7 +6805,7 @@ async function tuiUpdateFlow(onStatus) {
|
|
|
6306
6805
|
return;
|
|
6307
6806
|
}
|
|
6308
6807
|
onStatus({ kind: "updating", version: latest });
|
|
6309
|
-
if (await
|
|
6808
|
+
if (await runGlobalInstall2(latest)) {
|
|
6310
6809
|
writeState({ ...readState(), installed: latest });
|
|
6311
6810
|
onStatus({ kind: "updated", version: latest });
|
|
6312
6811
|
}
|
|
@@ -6345,8 +6844,8 @@ var init_self_update = __esm({
|
|
|
6345
6844
|
PKG = "@solongate/proxy";
|
|
6346
6845
|
CHECK_EVERY_MS = 30 * 60 * 1e3;
|
|
6347
6846
|
ATTEMPT_EVERY_MS = 6 * 60 * 60 * 1e3;
|
|
6348
|
-
STATE_FILE =
|
|
6349
|
-
LOG_FILE =
|
|
6847
|
+
STATE_FILE = join5(homedir3(), ".solongate", ".self-update.json");
|
|
6848
|
+
LOG_FILE = join5(homedir3(), ".solongate", "self-update.log");
|
|
6350
6849
|
}
|
|
6351
6850
|
});
|
|
6352
6851
|
|
|
@@ -6361,13 +6860,13 @@ __export(logs_server_daemon_exports, {
|
|
|
6361
6860
|
stopLogsServerDaemon: () => stopLogsServerDaemon
|
|
6362
6861
|
});
|
|
6363
6862
|
import { spawn as spawn2 } from "child_process";
|
|
6364
|
-
import { mkdirSync as
|
|
6365
|
-
import { homedir as
|
|
6366
|
-
import { dirname as
|
|
6367
|
-
import { fileURLToPath as
|
|
6863
|
+
import { mkdirSync as mkdirSync5, openSync as openSync2, readFileSync as readFileSync6, writeFileSync as writeFileSync5 } from "fs";
|
|
6864
|
+
import { homedir as homedir4 } from "os";
|
|
6865
|
+
import { dirname as dirname3, join as join6 } from "path";
|
|
6866
|
+
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
6368
6867
|
function readState2() {
|
|
6369
6868
|
try {
|
|
6370
|
-
const s = JSON.parse(
|
|
6869
|
+
const s = JSON.parse(readFileSync6(STATE_FILE2, "utf-8"));
|
|
6371
6870
|
return s && typeof s === "object" ? s : {};
|
|
6372
6871
|
} catch {
|
|
6373
6872
|
return {};
|
|
@@ -6375,8 +6874,8 @@ function readState2() {
|
|
|
6375
6874
|
}
|
|
6376
6875
|
function writeState2(s) {
|
|
6377
6876
|
try {
|
|
6378
|
-
|
|
6379
|
-
|
|
6877
|
+
mkdirSync5(DIR, { recursive: true });
|
|
6878
|
+
writeFileSync5(STATE_FILE2, JSON.stringify(s));
|
|
6380
6879
|
} catch {
|
|
6381
6880
|
}
|
|
6382
6881
|
}
|
|
@@ -6404,9 +6903,9 @@ function startLogsServerDaemon() {
|
|
|
6404
6903
|
return { ...cur, desired: "on" };
|
|
6405
6904
|
}
|
|
6406
6905
|
try {
|
|
6407
|
-
|
|
6906
|
+
mkdirSync5(DIR, { recursive: true });
|
|
6408
6907
|
const log3 = openSync2(LOG_FILE2, "a");
|
|
6409
|
-
const cli =
|
|
6908
|
+
const cli = join6(dirname3(fileURLToPath3(import.meta.url)), "index.js");
|
|
6410
6909
|
const p = spawn2(process.execPath, [cli, "logs-server"], {
|
|
6411
6910
|
detached: true,
|
|
6412
6911
|
stdio: ["ignore", log3, log3],
|
|
@@ -6443,22 +6942,22 @@ var DIR, STATE_FILE2, LOG_FILE2, LOGS_SERVER_PORT;
|
|
|
6443
6942
|
var init_logs_server_daemon = __esm({
|
|
6444
6943
|
"src/logs-server-daemon.ts"() {
|
|
6445
6944
|
"use strict";
|
|
6446
|
-
DIR =
|
|
6447
|
-
STATE_FILE2 =
|
|
6448
|
-
LOG_FILE2 =
|
|
6945
|
+
DIR = join6(homedir4(), ".solongate");
|
|
6946
|
+
STATE_FILE2 = join6(DIR, ".logs-server.json");
|
|
6947
|
+
LOG_FILE2 = join6(DIR, "logs-server.log");
|
|
6449
6948
|
LOGS_SERVER_PORT = 8788;
|
|
6450
6949
|
}
|
|
6451
6950
|
});
|
|
6452
6951
|
|
|
6453
6952
|
// src/tui/config.ts
|
|
6454
|
-
import { readFileSync as
|
|
6455
|
-
import { homedir as
|
|
6456
|
-
import { join as
|
|
6953
|
+
import { readFileSync as readFileSync7 } from "fs";
|
|
6954
|
+
import { homedir as homedir5 } from "os";
|
|
6955
|
+
import { join as join7 } from "path";
|
|
6457
6956
|
function loadConfig() {
|
|
6458
6957
|
if (cached) return cached;
|
|
6459
6958
|
const defaults = { notifications: true };
|
|
6460
6959
|
try {
|
|
6461
|
-
const raw =
|
|
6960
|
+
const raw = readFileSync7(join7(homedir5(), ".solongate", "tui-config.json"), "utf-8");
|
|
6462
6961
|
const j = JSON.parse(raw);
|
|
6463
6962
|
cached = {
|
|
6464
6963
|
notifications: j.notifications !== false,
|
|
@@ -6629,9 +7128,9 @@ var init_components = __esm({
|
|
|
6629
7128
|
});
|
|
6630
7129
|
|
|
6631
7130
|
// src/tui/local-log.ts
|
|
6632
|
-
import { closeSync, openSync as openSync3, readFileSync as
|
|
6633
|
-
import { homedir as
|
|
6634
|
-
import { join as
|
|
7131
|
+
import { closeSync, openSync as openSync3, readFileSync as readFileSync8, readSync, statSync, writeFileSync as writeFileSync6 } from "fs";
|
|
7132
|
+
import { homedir as homedir6 } from "os";
|
|
7133
|
+
import { join as join8 } from "path";
|
|
6635
7134
|
function tailLines(file, maxBytes = 131072) {
|
|
6636
7135
|
try {
|
|
6637
7136
|
const size = statSync(file).size;
|
|
@@ -6649,7 +7148,7 @@ function tailLines(file, maxBytes = 131072) {
|
|
|
6649
7148
|
}
|
|
6650
7149
|
function deleteLocalEntry(at, tool, session) {
|
|
6651
7150
|
try {
|
|
6652
|
-
const lines =
|
|
7151
|
+
const lines = readFileSync8(LOCAL_LOG, "utf-8").split("\n");
|
|
6653
7152
|
let removed = 0;
|
|
6654
7153
|
const kept = lines.filter((line) => {
|
|
6655
7154
|
if (!line.trim()) return false;
|
|
@@ -6665,7 +7164,7 @@ function deleteLocalEntry(at, tool, session) {
|
|
|
6665
7164
|
}
|
|
6666
7165
|
return true;
|
|
6667
7166
|
});
|
|
6668
|
-
if (removed)
|
|
7167
|
+
if (removed) writeFileSync6(LOCAL_LOG, kept.length ? kept.join("\n") + "\n" : "");
|
|
6669
7168
|
return removed;
|
|
6670
7169
|
} catch {
|
|
6671
7170
|
return 0;
|
|
@@ -6673,8 +7172,8 @@ function deleteLocalEntry(at, tool, session) {
|
|
|
6673
7172
|
}
|
|
6674
7173
|
function clearLocalLog() {
|
|
6675
7174
|
try {
|
|
6676
|
-
const n =
|
|
6677
|
-
|
|
7175
|
+
const n = readFileSync8(LOCAL_LOG, "utf-8").split("\n").filter(Boolean).length;
|
|
7176
|
+
writeFileSync6(LOCAL_LOG, "");
|
|
6678
7177
|
return n;
|
|
6679
7178
|
} catch {
|
|
6680
7179
|
return 0;
|
|
@@ -6705,20 +7204,20 @@ var LOCAL_LOG, DLP_REASON, RL_REASON;
|
|
|
6705
7204
|
var init_local_log = __esm({
|
|
6706
7205
|
"src/tui/local-log.ts"() {
|
|
6707
7206
|
"use strict";
|
|
6708
|
-
LOCAL_LOG =
|
|
7207
|
+
LOCAL_LOG = join8(homedir6(), ".solongate", "local-logs", "solongate-audit.jsonl");
|
|
6709
7208
|
DLP_REASON = /security layer \(dlp\)/i;
|
|
6710
7209
|
RL_REASON = /security layer \(rate limit\)|rate[- ]?limit(?:ed)?\b.*exceed|exceeded \d+ calls/i;
|
|
6711
7210
|
}
|
|
6712
7211
|
});
|
|
6713
7212
|
|
|
6714
7213
|
// src/api-client/client.ts
|
|
6715
|
-
import { readFileSync as
|
|
6716
|
-
import { resolve as
|
|
6717
|
-
import { homedir as
|
|
7214
|
+
import { readFileSync as readFileSync9, writeFileSync as writeFileSync7, mkdirSync as mkdirSync6, existsSync as existsSync4 } from "fs";
|
|
7215
|
+
import { resolve as resolve4, join as join9 } from "path";
|
|
7216
|
+
import { homedir as homedir7 } from "os";
|
|
6718
7217
|
function listAccounts() {
|
|
6719
7218
|
let list5 = [];
|
|
6720
7219
|
try {
|
|
6721
|
-
const raw = JSON.parse(
|
|
7220
|
+
const raw = JSON.parse(readFileSync9(accountsFile(), "utf-8"));
|
|
6722
7221
|
if (Array.isArray(raw)) list5 = raw.filter((a) => a && typeof a.apiKey === "string");
|
|
6723
7222
|
} catch {
|
|
6724
7223
|
}
|
|
@@ -6732,7 +7231,7 @@ function saveAccount(acc) {
|
|
|
6732
7231
|
try {
|
|
6733
7232
|
const list5 = (() => {
|
|
6734
7233
|
try {
|
|
6735
|
-
const raw = JSON.parse(
|
|
7234
|
+
const raw = JSON.parse(readFileSync9(accountsFile(), "utf-8"));
|
|
6736
7235
|
return Array.isArray(raw) ? raw.filter((a) => a && a.apiKey) : [];
|
|
6737
7236
|
} catch {
|
|
6738
7237
|
return [];
|
|
@@ -6740,8 +7239,8 @@ function saveAccount(acc) {
|
|
|
6740
7239
|
})();
|
|
6741
7240
|
const next = list5.filter((a) => a.apiKey !== acc.apiKey);
|
|
6742
7241
|
next.unshift({ ...acc, addedAt: acc.addedAt ?? Date.now() });
|
|
6743
|
-
|
|
6744
|
-
|
|
7242
|
+
mkdirSync6(join9(homedir7(), ".solongate"), { recursive: true });
|
|
7243
|
+
writeFileSync7(accountsFile(), JSON.stringify(next, null, 2));
|
|
6745
7244
|
} catch {
|
|
6746
7245
|
}
|
|
6747
7246
|
}
|
|
@@ -6749,13 +7248,13 @@ function removeAccount(apiKey) {
|
|
|
6749
7248
|
try {
|
|
6750
7249
|
const list5 = (() => {
|
|
6751
7250
|
try {
|
|
6752
|
-
const raw = JSON.parse(
|
|
7251
|
+
const raw = JSON.parse(readFileSync9(accountsFile(), "utf-8"));
|
|
6753
7252
|
return Array.isArray(raw) ? raw.filter((a) => a && a.apiKey) : [];
|
|
6754
7253
|
} catch {
|
|
6755
7254
|
return [];
|
|
6756
7255
|
}
|
|
6757
7256
|
})();
|
|
6758
|
-
|
|
7257
|
+
writeFileSync7(accountsFile(), JSON.stringify(list5.filter((a) => a.apiKey !== apiKey), null, 2));
|
|
6759
7258
|
} catch {
|
|
6760
7259
|
}
|
|
6761
7260
|
}
|
|
@@ -6768,15 +7267,15 @@ function isActiveAccount(apiKey) {
|
|
|
6768
7267
|
}
|
|
6769
7268
|
function setActiveAccount(creds) {
|
|
6770
7269
|
try {
|
|
6771
|
-
const dir =
|
|
6772
|
-
|
|
6773
|
-
const p =
|
|
7270
|
+
const dir = join9(homedir7(), ".solongate");
|
|
7271
|
+
mkdirSync6(dir, { recursive: true });
|
|
7272
|
+
const p = join9(dir, ["cloud", "guard.json"].join("-"));
|
|
6774
7273
|
let existing = {};
|
|
6775
7274
|
try {
|
|
6776
|
-
existing = JSON.parse(
|
|
7275
|
+
existing = JSON.parse(readFileSync9(p, "utf-8"));
|
|
6777
7276
|
} catch {
|
|
6778
7277
|
}
|
|
6779
|
-
|
|
7278
|
+
writeFileSync7(p, JSON.stringify({ ...existing, apiKey: creds.apiKey, apiUrl: creds.apiUrl }, null, 2));
|
|
6780
7279
|
cached2 = null;
|
|
6781
7280
|
return true;
|
|
6782
7281
|
} catch {
|
|
@@ -6785,19 +7284,19 @@ function setActiveAccount(creds) {
|
|
|
6785
7284
|
}
|
|
6786
7285
|
function clearActiveCredential() {
|
|
6787
7286
|
try {
|
|
6788
|
-
const p =
|
|
6789
|
-
if (!
|
|
7287
|
+
const p = join9(homedir7(), ".solongate", ["cloud", "guard.json"].join("-"));
|
|
7288
|
+
if (!existsSync4(p)) {
|
|
6790
7289
|
cached2 = null;
|
|
6791
7290
|
return true;
|
|
6792
7291
|
}
|
|
6793
7292
|
let existing = {};
|
|
6794
7293
|
try {
|
|
6795
|
-
existing = JSON.parse(
|
|
7294
|
+
existing = JSON.parse(readFileSync9(p, "utf-8"));
|
|
6796
7295
|
} catch {
|
|
6797
7296
|
}
|
|
6798
7297
|
delete existing.apiKey;
|
|
6799
7298
|
delete existing.apiUrl;
|
|
6800
|
-
|
|
7299
|
+
writeFileSync7(p, JSON.stringify(existing, null, 2));
|
|
6801
7300
|
cached2 = null;
|
|
6802
7301
|
viewOverride = null;
|
|
6803
7302
|
return true;
|
|
@@ -6807,9 +7306,9 @@ function clearActiveCredential() {
|
|
|
6807
7306
|
}
|
|
6808
7307
|
function loginCredentialFile() {
|
|
6809
7308
|
try {
|
|
6810
|
-
const p =
|
|
6811
|
-
if (!
|
|
6812
|
-
const c2 = JSON.parse(
|
|
7309
|
+
const p = join9(homedir7(), ".solongate", "cloud-guard.json");
|
|
7310
|
+
if (!existsSync4(p)) return {};
|
|
7311
|
+
const c2 = JSON.parse(readFileSync9(p, "utf-8"));
|
|
6813
7312
|
return c2 && typeof c2 === "object" ? c2 : {};
|
|
6814
7313
|
} catch {
|
|
6815
7314
|
return {};
|
|
@@ -6817,9 +7316,9 @@ function loginCredentialFile() {
|
|
|
6817
7316
|
}
|
|
6818
7317
|
function dotenvApiKey() {
|
|
6819
7318
|
try {
|
|
6820
|
-
const envPath =
|
|
6821
|
-
if (!
|
|
6822
|
-
for (const line of
|
|
7319
|
+
const envPath = resolve4(".env");
|
|
7320
|
+
if (!existsSync4(envPath)) return void 0;
|
|
7321
|
+
for (const line of readFileSync9(envPath, "utf-8").split("\n")) {
|
|
6823
7322
|
const trimmed = line.trim();
|
|
6824
7323
|
if (!trimmed || trimmed.startsWith("#")) continue;
|
|
6825
7324
|
const eq = trimmed.indexOf("=");
|
|
@@ -6922,7 +7421,7 @@ var init_client = __esm({
|
|
|
6922
7421
|
"src/api-client/client.ts"() {
|
|
6923
7422
|
"use strict";
|
|
6924
7423
|
DEFAULT_API_URL2 = "https://api.solongate.com";
|
|
6925
|
-
accountsFile = () =>
|
|
7424
|
+
accountsFile = () => join9(homedir7(), ".solongate", "accounts.json");
|
|
6926
7425
|
viewOverride = null;
|
|
6927
7426
|
ApiError = class extends Error {
|
|
6928
7427
|
status;
|
|
@@ -7413,9 +7912,9 @@ var init_hooks = __esm({
|
|
|
7413
7912
|
// src/tui/panels/Live.tsx
|
|
7414
7913
|
import { Box as Box2, Text as Text2, useInput } from "ink";
|
|
7415
7914
|
import TextInput from "ink-text-input";
|
|
7416
|
-
import { mkdirSync as
|
|
7417
|
-
import { homedir as
|
|
7418
|
-
import { join as
|
|
7915
|
+
import { mkdirSync as mkdirSync7, writeFileSync as writeFileSync8 } from "fs";
|
|
7916
|
+
import { homedir as homedir8 } from "os";
|
|
7917
|
+
import { join as join10 } from "path";
|
|
7419
7918
|
import { useCallback as useCallback2, useEffect as useEffect2, useRef as useRef2, useState as useState2 } from "react";
|
|
7420
7919
|
import { Fragment as Fragment2, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
7421
7920
|
function extractTarget(detail) {
|
|
@@ -7973,10 +8472,10 @@ function LivePanel({ active: active2 }) {
|
|
|
7973
8472
|
else if (input === "x") toggleSignal("dlp");
|
|
7974
8473
|
else if (input === "r") toggleSignal("ratelimit");
|
|
7975
8474
|
else if (input === "e") {
|
|
7976
|
-
const file =
|
|
8475
|
+
const file = join10(homedir8(), ".solongate", "live-export.jsonl");
|
|
7977
8476
|
try {
|
|
7978
|
-
|
|
7979
|
-
|
|
8477
|
+
mkdirSync7(join10(homedir8(), ".solongate"), { recursive: true });
|
|
8478
|
+
writeFileSync8(file, visibleDesc.map((x) => JSON.stringify(x)).join("\n") + "\n");
|
|
7980
8479
|
setActionMsg({ text: `\u2713 exported ${visibleDesc.length} lines \u2192 ${file}`, level: "ok", until: Date.now() + 6e3 });
|
|
7981
8480
|
} catch (err2) {
|
|
7982
8481
|
setActionMsg({ text: "\u2717 export failed: " + (err2 instanceof Error ? err2.message : String(err2)), level: "bad", until: Date.now() + 6e3 });
|
|
@@ -8387,7 +8886,7 @@ var init_Live = __esm({
|
|
|
8387
8886
|
SPIN = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
8388
8887
|
BG = "#12234f";
|
|
8389
8888
|
DIM_FLOOR = "#233457";
|
|
8390
|
-
RING =
|
|
8889
|
+
RING = join10(process.cwd(), ".solongate", ".eval-ring.jsonl");
|
|
8391
8890
|
fmtUp = (ms) => {
|
|
8392
8891
|
const s = Math.floor(ms / 1e3);
|
|
8393
8892
|
const p = (n) => String(n).padStart(2, "0");
|
|
@@ -9390,9 +9889,9 @@ var init_Dlp = __esm({
|
|
|
9390
9889
|
// src/tui/panels/Audit.tsx
|
|
9391
9890
|
import { Box as Box7, Text as Text7, useInput as useInput6 } from "ink";
|
|
9392
9891
|
import TextInput5 from "ink-text-input";
|
|
9393
|
-
import { mkdirSync as
|
|
9394
|
-
import { homedir as
|
|
9395
|
-
import { join as
|
|
9892
|
+
import { mkdirSync as mkdirSync8, writeFileSync as writeFileSync9 } from "fs";
|
|
9893
|
+
import { homedir as homedir9 } from "os";
|
|
9894
|
+
import { join as join11 } from "path";
|
|
9396
9895
|
import { useState as useState7 } from "react";
|
|
9397
9896
|
import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
9398
9897
|
function loadLocalRows() {
|
|
@@ -9542,16 +10041,16 @@ function AuditPanel({ active: active2, focused }) {
|
|
|
9542
10041
|
const doExport = (kind) => {
|
|
9543
10042
|
setMsg({ text: "exporting\u2026", level: "ok" });
|
|
9544
10043
|
const run10 = async () => {
|
|
9545
|
-
const dir =
|
|
9546
|
-
const file =
|
|
10044
|
+
const dir = join11(homedir9(), ".solongate");
|
|
10045
|
+
const file = join11(dir, `audit-export-${source}.jsonl`);
|
|
9547
10046
|
let rows2;
|
|
9548
10047
|
if (kind === "page") rows2 = pageRows;
|
|
9549
10048
|
else if (source === "cloud") {
|
|
9550
10049
|
const r = await api.audit.list({ ...query, limit: 1e4, offset: 0 });
|
|
9551
10050
|
rows2 = r.entries.map(cloudRow).sort((a, b) => b.at - a.at);
|
|
9552
10051
|
} else rows2 = localFiltered;
|
|
9553
|
-
|
|
9554
|
-
|
|
10052
|
+
mkdirSync8(dir, { recursive: true });
|
|
10053
|
+
writeFileSync9(file, rows2.map((x) => JSON.stringify(x)).join("\n") + (rows2.length ? "\n" : ""));
|
|
9555
10054
|
return { n: rows2.length, file };
|
|
9556
10055
|
};
|
|
9557
10056
|
run10().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" }));
|
|
@@ -10022,312 +10521,6 @@ var init_Audit = __esm({
|
|
|
10022
10521
|
}
|
|
10023
10522
|
});
|
|
10024
10523
|
|
|
10025
|
-
// src/global-install.ts
|
|
10026
|
-
import { readFileSync as readFileSync9, writeFileSync as writeFileSync9, existsSync as existsSync4, mkdirSync as mkdirSync8, rmSync as rmSync2 } from "fs";
|
|
10027
|
-
import { resolve as resolve4, join as join11, dirname as dirname3 } from "path";
|
|
10028
|
-
import { homedir as homedir9 } from "os";
|
|
10029
|
-
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
10030
|
-
import { createInterface } from "readline";
|
|
10031
|
-
import { execFileSync as execFileSync2 } from "child_process";
|
|
10032
|
-
function lockFile(file) {
|
|
10033
|
-
if (!existsSync4(file)) return;
|
|
10034
|
-
try {
|
|
10035
|
-
if (process.platform === "win32") {
|
|
10036
|
-
try {
|
|
10037
|
-
execFileSync2("icacls", [file, "/deny", "*S-1-1-0:(WD,AD,DC,DE)"], { stdio: "ignore" });
|
|
10038
|
-
} catch {
|
|
10039
|
-
}
|
|
10040
|
-
try {
|
|
10041
|
-
execFileSync2("attrib", ["+R", file], { stdio: "ignore" });
|
|
10042
|
-
} catch {
|
|
10043
|
-
}
|
|
10044
|
-
} else if (process.platform === "darwin") {
|
|
10045
|
-
try {
|
|
10046
|
-
execFileSync2("chflags", ["uchg", file], { stdio: "ignore" });
|
|
10047
|
-
} catch {
|
|
10048
|
-
}
|
|
10049
|
-
} else {
|
|
10050
|
-
try {
|
|
10051
|
-
execFileSync2("chattr", ["+i", file], { stdio: "ignore" });
|
|
10052
|
-
} catch {
|
|
10053
|
-
}
|
|
10054
|
-
}
|
|
10055
|
-
} catch {
|
|
10056
|
-
}
|
|
10057
|
-
}
|
|
10058
|
-
function unlockFile(file) {
|
|
10059
|
-
if (!existsSync4(file)) return;
|
|
10060
|
-
try {
|
|
10061
|
-
if (process.platform === "win32") {
|
|
10062
|
-
try {
|
|
10063
|
-
execFileSync2("icacls", [file, "/remove:d", "*S-1-1-0"], { stdio: "ignore" });
|
|
10064
|
-
} catch {
|
|
10065
|
-
}
|
|
10066
|
-
try {
|
|
10067
|
-
execFileSync2("icacls", [file, "/reset"], { stdio: "ignore" });
|
|
10068
|
-
} catch {
|
|
10069
|
-
}
|
|
10070
|
-
try {
|
|
10071
|
-
execFileSync2("attrib", ["-R", file], { stdio: "ignore" });
|
|
10072
|
-
} catch {
|
|
10073
|
-
}
|
|
10074
|
-
} else if (process.platform === "darwin") {
|
|
10075
|
-
try {
|
|
10076
|
-
execFileSync2("chflags", ["nouchg", file], { stdio: "ignore" });
|
|
10077
|
-
} catch {
|
|
10078
|
-
}
|
|
10079
|
-
} else {
|
|
10080
|
-
try {
|
|
10081
|
-
execFileSync2("chattr", ["-i", file], { stdio: "ignore" });
|
|
10082
|
-
} catch {
|
|
10083
|
-
}
|
|
10084
|
-
}
|
|
10085
|
-
} catch {
|
|
10086
|
-
}
|
|
10087
|
-
}
|
|
10088
|
-
function protectedTargets() {
|
|
10089
|
-
const p = globalPaths();
|
|
10090
|
-
return [
|
|
10091
|
-
join11(p.hooksDir, "guard.mjs"),
|
|
10092
|
-
join11(p.hooksDir, "audit.mjs"),
|
|
10093
|
-
join11(p.hooksDir, "stop.mjs"),
|
|
10094
|
-
join11(p.hooksDir, "shield.mjs"),
|
|
10095
|
-
p.configPath,
|
|
10096
|
-
p.settingsPath,
|
|
10097
|
-
p.antigravityHooksPath
|
|
10098
|
-
];
|
|
10099
|
-
}
|
|
10100
|
-
function lockProtected() {
|
|
10101
|
-
for (const f of protectedTargets()) lockFile(f);
|
|
10102
|
-
}
|
|
10103
|
-
function unlockProtected() {
|
|
10104
|
-
for (const f of protectedTargets()) unlockFile(f);
|
|
10105
|
-
}
|
|
10106
|
-
function globalPaths() {
|
|
10107
|
-
const home = homedir9();
|
|
10108
|
-
const sgDir = join11(home, ".solongate");
|
|
10109
|
-
const hooksDir = join11(sgDir, "hooks");
|
|
10110
|
-
const claudeDir = join11(home, ".claude");
|
|
10111
|
-
const antigravityDir = join11(home, ".gemini", "config");
|
|
10112
|
-
return {
|
|
10113
|
-
home,
|
|
10114
|
-
sgDir,
|
|
10115
|
-
hooksDir,
|
|
10116
|
-
claudeDir,
|
|
10117
|
-
antigravityDir,
|
|
10118
|
-
settingsPath: join11(claudeDir, "settings.json"),
|
|
10119
|
-
backupPath: join11(claudeDir, "settings.solongate.bak"),
|
|
10120
|
-
configPath: join11(sgDir, "cloud-guard.json"),
|
|
10121
|
-
// Antigravity reads global hooks from ~/.gemini/config/hooks.json. Only the
|
|
10122
|
-
// guard is registered there (PreToolUse); Antigravity's ALLOW-path audit is
|
|
10123
|
-
// covered by the passive session-log collector, not a hook.
|
|
10124
|
-
antigravityHooksPath: join11(antigravityDir, "hooks.json"),
|
|
10125
|
-
antigravityBackupPath: join11(antigravityDir, "hooks.solongate.bak")
|
|
10126
|
-
};
|
|
10127
|
-
}
|
|
10128
|
-
function readHook(filename) {
|
|
10129
|
-
return readFileSync9(join11(HOOKS_DIR, filename), "utf-8");
|
|
10130
|
-
}
|
|
10131
|
-
function firstAccountCredential() {
|
|
10132
|
-
try {
|
|
10133
|
-
const raw = JSON.parse(readFileSync9(join11(homedir9(), ".solongate", "accounts.json"), "utf-8"));
|
|
10134
|
-
if (Array.isArray(raw)) {
|
|
10135
|
-
const acc = raw.find((a) => a && typeof a.apiKey === "string" && a.apiKey);
|
|
10136
|
-
if (acc) return { apiKey: acc.apiKey, apiUrl: typeof acc.apiUrl === "string" ? acc.apiUrl : void 0 };
|
|
10137
|
-
}
|
|
10138
|
-
} catch {
|
|
10139
|
-
}
|
|
10140
|
-
return {};
|
|
10141
|
-
}
|
|
10142
|
-
function readGuard() {
|
|
10143
|
-
const bundled = join11(HOOKS_DIR, "guard.bundled.mjs");
|
|
10144
|
-
return existsSync4(bundled) ? readFileSync9(bundled, "utf-8") : readHook("guard.mjs");
|
|
10145
|
-
}
|
|
10146
|
-
function antigravityHookCommand(guardAbs) {
|
|
10147
|
-
const nodeBin = process.execPath.replace(/\\/g, "/");
|
|
10148
|
-
const call = process.platform === "win32" ? "& " : "";
|
|
10149
|
-
return `${call}"${nodeBin}" "${guardAbs.replace(/\\/g, "/")}" antigravity "Antigravity"`;
|
|
10150
|
-
}
|
|
10151
|
-
function installAntigravityGuard(p, guardAbs) {
|
|
10152
|
-
mkdirSync8(p.antigravityDir, { recursive: true });
|
|
10153
|
-
let existing = {};
|
|
10154
|
-
if (existsSync4(p.antigravityHooksPath)) {
|
|
10155
|
-
const raw = readFileSync9(p.antigravityHooksPath, "utf-8");
|
|
10156
|
-
if (!existsSync4(p.antigravityBackupPath)) writeFileSync9(p.antigravityBackupPath, raw);
|
|
10157
|
-
try {
|
|
10158
|
-
existing = JSON.parse(raw);
|
|
10159
|
-
} catch {
|
|
10160
|
-
existing = {};
|
|
10161
|
-
}
|
|
10162
|
-
}
|
|
10163
|
-
const merged = {
|
|
10164
|
-
...existing,
|
|
10165
|
-
[ANTIGRAVITY_GROUP]: {
|
|
10166
|
-
PreToolUse: [{ matcher: "", hooks: [{ type: "command", command: antigravityHookCommand(guardAbs) }] }]
|
|
10167
|
-
}
|
|
10168
|
-
};
|
|
10169
|
-
writeFileSync9(p.antigravityHooksPath, JSON.stringify(merged, null, 2) + "\n");
|
|
10170
|
-
}
|
|
10171
|
-
function removeAntigravityGuard(p) {
|
|
10172
|
-
if (!existsSync4(p.antigravityHooksPath)) return;
|
|
10173
|
-
try {
|
|
10174
|
-
const s = JSON.parse(readFileSync9(p.antigravityHooksPath, "utf-8"));
|
|
10175
|
-
if (!(ANTIGRAVITY_GROUP in s)) return;
|
|
10176
|
-
delete s[ANTIGRAVITY_GROUP];
|
|
10177
|
-
writeFileSync9(p.antigravityHooksPath, JSON.stringify(s, null, 2) + "\n");
|
|
10178
|
-
} catch {
|
|
10179
|
-
}
|
|
10180
|
-
}
|
|
10181
|
-
function installGlobalQuiet() {
|
|
10182
|
-
try {
|
|
10183
|
-
const p = globalPaths();
|
|
10184
|
-
let apiKey = process.env["SOLONGATE_API_KEY"] || "";
|
|
10185
|
-
let apiUrl = process.env["SOLONGATE_API_URL"] || "https://api.solongate.com";
|
|
10186
|
-
try {
|
|
10187
|
-
const cfg = JSON.parse(readFileSync9(p.configPath, "utf-8"));
|
|
10188
|
-
if (cfg && typeof cfg.apiKey === "string") apiKey = apiKey || cfg.apiKey;
|
|
10189
|
-
if (cfg && typeof cfg.apiUrl === "string") apiUrl = cfg.apiUrl;
|
|
10190
|
-
} catch {
|
|
10191
|
-
}
|
|
10192
|
-
if (!apiKey) {
|
|
10193
|
-
const acc = firstAccountCredential();
|
|
10194
|
-
if (acc.apiKey) {
|
|
10195
|
-
apiKey = acc.apiKey;
|
|
10196
|
-
if (acc.apiUrl) apiUrl = acc.apiUrl;
|
|
10197
|
-
}
|
|
10198
|
-
}
|
|
10199
|
-
if (!apiKey) return { ok: false, message: "no login on this device \u2014 add an account first (Accounts \u2192 + add)" };
|
|
10200
|
-
mkdirSync8(p.hooksDir, { recursive: true });
|
|
10201
|
-
mkdirSync8(p.claudeDir, { recursive: true });
|
|
10202
|
-
unlockProtected();
|
|
10203
|
-
writeFileSync9(join11(p.hooksDir, "guard.mjs"), readGuard());
|
|
10204
|
-
writeFileSync9(join11(p.hooksDir, "audit.mjs"), readHook("audit.mjs"));
|
|
10205
|
-
writeFileSync9(join11(p.hooksDir, "stop.mjs"), readHook("stop.mjs"));
|
|
10206
|
-
writeFileSync9(join11(p.hooksDir, "shield.mjs"), readHook("shield.mjs"));
|
|
10207
|
-
writeFileSync9(p.configPath, JSON.stringify({ apiKey, apiUrl }, null, 2) + "\n");
|
|
10208
|
-
let existing = {};
|
|
10209
|
-
if (existsSync4(p.settingsPath)) {
|
|
10210
|
-
const raw = readFileSync9(p.settingsPath, "utf-8");
|
|
10211
|
-
if (!existsSync4(p.backupPath)) writeFileSync9(p.backupPath, raw);
|
|
10212
|
-
try {
|
|
10213
|
-
existing = JSON.parse(raw);
|
|
10214
|
-
} catch {
|
|
10215
|
-
existing = {};
|
|
10216
|
-
}
|
|
10217
|
-
}
|
|
10218
|
-
const nodeBin = process.execPath.replace(/\\/g, "/");
|
|
10219
|
-
const call = process.platform === "win32" ? "& " : "";
|
|
10220
|
-
const hookCmd = (script) => `${call}"${nodeBin}" "${join11(p.hooksDir, script).replace(/\\/g, "/")}" claude-code "Claude Code"`;
|
|
10221
|
-
const merged = {
|
|
10222
|
-
...existing,
|
|
10223
|
-
hooks: {
|
|
10224
|
-
PreToolUse: [{ matcher: "", hooks: [{ type: "command", command: hookCmd("guard.mjs") }] }],
|
|
10225
|
-
PostToolUse: [{ matcher: "", hooks: [{ type: "command", command: hookCmd("audit.mjs") }] }],
|
|
10226
|
-
Stop: [{ matcher: "", hooks: [{ type: "command", command: hookCmd("stop.mjs") }] }]
|
|
10227
|
-
}
|
|
10228
|
-
};
|
|
10229
|
-
writeFileSync9(p.settingsPath, JSON.stringify(merged, null, 2) + "\n");
|
|
10230
|
-
try {
|
|
10231
|
-
installAntigravityGuard(p, join11(p.hooksDir, "guard.mjs").replace(/\\/g, "/"));
|
|
10232
|
-
} catch {
|
|
10233
|
-
}
|
|
10234
|
-
if (process.env["SOLONGATE_OS_LOCK"] === "1") lockProtected();
|
|
10235
|
-
return { ok: true, message: "guard installed (open a new session)" };
|
|
10236
|
-
} catch (e) {
|
|
10237
|
-
return { ok: false, message: e instanceof Error ? e.message : String(e) };
|
|
10238
|
-
}
|
|
10239
|
-
}
|
|
10240
|
-
function installedGuardVersion() {
|
|
10241
|
-
try {
|
|
10242
|
-
const p = globalPaths();
|
|
10243
|
-
const s = readFileSync9(join11(p.hooksDir, "guard.mjs"), "utf-8");
|
|
10244
|
-
const m = s.match(/HOOK_VERSION\s*=\s*(\d+)/);
|
|
10245
|
-
return m ? parseInt(m[1], 10) : null;
|
|
10246
|
-
} catch {
|
|
10247
|
-
return null;
|
|
10248
|
-
}
|
|
10249
|
-
}
|
|
10250
|
-
function guardHookOutdated() {
|
|
10251
|
-
try {
|
|
10252
|
-
const p = globalPaths();
|
|
10253
|
-
return readFileSync9(join11(p.hooksDir, "guard.mjs"), "utf-8") !== readGuard();
|
|
10254
|
-
} catch {
|
|
10255
|
-
return false;
|
|
10256
|
-
}
|
|
10257
|
-
}
|
|
10258
|
-
function isGuardInstalled() {
|
|
10259
|
-
try {
|
|
10260
|
-
const p = globalPaths();
|
|
10261
|
-
if (!existsSync4(p.settingsPath)) return false;
|
|
10262
|
-
const s = JSON.parse(readFileSync9(p.settingsPath, "utf-8"));
|
|
10263
|
-
return !!s.hooks && JSON.stringify(s.hooks).includes(".solongate");
|
|
10264
|
-
} catch {
|
|
10265
|
-
return false;
|
|
10266
|
-
}
|
|
10267
|
-
}
|
|
10268
|
-
function uninstallGlobalQuiet() {
|
|
10269
|
-
try {
|
|
10270
|
-
const p = globalPaths();
|
|
10271
|
-
unlockProtected();
|
|
10272
|
-
removeClaudeShim();
|
|
10273
|
-
try {
|
|
10274
|
-
removeAntigravityGuard(p);
|
|
10275
|
-
} catch {
|
|
10276
|
-
}
|
|
10277
|
-
if (!existsSync4(p.settingsPath)) return { ok: true, message: "guard removed (open a new session)" };
|
|
10278
|
-
const s = JSON.parse(readFileSync9(p.settingsPath, "utf-8"));
|
|
10279
|
-
delete s.hooks;
|
|
10280
|
-
writeFileSync9(p.settingsPath, JSON.stringify(s, null, 2) + "\n");
|
|
10281
|
-
return { ok: true, message: "guard removed (open a new session)" };
|
|
10282
|
-
} catch (e) {
|
|
10283
|
-
return { ok: false, message: e instanceof Error ? e.message : String(e) };
|
|
10284
|
-
}
|
|
10285
|
-
}
|
|
10286
|
-
function escapeRe(s) {
|
|
10287
|
-
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
10288
|
-
}
|
|
10289
|
-
function shimTargets() {
|
|
10290
|
-
if (process.platform === "win32") {
|
|
10291
|
-
try {
|
|
10292
|
-
const prof = execFileSync2("powershell", ["-NoProfile", "-Command", "$PROFILE.CurrentUserAllHosts"], { encoding: "utf-8" }).trim();
|
|
10293
|
-
return prof ? [prof] : [];
|
|
10294
|
-
} catch {
|
|
10295
|
-
return [];
|
|
10296
|
-
}
|
|
10297
|
-
}
|
|
10298
|
-
return [".bashrc", ".zshrc", ".profile"].map((f) => join11(homedir9(), f)).filter((f) => existsSync4(f));
|
|
10299
|
-
}
|
|
10300
|
-
function writeShimBlock(file, block2) {
|
|
10301
|
-
const re = new RegExp(escapeRe(SHIM_BEGIN) + "[\\s\\S]*?" + escapeRe(SHIM_END) + "\\r?\\n?", "g");
|
|
10302
|
-
let content = existsSync4(file) ? readFileSync9(file, "utf-8") : "";
|
|
10303
|
-
content = content.replace(re, "");
|
|
10304
|
-
if (block2) {
|
|
10305
|
-
if (content.length && !content.endsWith("\n")) content += "\n";
|
|
10306
|
-
content += block2 + "\n";
|
|
10307
|
-
}
|
|
10308
|
-
mkdirSync8(dirname3(file), { recursive: true });
|
|
10309
|
-
writeFileSync9(file, content);
|
|
10310
|
-
}
|
|
10311
|
-
function removeClaudeShim() {
|
|
10312
|
-
for (const file of shimTargets()) {
|
|
10313
|
-
try {
|
|
10314
|
-
writeShimBlock(file, null);
|
|
10315
|
-
} catch {
|
|
10316
|
-
}
|
|
10317
|
-
}
|
|
10318
|
-
}
|
|
10319
|
-
var __dirname, HOOKS_DIR, ANTIGRAVITY_GROUP, SHIM_BEGIN, SHIM_END;
|
|
10320
|
-
var init_global_install = __esm({
|
|
10321
|
-
"src/global-install.ts"() {
|
|
10322
|
-
"use strict";
|
|
10323
|
-
__dirname = dirname3(fileURLToPath3(import.meta.url));
|
|
10324
|
-
HOOKS_DIR = resolve4(__dirname, "..", "hooks");
|
|
10325
|
-
ANTIGRAVITY_GROUP = "solongate-guard";
|
|
10326
|
-
SHIM_BEGIN = "# >>> SolonGate shield (auto secret redaction) >>>";
|
|
10327
|
-
SHIM_END = "# <<< SolonGate shield <<<";
|
|
10328
|
-
}
|
|
10329
|
-
});
|
|
10330
|
-
|
|
10331
10524
|
// src/tui/panels/Settings.tsx
|
|
10332
10525
|
import { Box as Box8, Text as Text8, useInput as useInput7 } from "ink";
|
|
10333
10526
|
import TextInput6 from "ink-text-input";
|
|
@@ -15862,7 +16055,7 @@ ${msg.content.text}`;
|
|
|
15862
16055
|
|
|
15863
16056
|
// src/index.ts
|
|
15864
16057
|
init_cli_utils();
|
|
15865
|
-
var CLI_SUBCOMMANDS = /* @__PURE__ */ new Set(["logs-server", "local-logs", "policy", "ratelimit", "dlp", "stats", "audit", "sessions", "session", "doctor", "watch", "alerts", "webhooks", "dataroom"]);
|
|
16058
|
+
var CLI_SUBCOMMANDS = /* @__PURE__ */ new Set(["update", "logs-server", "local-logs", "policy", "ratelimit", "dlp", "stats", "audit", "sessions", "session", "doctor", "watch", "alerts", "webhooks", "dataroom"]);
|
|
15866
16059
|
var CLI_INFO_ARGS = /* @__PURE__ */ new Set(["login", "help", "--help", "-h", "--version", "-v", "version"]);
|
|
15867
16060
|
var IS_HUMAN_CLI = process.argv.length <= 2 || CLI_SUBCOMMANDS.has(process.argv[2] ?? "") || CLI_INFO_ARGS.has(process.argv[2] ?? "");
|
|
15868
16061
|
if (!IS_HUMAN_CLI) {
|
|
@@ -15923,6 +16116,7 @@ function printHelp() {
|
|
|
15923
16116
|
console.log(` ${c.dim}Usage:${c.reset} ${c.cyan}solongate${c.reset} ${c.dim}[command]${c.reset} ${c.dim}(no command opens the dataroom: all of this in a terminal UI)${c.reset}`);
|
|
15924
16117
|
head("Setup & status");
|
|
15925
16118
|
cmd("solongate", "open the dataroom UI (login, policies, audit, settings)");
|
|
16119
|
+
cmd("update", "update SolonGate to the newest version and refresh the guard");
|
|
15926
16120
|
cmd("doctor", "health check: login, policy, guard, local logs");
|
|
15927
16121
|
cmd("doctor --json", "the same health check as machine-readable JSON");
|
|
15928
16122
|
cmd("logs-server start", "start the local audit-log service for the dashboard (background)");
|
|
@@ -16018,6 +16212,10 @@ async function main() {
|
|
|
16018
16212
|
console.log("");
|
|
16019
16213
|
return;
|
|
16020
16214
|
}
|
|
16215
|
+
if (subcommand === "update") {
|
|
16216
|
+
const { runUpdateCommand: runUpdateCommand2 } = await Promise.resolve().then(() => (init_self_update(), self_update_exports));
|
|
16217
|
+
process.exit(await runUpdateCommand2());
|
|
16218
|
+
}
|
|
16021
16219
|
if (subcommand === "logs-server" || subcommand === "local-logs") {
|
|
16022
16220
|
const { runLogsServer: runLogsServer2 } = await Promise.resolve().then(() => (init_logs_server(), logs_server_exports));
|
|
16023
16221
|
await runLogsServer2();
|