@solongate/proxy 0.81.36 → 0.81.37
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/api-client/client.d.ts +11 -0
- package/dist/commands/index.js +3 -1
- package/dist/index.js +104 -43
- package/dist/login.js +24 -0
- package/dist/tui/index.js +49 -11
- package/package.json +1 -1
|
@@ -3,6 +3,17 @@ export interface Credentials {
|
|
|
3
3
|
apiKey: string;
|
|
4
4
|
apiUrl: string;
|
|
5
5
|
}
|
|
6
|
+
export interface SavedAccount {
|
|
7
|
+
apiKey: string;
|
|
8
|
+
apiUrl: string;
|
|
9
|
+
project?: string;
|
|
10
|
+
user?: string;
|
|
11
|
+
addedAt?: number;
|
|
12
|
+
}
|
|
13
|
+
export declare function listAccounts(): SavedAccount[];
|
|
14
|
+
/** Upsert an account (dedupe by apiKey). Called from `login`. */
|
|
15
|
+
export declare function saveAccount(acc: SavedAccount): void;
|
|
16
|
+
export declare function setViewCredentials(creds: Credentials | null): void;
|
|
6
17
|
/**
|
|
7
18
|
* Thrown for any non-2xx response. `code`/`message` come from the API's
|
|
8
19
|
* `{ error: { code, message } }` envelope when present; `status` is the HTTP
|
package/dist/commands/index.js
CHANGED
|
@@ -5,10 +5,11 @@ var __export = (target, all) => {
|
|
|
5
5
|
};
|
|
6
6
|
|
|
7
7
|
// src/api-client/client.ts
|
|
8
|
-
import { readFileSync, existsSync } from "fs";
|
|
8
|
+
import { readFileSync, writeFileSync, mkdirSync, existsSync } from "fs";
|
|
9
9
|
import { resolve, join } from "path";
|
|
10
10
|
import { homedir } from "os";
|
|
11
11
|
var DEFAULT_API_URL = "https://api.solongate.com";
|
|
12
|
+
var viewOverride = null;
|
|
12
13
|
var ApiError = class extends Error {
|
|
13
14
|
status;
|
|
14
15
|
code;
|
|
@@ -62,6 +63,7 @@ function isAuthenticated() {
|
|
|
62
63
|
}
|
|
63
64
|
}
|
|
64
65
|
function resolveCredentials(apiUrlOverride) {
|
|
66
|
+
if (viewOverride && !apiUrlOverride) return viewOverride;
|
|
65
67
|
if (cached && !apiUrlOverride) return cached;
|
|
66
68
|
const file = loginCredentialFile();
|
|
67
69
|
const apiKey = process.env["SOLONGATE_API_KEY"] || file.apiKey || dotenvApiKey();
|
package/dist/index.js
CHANGED
|
@@ -6561,12 +6561,49 @@ __export(client_exports, {
|
|
|
6561
6561
|
DEFAULT_API_URL: () => DEFAULT_API_URL2,
|
|
6562
6562
|
NotAuthenticatedError: () => NotAuthenticatedError,
|
|
6563
6563
|
isAuthenticated: () => isAuthenticated,
|
|
6564
|
+
listAccounts: () => listAccounts,
|
|
6564
6565
|
request: () => request,
|
|
6565
|
-
resolveCredentials: () => resolveCredentials
|
|
6566
|
+
resolveCredentials: () => resolveCredentials,
|
|
6567
|
+
saveAccount: () => saveAccount,
|
|
6568
|
+
setViewCredentials: () => setViewCredentials
|
|
6566
6569
|
});
|
|
6567
|
-
import { readFileSync as readFileSync4, existsSync as existsSync3 } from "fs";
|
|
6570
|
+
import { readFileSync as readFileSync4, writeFileSync as writeFileSync3, mkdirSync as mkdirSync3, existsSync as existsSync3 } from "fs";
|
|
6568
6571
|
import { resolve as resolve3, join as join4 } from "path";
|
|
6569
6572
|
import { homedir as homedir2 } from "os";
|
|
6573
|
+
function listAccounts() {
|
|
6574
|
+
let list6 = [];
|
|
6575
|
+
try {
|
|
6576
|
+
const raw = JSON.parse(readFileSync4(accountsFile(), "utf-8"));
|
|
6577
|
+
if (Array.isArray(raw)) list6 = raw.filter((a) => a && typeof a.apiKey === "string");
|
|
6578
|
+
} catch {
|
|
6579
|
+
}
|
|
6580
|
+
const active2 = loginCredentialFile();
|
|
6581
|
+
if (active2.apiKey && !list6.some((a) => a.apiKey === active2.apiKey)) {
|
|
6582
|
+
list6.unshift({ apiKey: active2.apiKey, apiUrl: active2.apiUrl || DEFAULT_API_URL2 });
|
|
6583
|
+
}
|
|
6584
|
+
return list6;
|
|
6585
|
+
}
|
|
6586
|
+
function saveAccount(acc) {
|
|
6587
|
+
try {
|
|
6588
|
+
const list6 = (() => {
|
|
6589
|
+
try {
|
|
6590
|
+
const raw = JSON.parse(readFileSync4(accountsFile(), "utf-8"));
|
|
6591
|
+
return Array.isArray(raw) ? raw.filter((a) => a && a.apiKey) : [];
|
|
6592
|
+
} catch {
|
|
6593
|
+
return [];
|
|
6594
|
+
}
|
|
6595
|
+
})();
|
|
6596
|
+
const next = list6.filter((a) => a.apiKey !== acc.apiKey);
|
|
6597
|
+
next.unshift({ ...acc, addedAt: acc.addedAt ?? Date.now() });
|
|
6598
|
+
mkdirSync3(join4(homedir2(), ".solongate"), { recursive: true });
|
|
6599
|
+
writeFileSync3(accountsFile(), JSON.stringify(next, null, 2));
|
|
6600
|
+
} catch {
|
|
6601
|
+
}
|
|
6602
|
+
}
|
|
6603
|
+
function setViewCredentials(creds) {
|
|
6604
|
+
viewOverride = creds;
|
|
6605
|
+
cached = null;
|
|
6606
|
+
}
|
|
6570
6607
|
function loginCredentialFile() {
|
|
6571
6608
|
try {
|
|
6572
6609
|
const p = join4(homedir2(), ".solongate", "cloud-guard.json");
|
|
@@ -6603,6 +6640,7 @@ function isAuthenticated() {
|
|
|
6603
6640
|
}
|
|
6604
6641
|
}
|
|
6605
6642
|
function resolveCredentials(apiUrlOverride) {
|
|
6643
|
+
if (viewOverride && !apiUrlOverride) return viewOverride;
|
|
6606
6644
|
if (cached && !apiUrlOverride) return cached;
|
|
6607
6645
|
const file = loginCredentialFile();
|
|
6608
6646
|
const apiKey = process.env["SOLONGATE_API_KEY"] || file.apiKey || dotenvApiKey();
|
|
@@ -6677,11 +6715,13 @@ async function request(method, path, opts = {}) {
|
|
|
6677
6715
|
}
|
|
6678
6716
|
return json;
|
|
6679
6717
|
}
|
|
6680
|
-
var DEFAULT_API_URL2, ApiError, NotAuthenticatedError, cached;
|
|
6718
|
+
var DEFAULT_API_URL2, accountsFile, viewOverride, ApiError, NotAuthenticatedError, cached;
|
|
6681
6719
|
var init_client = __esm({
|
|
6682
6720
|
"src/api-client/client.ts"() {
|
|
6683
6721
|
"use strict";
|
|
6684
6722
|
DEFAULT_API_URL2 = "https://api.solongate.com";
|
|
6723
|
+
accountsFile = () => join4(homedir2(), ".solongate", "accounts.json");
|
|
6724
|
+
viewOverride = null;
|
|
6685
6725
|
ApiError = class extends Error {
|
|
6686
6726
|
status;
|
|
6687
6727
|
code;
|
|
@@ -6836,7 +6876,7 @@ var init_components = __esm({
|
|
|
6836
6876
|
});
|
|
6837
6877
|
|
|
6838
6878
|
// src/tui/local-log.ts
|
|
6839
|
-
import { closeSync, openSync, readFileSync as readFileSync6, readSync, statSync, writeFileSync as
|
|
6879
|
+
import { closeSync, openSync, readFileSync as readFileSync6, readSync, statSync, writeFileSync as writeFileSync4 } from "fs";
|
|
6840
6880
|
import { homedir as homedir4 } from "os";
|
|
6841
6881
|
import { join as join6 } from "path";
|
|
6842
6882
|
function tailLines(file, maxBytes = 131072) {
|
|
@@ -6872,7 +6912,7 @@ function deleteLocalEntry(at, tool, session) {
|
|
|
6872
6912
|
}
|
|
6873
6913
|
return true;
|
|
6874
6914
|
});
|
|
6875
|
-
if (removed)
|
|
6915
|
+
if (removed) writeFileSync4(LOCAL_LOG, kept.length ? kept.join("\n") + "\n" : "");
|
|
6876
6916
|
return removed;
|
|
6877
6917
|
} catch {
|
|
6878
6918
|
return 0;
|
|
@@ -6881,7 +6921,7 @@ function deleteLocalEntry(at, tool, session) {
|
|
|
6881
6921
|
function clearLocalLog() {
|
|
6882
6922
|
try {
|
|
6883
6923
|
const n = readFileSync6(LOCAL_LOG, "utf-8").split("\n").filter(Boolean).length;
|
|
6884
|
-
|
|
6924
|
+
writeFileSync4(LOCAL_LOG, "");
|
|
6885
6925
|
return n;
|
|
6886
6926
|
} catch {
|
|
6887
6927
|
return 0;
|
|
@@ -7310,7 +7350,7 @@ var init_hooks = __esm({
|
|
|
7310
7350
|
// src/tui/panels/Live.tsx
|
|
7311
7351
|
import { Box as Box2, Text as Text2, useInput } from "ink";
|
|
7312
7352
|
import TextInput from "ink-text-input";
|
|
7313
|
-
import { mkdirSync as
|
|
7353
|
+
import { mkdirSync as mkdirSync4, writeFileSync as writeFileSync5 } from "fs";
|
|
7314
7354
|
import { homedir as homedir5 } from "os";
|
|
7315
7355
|
import { join as join7 } from "path";
|
|
7316
7356
|
import { useCallback as useCallback2, useEffect as useEffect2, useRef as useRef2, useState as useState2 } from "react";
|
|
@@ -7861,8 +7901,8 @@ function LivePanel({ active: active2 }) {
|
|
|
7861
7901
|
else if (input === "e") {
|
|
7862
7902
|
const file = join7(homedir5(), ".solongate", "live-export.jsonl");
|
|
7863
7903
|
try {
|
|
7864
|
-
|
|
7865
|
-
|
|
7904
|
+
mkdirSync4(join7(homedir5(), ".solongate"), { recursive: true });
|
|
7905
|
+
writeFileSync5(file, visibleDesc.map((x) => JSON.stringify(x)).join("\n") + "\n");
|
|
7866
7906
|
setActionMsg({ text: `\u2713 exported ${visibleDesc.length} lines \u2192 ${file}`, level: "ok", until: Date.now() + 6e3 });
|
|
7867
7907
|
} catch (err2) {
|
|
7868
7908
|
setActionMsg({ text: "\u2717 export failed: " + (err2 instanceof Error ? err2.message : String(err2)), level: "bad", until: Date.now() + 6e3 });
|
|
@@ -8880,7 +8920,7 @@ var init_Dlp = __esm({
|
|
|
8880
8920
|
// src/tui/panels/Audit.tsx
|
|
8881
8921
|
import { Box as Box6, Text as Text6, useInput as useInput5 } from "ink";
|
|
8882
8922
|
import TextInput4 from "ink-text-input";
|
|
8883
|
-
import { mkdirSync as
|
|
8923
|
+
import { mkdirSync as mkdirSync5, writeFileSync as writeFileSync6 } from "fs";
|
|
8884
8924
|
import { homedir as homedir6 } from "os";
|
|
8885
8925
|
import { join as join8 } from "path";
|
|
8886
8926
|
import { useState as useState6 } from "react";
|
|
@@ -9044,8 +9084,8 @@ function AuditPanel({ active: active2, focused }) {
|
|
|
9044
9084
|
const r = await api.audit.list({ ...query, limit: 1e4, offset: 0 });
|
|
9045
9085
|
rows2 = r.entries.map(cloudRow).sort((a, b) => b.at - a.at);
|
|
9046
9086
|
} else rows2 = localFiltered;
|
|
9047
|
-
|
|
9048
|
-
|
|
9087
|
+
mkdirSync5(dir, { recursive: true });
|
|
9088
|
+
writeFileSync6(file, rows2.map((x) => JSON.stringify(x)).join("\n") + (rows2.length ? "\n" : ""));
|
|
9049
9089
|
return { n: rows2.length, file };
|
|
9050
9090
|
};
|
|
9051
9091
|
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" }));
|
|
@@ -9781,6 +9821,17 @@ function App() {
|
|
|
9781
9821
|
const [section, setSection] = useState8(0);
|
|
9782
9822
|
const [focus, setFocus] = useState8("nav");
|
|
9783
9823
|
const [help, setHelp] = useState8(false);
|
|
9824
|
+
const [accounts] = useState8(() => listAccounts());
|
|
9825
|
+
const [acctIdx, setAcctIdx] = useState8(0);
|
|
9826
|
+
const cur = accounts[acctIdx];
|
|
9827
|
+
const acctLabel = cur ? cur.project || cur.user || cur.apiKey.slice(0, 8) : "\u2014";
|
|
9828
|
+
const switchAccount = () => {
|
|
9829
|
+
if (accounts.length < 2) return;
|
|
9830
|
+
const next = (acctIdx + 1) % accounts.length;
|
|
9831
|
+
const a = accounts[next];
|
|
9832
|
+
setViewCredentials({ apiKey: a.apiKey, apiUrl: a.apiUrl });
|
|
9833
|
+
setAcctIdx(next);
|
|
9834
|
+
};
|
|
9784
9835
|
useInput7((input, key) => {
|
|
9785
9836
|
if (help) {
|
|
9786
9837
|
setHelp(false);
|
|
@@ -9794,6 +9845,7 @@ function App() {
|
|
|
9794
9845
|
if (key.upArrow) setSection((n) => (n - 1 + SECTIONS.length) % SECTIONS.length);
|
|
9795
9846
|
else if (key.downArrow) setSection((n) => (n + 1) % SECTIONS.length);
|
|
9796
9847
|
else if (key.rightArrow || key.return || key.tab) setFocus("panel");
|
|
9848
|
+
else if (input === "a") switchAccount();
|
|
9797
9849
|
else if (input === "q") exit();
|
|
9798
9850
|
} else {
|
|
9799
9851
|
if (key.escape || key.tab) setFocus("nav");
|
|
@@ -9804,16 +9856,21 @@ function App() {
|
|
|
9804
9856
|
const current = SECTIONS[section];
|
|
9805
9857
|
if (help) return /* @__PURE__ */ jsx8(HelpOverlay, { cols, rows });
|
|
9806
9858
|
if (current.label === "Live" && focus === "panel") {
|
|
9807
|
-
return /* @__PURE__ */ jsx8(Box8, { flexDirection: "column", width: cols, height: rows, children: /* @__PURE__ */ jsx8(LivePanel, { active: true, focused: true }) });
|
|
9859
|
+
return /* @__PURE__ */ jsx8(Box8, { flexDirection: "column", width: cols, height: rows, children: /* @__PURE__ */ jsx8(LivePanel, { active: true, focused: true }, acctIdx) });
|
|
9808
9860
|
}
|
|
9809
9861
|
const Panel = current.Panel;
|
|
9810
9862
|
return /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", width: cols, height: rows, paddingX: 1, paddingTop: 1, children: [
|
|
9811
9863
|
/* @__PURE__ */ jsx8(Banner, { cols }),
|
|
9864
|
+
/* @__PURE__ */ jsxs8(Text8, { wrap: "truncate", children: [
|
|
9865
|
+
/* @__PURE__ */ jsx8(Text8, { color: theme.dim, children: "account: " }),
|
|
9866
|
+
/* @__PURE__ */ jsx8(Text8, { color: theme.accentBright, bold: true, children: acctLabel }),
|
|
9867
|
+
accounts.length > 1 ? /* @__PURE__ */ jsx8(Text8, { color: theme.dim, children: ` (${acctIdx + 1}/${accounts.length} \xB7 a switch)` }) : null
|
|
9868
|
+
] }),
|
|
9812
9869
|
/* @__PURE__ */ jsxs8(Box8, { marginTop: 1, flexGrow: 1, children: [
|
|
9813
9870
|
/* @__PURE__ */ jsx8(Box8, { flexDirection: "column", width: 16, borderStyle: "round", borderColor: focus === "nav" ? theme.accent : "gray", paddingX: 1, children: SECTIONS.map((s, i) => /* @__PURE__ */ jsx8(Text8, { color: i === section ? theme.accentBright : void 0, bold: i === section, children: (i === section ? "\u25B8 " : " ") + s.label }, s.label)) }),
|
|
9814
9871
|
/* @__PURE__ */ jsx8(Box8, { flexGrow: 1, borderStyle: "round", borderColor: focus === "panel" ? theme.accent : "gray", paddingX: 1, paddingY: 0, children: /* @__PURE__ */ jsx8(Panel, { active: focus === "panel" || current.label !== "Live", focused: focus === "panel" }) })
|
|
9815
|
-
] }),
|
|
9816
|
-
/* @__PURE__ */ jsx8(Box8, { children: focus === "nav" ? /* @__PURE__ */ jsx8(KeyHints, { hints: [["\u2191\u2193", "section"], ["\u2192/enter", "open"], ["?", "help"], ["q", "quit"]] }) : /* @__PURE__ */ jsx8(KeyHints, { hints: [["\u2190/esc", "back"], ["\u2191\u2193", "in-panel"], ["space/s", "act"]] }) })
|
|
9872
|
+
] }, acctIdx),
|
|
9873
|
+
/* @__PURE__ */ jsx8(Box8, { children: 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"]] }) })
|
|
9817
9874
|
] });
|
|
9818
9875
|
}
|
|
9819
9876
|
function HelpOverlay({ cols, rows }) {
|
|
@@ -9843,6 +9900,7 @@ var init_App = __esm({
|
|
|
9843
9900
|
init_Audit();
|
|
9844
9901
|
init_Settings();
|
|
9845
9902
|
init_hooks();
|
|
9903
|
+
init_client();
|
|
9846
9904
|
SECTIONS = [
|
|
9847
9905
|
{ label: "Live", Panel: LiveHint },
|
|
9848
9906
|
{ label: "Policies", Panel: PoliciesPanel },
|
|
@@ -9858,7 +9916,8 @@ var init_App = __esm({
|
|
|
9858
9916
|
["Policies", [["\u2191\u2193", "browse / select"], ["a", "activate (pin) selected policy"], ["x", "deactivate \u2014 no active policy"], ["enter", "open rules \u2192 open a rule"], ["space", "toggle a rule on/off"], ["e", "flip effect"], ["n", "new rule"], ["d", "delete rule"], ["m", "flip mode"], ["D", "dry-run the draft"], ["s", "save"], ["x", "discard"]]],
|
|
9859
9917
|
["Rate limit / DLP", [["\u2191\u2193", "field / pattern"], ["\u2190\u2192", "adjust (shift = \xB110)"], ["space", "toggle pattern"], ["m", "mode"], ["a / d", "add / remove custom"], ["g", "ghost mode"], ["P", "self-protection"], ["s", "save"]]],
|
|
9860
9918
|
["Audit", [["v", "logs \u2194 sessions"], ["s", "source: cloud \u2194 local"], ["\u2190 \u2192", "prev / next page (500 each)"], ["\u2191\u2193", "select (list scrolls)"], ["enter", "full entry / session logs"], ["f / g", "decision / signal filter"], ["t / n / /", "tool / agent / search"], ["x / X", "delete entry / ALL (press twice)"], ["c", "clear filters"]]],
|
|
9861
|
-
["Settings", [["\u2191\u2193", "move"], ["enter / space", "toggle \xB7 edit \xB7 add"], ["e", "webhook events"], ["d d", "delete"], ["r", "refresh"]]]
|
|
9919
|
+
["Settings", [["\u2191\u2193", "move"], ["enter / space", "toggle \xB7 edit \xB7 add"], ["e", "webhook events"], ["d d", "delete"], ["r", "refresh"]]],
|
|
9920
|
+
["Accounts", [["a", "switch account (view another account logged in on this device)"], ["", "the header shows which account you are viewing; guard/logging keep the active key"]]]
|
|
9862
9921
|
];
|
|
9863
9922
|
}
|
|
9864
9923
|
});
|
|
@@ -11063,7 +11122,7 @@ __export(global_install_exports, {
|
|
|
11063
11122
|
runGlobalRestore: () => runGlobalRestore,
|
|
11064
11123
|
unlockProtected: () => unlockProtected
|
|
11065
11124
|
});
|
|
11066
|
-
import { readFileSync as readFileSync8, writeFileSync as
|
|
11125
|
+
import { readFileSync as readFileSync8, writeFileSync as writeFileSync7, existsSync as existsSync6, mkdirSync as mkdirSync6 } from "fs";
|
|
11067
11126
|
import { resolve as resolve4, join as join11, dirname } from "path";
|
|
11068
11127
|
import { homedir as homedir9 } from "os";
|
|
11069
11128
|
import { fileURLToPath } from "url";
|
|
@@ -11176,13 +11235,13 @@ function runGlobalRestore() {
|
|
|
11176
11235
|
unlockProtected();
|
|
11177
11236
|
removeClaudeShim();
|
|
11178
11237
|
if (existsSync6(p.backupPath)) {
|
|
11179
|
-
|
|
11238
|
+
writeFileSync7(p.settingsPath, readFileSync8(p.backupPath, "utf-8"));
|
|
11180
11239
|
console.log(` Restored ${p.settingsPath} from backup.`);
|
|
11181
11240
|
} else if (existsSync6(p.settingsPath)) {
|
|
11182
11241
|
try {
|
|
11183
11242
|
const s = JSON.parse(readFileSync8(p.settingsPath, "utf-8"));
|
|
11184
11243
|
delete s.hooks;
|
|
11185
|
-
|
|
11244
|
+
writeFileSync7(p.settingsPath, JSON.stringify(s, null, 2) + "\n");
|
|
11186
11245
|
console.log(` Removed SolonGate hooks from ${p.settingsPath}.`);
|
|
11187
11246
|
} catch {
|
|
11188
11247
|
}
|
|
@@ -11226,8 +11285,8 @@ function writeShimBlock(file, block2) {
|
|
|
11226
11285
|
if (content.length && !content.endsWith("\n")) content += "\n";
|
|
11227
11286
|
content += block2 + "\n";
|
|
11228
11287
|
}
|
|
11229
|
-
|
|
11230
|
-
|
|
11288
|
+
mkdirSync6(dirname(file), { recursive: true });
|
|
11289
|
+
writeFileSync7(file, content);
|
|
11231
11290
|
}
|
|
11232
11291
|
function installClaudeShim(shieldPath) {
|
|
11233
11292
|
const real = resolveRealClaude();
|
|
@@ -11278,22 +11337,22 @@ async function runGlobalInstall(opts = {}) {
|
|
|
11278
11337
|
process.exit(1);
|
|
11279
11338
|
}
|
|
11280
11339
|
const apiUrl = opts.apiUrl || process.env["SOLONGATE_API_URL"] || "https://api.solongate.com";
|
|
11281
|
-
|
|
11282
|
-
|
|
11340
|
+
mkdirSync6(p.hooksDir, { recursive: true });
|
|
11341
|
+
mkdirSync6(p.claudeDir, { recursive: true });
|
|
11283
11342
|
unlockProtected();
|
|
11284
|
-
|
|
11285
|
-
|
|
11286
|
-
|
|
11287
|
-
|
|
11343
|
+
writeFileSync7(join11(p.hooksDir, "guard.mjs"), readGuard());
|
|
11344
|
+
writeFileSync7(join11(p.hooksDir, "audit.mjs"), readHook("audit.mjs"));
|
|
11345
|
+
writeFileSync7(join11(p.hooksDir, "stop.mjs"), readHook("stop.mjs"));
|
|
11346
|
+
writeFileSync7(join11(p.hooksDir, "shield.mjs"), readHook("shield.mjs"));
|
|
11288
11347
|
console.log(` Installed hooks \u2192 ${p.hooksDir}`);
|
|
11289
11348
|
installClaudeShim(join11(p.hooksDir, "shield.mjs"));
|
|
11290
|
-
|
|
11349
|
+
writeFileSync7(p.configPath, JSON.stringify({ apiKey, apiUrl }, null, 2) + "\n");
|
|
11291
11350
|
console.log(` Wrote ${p.configPath}`);
|
|
11292
11351
|
let existing = {};
|
|
11293
11352
|
if (existsSync6(p.settingsPath)) {
|
|
11294
11353
|
const raw = readFileSync8(p.settingsPath, "utf-8");
|
|
11295
11354
|
if (!existsSync6(p.backupPath)) {
|
|
11296
|
-
|
|
11355
|
+
writeFileSync7(p.backupPath, raw);
|
|
11297
11356
|
console.log(` Backed up existing settings \u2192 ${p.backupPath}`);
|
|
11298
11357
|
}
|
|
11299
11358
|
try {
|
|
@@ -11316,7 +11375,7 @@ async function runGlobalInstall(opts = {}) {
|
|
|
11316
11375
|
Stop: [{ matcher: "", hooks: [{ type: "command", command: hookCmd(stopAbs) }] }]
|
|
11317
11376
|
}
|
|
11318
11377
|
};
|
|
11319
|
-
|
|
11378
|
+
writeFileSync7(p.settingsPath, JSON.stringify(merged, null, 2) + "\n");
|
|
11320
11379
|
console.log(` Registered global hooks \u2192 ${p.settingsPath}`);
|
|
11321
11380
|
if (process.env["SOLONGATE_OS_LOCK"] === "1") {
|
|
11322
11381
|
lockProtected();
|
|
@@ -11434,6 +11493,7 @@ async function main() {
|
|
|
11434
11493
|
if (data?.project?.name) {
|
|
11435
11494
|
console.log(` ${c.dim}Project:${c.reset} ${c.cyan}${data.project.name}${c.reset}`);
|
|
11436
11495
|
}
|
|
11496
|
+
saveAccount({ apiKey, apiUrl, project: data?.project?.name, user: data?.user?.name || data?.user?.email });
|
|
11437
11497
|
break;
|
|
11438
11498
|
}
|
|
11439
11499
|
if (data?.status === "expired" || data?.status === "not_found") {
|
|
@@ -11478,6 +11538,7 @@ var init_login = __esm({
|
|
|
11478
11538
|
"use strict";
|
|
11479
11539
|
init_cli_utils();
|
|
11480
11540
|
init_global_install();
|
|
11541
|
+
init_client();
|
|
11481
11542
|
sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
11482
11543
|
SPINNER_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
11483
11544
|
main().catch((err2) => {
|
|
@@ -11992,7 +12053,7 @@ var init_logs_server = __esm({
|
|
|
11992
12053
|
|
|
11993
12054
|
// src/inject.ts
|
|
11994
12055
|
var inject_exports = {};
|
|
11995
|
-
import { readFileSync as readFileSync11, writeFileSync as
|
|
12056
|
+
import { readFileSync as readFileSync11, writeFileSync as writeFileSync8, existsSync as existsSync8, copyFileSync } from "fs";
|
|
11996
12057
|
import { resolve as resolve7 } from "path";
|
|
11997
12058
|
import { execSync } from "child_process";
|
|
11998
12059
|
function parseInjectArgs(argv) {
|
|
@@ -12300,7 +12361,7 @@ async function main2() {
|
|
|
12300
12361
|
log3("");
|
|
12301
12362
|
log3(` Backup: ${backupPath}`);
|
|
12302
12363
|
}
|
|
12303
|
-
|
|
12364
|
+
writeFileSync8(entryFile, result.modified);
|
|
12304
12365
|
log3("");
|
|
12305
12366
|
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");
|
|
12306
12367
|
log3(" \u2502 SolonGate SDK injected successfully! \u2502");
|
|
@@ -12329,7 +12390,7 @@ var init_inject = __esm({
|
|
|
12329
12390
|
|
|
12330
12391
|
// src/create.ts
|
|
12331
12392
|
var create_exports = {};
|
|
12332
|
-
import { mkdirSync as
|
|
12393
|
+
import { mkdirSync as mkdirSync7, writeFileSync as writeFileSync9, existsSync as existsSync9 } from "fs";
|
|
12333
12394
|
import { resolve as resolve8, join as join13 } from "path";
|
|
12334
12395
|
import { execSync as execSync2 } from "child_process";
|
|
12335
12396
|
function withSpinner(message, fn) {
|
|
@@ -12409,7 +12470,7 @@ EXAMPLES
|
|
|
12409
12470
|
`);
|
|
12410
12471
|
}
|
|
12411
12472
|
function createProject(dir, name, _policy) {
|
|
12412
|
-
|
|
12473
|
+
writeFileSync9(
|
|
12413
12474
|
join13(dir, "package.json"),
|
|
12414
12475
|
JSON.stringify(
|
|
12415
12476
|
{
|
|
@@ -12439,7 +12500,7 @@ function createProject(dir, name, _policy) {
|
|
|
12439
12500
|
2
|
|
12440
12501
|
) + "\n"
|
|
12441
12502
|
);
|
|
12442
|
-
|
|
12503
|
+
writeFileSync9(
|
|
12443
12504
|
join13(dir, "tsconfig.json"),
|
|
12444
12505
|
JSON.stringify(
|
|
12445
12506
|
{
|
|
@@ -12460,8 +12521,8 @@ function createProject(dir, name, _policy) {
|
|
|
12460
12521
|
2
|
|
12461
12522
|
) + "\n"
|
|
12462
12523
|
);
|
|
12463
|
-
|
|
12464
|
-
|
|
12524
|
+
mkdirSync7(join13(dir, "src"), { recursive: true });
|
|
12525
|
+
writeFileSync9(
|
|
12465
12526
|
join13(dir, "src", "index.ts"),
|
|
12466
12527
|
`#!/usr/bin/env node
|
|
12467
12528
|
|
|
@@ -12503,7 +12564,7 @@ console.log('');
|
|
|
12503
12564
|
console.log('Press Ctrl+C to stop.');
|
|
12504
12565
|
`
|
|
12505
12566
|
);
|
|
12506
|
-
|
|
12567
|
+
writeFileSync9(
|
|
12507
12568
|
join13(dir, ".mcp.json"),
|
|
12508
12569
|
JSON.stringify(
|
|
12509
12570
|
{
|
|
@@ -12521,12 +12582,12 @@ console.log('Press Ctrl+C to stop.');
|
|
|
12521
12582
|
2
|
|
12522
12583
|
) + "\n"
|
|
12523
12584
|
);
|
|
12524
|
-
|
|
12585
|
+
writeFileSync9(
|
|
12525
12586
|
join13(dir, ".env"),
|
|
12526
12587
|
`SOLONGATE_API_KEY=sg_live_YOUR_KEY_HERE
|
|
12527
12588
|
`
|
|
12528
12589
|
);
|
|
12529
|
-
|
|
12590
|
+
writeFileSync9(
|
|
12530
12591
|
join13(dir, ".gitignore"),
|
|
12531
12592
|
`node_modules/
|
|
12532
12593
|
dist/
|
|
@@ -12546,7 +12607,7 @@ async function main3() {
|
|
|
12546
12607
|
process.exit(1);
|
|
12547
12608
|
}
|
|
12548
12609
|
withSpinner(`Setting up ${opts.name}...`, () => {
|
|
12549
|
-
|
|
12610
|
+
mkdirSync7(dir, { recursive: true });
|
|
12550
12611
|
createProject(dir, opts.name, opts.policy);
|
|
12551
12612
|
});
|
|
12552
12613
|
if (!opts.noInstall) {
|
|
@@ -12620,7 +12681,7 @@ var init_create = __esm({
|
|
|
12620
12681
|
|
|
12621
12682
|
// src/pull-push.ts
|
|
12622
12683
|
var pull_push_exports = {};
|
|
12623
|
-
import { readFileSync as readFileSync12, writeFileSync as
|
|
12684
|
+
import { readFileSync as readFileSync12, writeFileSync as writeFileSync10, existsSync as existsSync10 } from "fs";
|
|
12624
12685
|
import { resolve as resolve9 } from "path";
|
|
12625
12686
|
function loadEnv() {
|
|
12626
12687
|
if (process.env.SOLONGATE_API_KEY) return;
|
|
@@ -12815,7 +12876,7 @@ async function pull(apiKey, file, policyId) {
|
|
|
12815
12876
|
const policy = await fetchCloudPolicy(apiKey, API_URL, policyId);
|
|
12816
12877
|
const { id: _id, ...policyWithoutId } = policy;
|
|
12817
12878
|
const json = JSON.stringify(policyWithoutId, null, 2) + "\n";
|
|
12818
|
-
|
|
12879
|
+
writeFileSync10(file, json, "utf-8");
|
|
12819
12880
|
log5("");
|
|
12820
12881
|
log5(green2(" Saved to: ") + file);
|
|
12821
12882
|
log5(` ${dim2("Name:")} ${policy.name}`);
|
package/dist/login.js
CHANGED
|
@@ -263,6 +263,29 @@ async function runGlobalInstall(opts = {}) {
|
|
|
263
263
|
}
|
|
264
264
|
}
|
|
265
265
|
|
|
266
|
+
// src/api-client/client.ts
|
|
267
|
+
import { readFileSync as readFileSync2, writeFileSync as writeFileSync2, mkdirSync as mkdirSync2, existsSync as existsSync2 } from "fs";
|
|
268
|
+
import { resolve as resolve2, join as join2 } from "path";
|
|
269
|
+
import { homedir as homedir2 } from "os";
|
|
270
|
+
var accountsFile = () => join2(homedir2(), ".solongate", "accounts.json");
|
|
271
|
+
function saveAccount(acc) {
|
|
272
|
+
try {
|
|
273
|
+
const list = (() => {
|
|
274
|
+
try {
|
|
275
|
+
const raw = JSON.parse(readFileSync2(accountsFile(), "utf-8"));
|
|
276
|
+
return Array.isArray(raw) ? raw.filter((a) => a && a.apiKey) : [];
|
|
277
|
+
} catch {
|
|
278
|
+
return [];
|
|
279
|
+
}
|
|
280
|
+
})();
|
|
281
|
+
const next = list.filter((a) => a.apiKey !== acc.apiKey);
|
|
282
|
+
next.unshift({ ...acc, addedAt: acc.addedAt ?? Date.now() });
|
|
283
|
+
mkdirSync2(join2(homedir2(), ".solongate"), { recursive: true });
|
|
284
|
+
writeFileSync2(accountsFile(), JSON.stringify(next, null, 2));
|
|
285
|
+
} catch {
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
|
|
266
289
|
// src/login.ts
|
|
267
290
|
var sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
268
291
|
var SPINNER_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
@@ -360,6 +383,7 @@ async function main() {
|
|
|
360
383
|
if (data?.project?.name) {
|
|
361
384
|
console.log(` ${c.dim}Project:${c.reset} ${c.cyan}${data.project.name}${c.reset}`);
|
|
362
385
|
}
|
|
386
|
+
saveAccount({ apiKey, apiUrl, project: data?.project?.name, user: data?.user?.name || data?.user?.email });
|
|
363
387
|
break;
|
|
364
388
|
}
|
|
365
389
|
if (data?.status === "expired" || data?.status === "not_found") {
|
package/dist/tui/index.js
CHANGED
|
@@ -160,7 +160,7 @@ function KeyHints({ hints }) {
|
|
|
160
160
|
// src/tui/panels/Live.tsx
|
|
161
161
|
import { Box as Box2, Text as Text2, useInput } from "ink";
|
|
162
162
|
import TextInput from "ink-text-input";
|
|
163
|
-
import { mkdirSync, writeFileSync as
|
|
163
|
+
import { mkdirSync as mkdirSync2, writeFileSync as writeFileSync3 } from "fs";
|
|
164
164
|
import { homedir as homedir4 } from "os";
|
|
165
165
|
import { join as join4 } from "path";
|
|
166
166
|
|
|
@@ -245,10 +245,29 @@ function parseLocalLines(lines) {
|
|
|
245
245
|
import { useCallback as useCallback2, useEffect as useEffect2, useRef as useRef2, useState as useState2 } from "react";
|
|
246
246
|
|
|
247
247
|
// src/api-client/client.ts
|
|
248
|
-
import { readFileSync as readFileSync3, existsSync } from "fs";
|
|
248
|
+
import { readFileSync as readFileSync3, writeFileSync as writeFileSync2, mkdirSync, existsSync } from "fs";
|
|
249
249
|
import { resolve, join as join3 } from "path";
|
|
250
250
|
import { homedir as homedir3 } from "os";
|
|
251
251
|
var DEFAULT_API_URL = "https://api.solongate.com";
|
|
252
|
+
var accountsFile = () => join3(homedir3(), ".solongate", "accounts.json");
|
|
253
|
+
function listAccounts() {
|
|
254
|
+
let list5 = [];
|
|
255
|
+
try {
|
|
256
|
+
const raw = JSON.parse(readFileSync3(accountsFile(), "utf-8"));
|
|
257
|
+
if (Array.isArray(raw)) list5 = raw.filter((a) => a && typeof a.apiKey === "string");
|
|
258
|
+
} catch {
|
|
259
|
+
}
|
|
260
|
+
const active2 = loginCredentialFile();
|
|
261
|
+
if (active2.apiKey && !list5.some((a) => a.apiKey === active2.apiKey)) {
|
|
262
|
+
list5.unshift({ apiKey: active2.apiKey, apiUrl: active2.apiUrl || DEFAULT_API_URL });
|
|
263
|
+
}
|
|
264
|
+
return list5;
|
|
265
|
+
}
|
|
266
|
+
var viewOverride = null;
|
|
267
|
+
function setViewCredentials(creds) {
|
|
268
|
+
viewOverride = creds;
|
|
269
|
+
cached2 = null;
|
|
270
|
+
}
|
|
252
271
|
var ApiError = class extends Error {
|
|
253
272
|
status;
|
|
254
273
|
code;
|
|
@@ -302,6 +321,7 @@ function isAuthenticated() {
|
|
|
302
321
|
}
|
|
303
322
|
}
|
|
304
323
|
function resolveCredentials(apiUrlOverride) {
|
|
324
|
+
if (viewOverride && !apiUrlOverride) return viewOverride;
|
|
305
325
|
if (cached2 && !apiUrlOverride) return cached2;
|
|
306
326
|
const file = loginCredentialFile();
|
|
307
327
|
const apiKey = process.env["SOLONGATE_API_KEY"] || file.apiKey || dotenvApiKey();
|
|
@@ -1300,8 +1320,8 @@ function LivePanel({ active: active2 }) {
|
|
|
1300
1320
|
else if (input === "e") {
|
|
1301
1321
|
const file = join4(homedir4(), ".solongate", "live-export.jsonl");
|
|
1302
1322
|
try {
|
|
1303
|
-
|
|
1304
|
-
|
|
1323
|
+
mkdirSync2(join4(homedir4(), ".solongate"), { recursive: true });
|
|
1324
|
+
writeFileSync3(file, visibleDesc.map((x) => JSON.stringify(x)).join("\n") + "\n");
|
|
1305
1325
|
setActionMsg({ text: `\u2713 exported ${visibleDesc.length} lines \u2192 ${file}`, level: "ok", until: Date.now() + 6e3 });
|
|
1306
1326
|
} catch (err) {
|
|
1307
1327
|
setActionMsg({ text: "\u2717 export failed: " + (err instanceof Error ? err.message : String(err)), level: "bad", until: Date.now() + 6e3 });
|
|
@@ -2217,7 +2237,7 @@ function RegexTest({ re }) {
|
|
|
2217
2237
|
// src/tui/panels/Audit.tsx
|
|
2218
2238
|
import { Box as Box6, Text as Text6, useInput as useInput5 } from "ink";
|
|
2219
2239
|
import TextInput4 from "ink-text-input";
|
|
2220
|
-
import { mkdirSync as
|
|
2240
|
+
import { mkdirSync as mkdirSync3, writeFileSync as writeFileSync4 } from "fs";
|
|
2221
2241
|
import { homedir as homedir5 } from "os";
|
|
2222
2242
|
import { join as join5 } from "path";
|
|
2223
2243
|
import { useState as useState6 } from "react";
|
|
@@ -2451,8 +2471,8 @@ function AuditPanel({ active: active2, focused }) {
|
|
|
2451
2471
|
const r = await api.audit.list({ ...query, limit: 1e4, offset: 0 });
|
|
2452
2472
|
rows2 = r.entries.map(cloudRow).sort((a, b) => b.at - a.at);
|
|
2453
2473
|
} else rows2 = localFiltered;
|
|
2454
|
-
|
|
2455
|
-
|
|
2474
|
+
mkdirSync3(dir, { recursive: true });
|
|
2475
|
+
writeFileSync4(file, rows2.map((x) => JSON.stringify(x)).join("\n") + (rows2.length ? "\n" : ""));
|
|
2456
2476
|
return { n: rows2.length, file };
|
|
2457
2477
|
};
|
|
2458
2478
|
run().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" }));
|
|
@@ -3104,6 +3124,17 @@ function App() {
|
|
|
3104
3124
|
const [section, setSection] = useState8(0);
|
|
3105
3125
|
const [focus, setFocus] = useState8("nav");
|
|
3106
3126
|
const [help, setHelp] = useState8(false);
|
|
3127
|
+
const [accounts] = useState8(() => listAccounts());
|
|
3128
|
+
const [acctIdx, setAcctIdx] = useState8(0);
|
|
3129
|
+
const cur = accounts[acctIdx];
|
|
3130
|
+
const acctLabel = cur ? cur.project || cur.user || cur.apiKey.slice(0, 8) : "\u2014";
|
|
3131
|
+
const switchAccount = () => {
|
|
3132
|
+
if (accounts.length < 2) return;
|
|
3133
|
+
const next = (acctIdx + 1) % accounts.length;
|
|
3134
|
+
const a = accounts[next];
|
|
3135
|
+
setViewCredentials({ apiKey: a.apiKey, apiUrl: a.apiUrl });
|
|
3136
|
+
setAcctIdx(next);
|
|
3137
|
+
};
|
|
3107
3138
|
useInput7((input, key) => {
|
|
3108
3139
|
if (help) {
|
|
3109
3140
|
setHelp(false);
|
|
@@ -3117,6 +3148,7 @@ function App() {
|
|
|
3117
3148
|
if (key.upArrow) setSection((n) => (n - 1 + SECTIONS.length) % SECTIONS.length);
|
|
3118
3149
|
else if (key.downArrow) setSection((n) => (n + 1) % SECTIONS.length);
|
|
3119
3150
|
else if (key.rightArrow || key.return || key.tab) setFocus("panel");
|
|
3151
|
+
else if (input === "a") switchAccount();
|
|
3120
3152
|
else if (input === "q") exit();
|
|
3121
3153
|
} else {
|
|
3122
3154
|
if (key.escape || key.tab) setFocus("nav");
|
|
@@ -3127,16 +3159,21 @@ function App() {
|
|
|
3127
3159
|
const current = SECTIONS[section];
|
|
3128
3160
|
if (help) return /* @__PURE__ */ jsx8(HelpOverlay, { cols, rows });
|
|
3129
3161
|
if (current.label === "Live" && focus === "panel") {
|
|
3130
|
-
return /* @__PURE__ */ jsx8(Box8, { flexDirection: "column", width: cols, height: rows, children: /* @__PURE__ */ jsx8(LivePanel, { active: true, focused: true }) });
|
|
3162
|
+
return /* @__PURE__ */ jsx8(Box8, { flexDirection: "column", width: cols, height: rows, children: /* @__PURE__ */ jsx8(LivePanel, { active: true, focused: true }, acctIdx) });
|
|
3131
3163
|
}
|
|
3132
3164
|
const Panel = current.Panel;
|
|
3133
3165
|
return /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", width: cols, height: rows, paddingX: 1, paddingTop: 1, children: [
|
|
3134
3166
|
/* @__PURE__ */ jsx8(Banner, { cols }),
|
|
3167
|
+
/* @__PURE__ */ jsxs8(Text8, { wrap: "truncate", children: [
|
|
3168
|
+
/* @__PURE__ */ jsx8(Text8, { color: theme.dim, children: "account: " }),
|
|
3169
|
+
/* @__PURE__ */ jsx8(Text8, { color: theme.accentBright, bold: true, children: acctLabel }),
|
|
3170
|
+
accounts.length > 1 ? /* @__PURE__ */ jsx8(Text8, { color: theme.dim, children: ` (${acctIdx + 1}/${accounts.length} \xB7 a switch)` }) : null
|
|
3171
|
+
] }),
|
|
3135
3172
|
/* @__PURE__ */ jsxs8(Box8, { marginTop: 1, flexGrow: 1, children: [
|
|
3136
3173
|
/* @__PURE__ */ jsx8(Box8, { flexDirection: "column", width: 16, borderStyle: "round", borderColor: focus === "nav" ? theme.accent : "gray", paddingX: 1, children: SECTIONS.map((s, i) => /* @__PURE__ */ jsx8(Text8, { color: i === section ? theme.accentBright : void 0, bold: i === section, children: (i === section ? "\u25B8 " : " ") + s.label }, s.label)) }),
|
|
3137
3174
|
/* @__PURE__ */ jsx8(Box8, { flexGrow: 1, borderStyle: "round", borderColor: focus === "panel" ? theme.accent : "gray", paddingX: 1, paddingY: 0, children: /* @__PURE__ */ jsx8(Panel, { active: focus === "panel" || current.label !== "Live", focused: focus === "panel" }) })
|
|
3138
|
-
] }),
|
|
3139
|
-
/* @__PURE__ */ jsx8(Box8, { children: focus === "nav" ? /* @__PURE__ */ jsx8(KeyHints, { hints: [["\u2191\u2193", "section"], ["\u2192/enter", "open"], ["?", "help"], ["q", "quit"]] }) : /* @__PURE__ */ jsx8(KeyHints, { hints: [["\u2190/esc", "back"], ["\u2191\u2193", "in-panel"], ["space/s", "act"]] }) })
|
|
3175
|
+
] }, acctIdx),
|
|
3176
|
+
/* @__PURE__ */ jsx8(Box8, { children: 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"]] }) })
|
|
3140
3177
|
] });
|
|
3141
3178
|
}
|
|
3142
3179
|
var HELP = [
|
|
@@ -3145,7 +3182,8 @@ var HELP = [
|
|
|
3145
3182
|
["Policies", [["\u2191\u2193", "browse / select"], ["a", "activate (pin) selected policy"], ["x", "deactivate \u2014 no active policy"], ["enter", "open rules \u2192 open a rule"], ["space", "toggle a rule on/off"], ["e", "flip effect"], ["n", "new rule"], ["d", "delete rule"], ["m", "flip mode"], ["D", "dry-run the draft"], ["s", "save"], ["x", "discard"]]],
|
|
3146
3183
|
["Rate limit / DLP", [["\u2191\u2193", "field / pattern"], ["\u2190\u2192", "adjust (shift = \xB110)"], ["space", "toggle pattern"], ["m", "mode"], ["a / d", "add / remove custom"], ["g", "ghost mode"], ["P", "self-protection"], ["s", "save"]]],
|
|
3147
3184
|
["Audit", [["v", "logs \u2194 sessions"], ["s", "source: cloud \u2194 local"], ["\u2190 \u2192", "prev / next page (500 each)"], ["\u2191\u2193", "select (list scrolls)"], ["enter", "full entry / session logs"], ["f / g", "decision / signal filter"], ["t / n / /", "tool / agent / search"], ["x / X", "delete entry / ALL (press twice)"], ["c", "clear filters"]]],
|
|
3148
|
-
["Settings", [["\u2191\u2193", "move"], ["enter / space", "toggle \xB7 edit \xB7 add"], ["e", "webhook events"], ["d d", "delete"], ["r", "refresh"]]]
|
|
3185
|
+
["Settings", [["\u2191\u2193", "move"], ["enter / space", "toggle \xB7 edit \xB7 add"], ["e", "webhook events"], ["d d", "delete"], ["r", "refresh"]]],
|
|
3186
|
+
["Accounts", [["a", "switch account (view another account logged in on this device)"], ["", "the header shows which account you are viewing; guard/logging keep the active key"]]]
|
|
3149
3187
|
];
|
|
3150
3188
|
function HelpOverlay({ cols, rows }) {
|
|
3151
3189
|
return /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", width: cols, height: rows, paddingX: 2, paddingTop: 1, children: [
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@solongate/proxy",
|
|
3
|
-
"version": "0.81.
|
|
3
|
+
"version": "0.81.37",
|
|
4
4
|
"description": "AI tool security proxy: protect any AI tool server with customizable policies, path/command constraints, rate limiting, and audit logging. No code changes required.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|