@solongate/proxy 0.49.1 → 0.50.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -3412,12 +3412,12 @@ ${ctx.indent}`;
3412
3412
  for (const {
3413
3413
  format,
3414
3414
  test,
3415
- resolve: resolve8
3415
+ resolve: resolve7
3416
3416
  } of tags) {
3417
3417
  if (test) {
3418
3418
  const match = str.match(test);
3419
3419
  if (match) {
3420
- let res = resolve8.apply(null, match);
3420
+ let res = resolve7.apply(null, match);
3421
3421
  if (!(res instanceof Scalar)) res = new Scalar(res);
3422
3422
  if (format) res.format = format;
3423
3423
  return res;
@@ -6775,707 +6775,10 @@ var init_global_install = __esm({
6775
6775
  }
6776
6776
  });
6777
6777
 
6778
- // src/init.ts
6779
- var init_exports = {};
6780
- import { readFileSync as readFileSync6, writeFileSync as writeFileSync4, existsSync as existsSync5, mkdirSync as mkdirSync5 } from "fs";
6781
- import { resolve as resolve4, join as join5, dirname as dirname3 } from "path";
6782
- import { fileURLToPath as fileURLToPath2 } from "url";
6783
- import { execFileSync as execFileSync3 } from "child_process";
6784
- import { createInterface as createInterface2 } from "readline";
6785
- function startSpinner(message) {
6786
- spinnerFrame = 0;
6787
- process.stderr.write(` ${SPINNER_FRAMES[0]} ${message}`);
6788
- spinnerInterval = setInterval(() => {
6789
- spinnerFrame = (spinnerFrame + 1) % SPINNER_FRAMES.length;
6790
- process.stderr.write(`\r ${SPINNER_FRAMES[spinnerFrame]} ${message}`);
6791
- }, 80);
6792
- }
6793
- function stopSpinner(result) {
6794
- if (spinnerInterval) {
6795
- clearInterval(spinnerInterval);
6796
- spinnerInterval = null;
6797
- }
6798
- process.stderr.write(`\r ${result}
6799
- `);
6800
- }
6801
- function findConfigFile(explicitPath, createIfMissing = false) {
6802
- if (explicitPath) {
6803
- if (existsSync5(explicitPath)) {
6804
- return { path: resolve4(explicitPath), type: "mcp" };
6805
- }
6806
- return null;
6807
- }
6808
- for (const searchPath of SEARCH_PATHS) {
6809
- const full = resolve4(searchPath);
6810
- if (existsSync5(full)) return { path: full, type: "mcp" };
6811
- }
6812
- if (createIfMissing) {
6813
- const starterConfig = {
6814
- mcpServers: {
6815
- "filesystem": {
6816
- command: "npx",
6817
- args: ["-y", "@modelcontextprotocol/server-filesystem@latest", "."]
6818
- },
6819
- "playwright": {
6820
- command: "npx",
6821
- args: ["-y", "@playwright/mcp@latest"]
6822
- }
6823
- }
6824
- };
6825
- const starterPath = resolve4(".mcp.json");
6826
- writeFileSync4(starterPath, JSON.stringify(starterConfig, null, 2) + "\n");
6827
- console.log(" Created .mcp.json with starter servers (filesystem, playwright).");
6828
- console.log("");
6829
- return { path: starterPath, type: "mcp", created: true };
6830
- }
6831
- for (const desktopPath of CLAUDE_DESKTOP_PATHS) {
6832
- if (existsSync5(desktopPath)) return { path: desktopPath, type: "claude-desktop" };
6833
- }
6834
- return null;
6835
- }
6836
- function readConfig(filePath) {
6837
- const content = readFileSync6(filePath, "utf-8");
6838
- const parsed = JSON.parse(content);
6839
- if (parsed.mcpServers) return parsed;
6840
- throw new Error(`Unrecognized config format in ${filePath}`);
6841
- }
6842
- function isAlreadyProtected(server) {
6843
- const args = server.args ?? [];
6844
- if (server.command === "solongate-proxy") return true;
6845
- if (server.command === "@solongate/proxy") return true;
6846
- for (const arg of args) {
6847
- if (arg === "-y" || arg === "--yes") continue;
6848
- if (arg === "@solongate/proxy" || arg === "@solongate/proxy@latest" || arg === "solongate-proxy") return true;
6849
- if (/[/\\]packages[/\\]proxy[/\\]dist[/\\]index\.js$/.test(arg)) return true;
6850
- break;
6851
- }
6852
- return false;
6853
- }
6854
- function wrapServer(serverName, server, policy, agentName) {
6855
- const env = { ...server.env ?? {} };
6856
- env.SOLONGATE_API_KEY = "${SOLONGATE_API_KEY}";
6857
- const proxyArgs = ["-y", "@solongate/proxy@latest"];
6858
- if (policy) {
6859
- proxyArgs.push("--policy", policy);
6860
- }
6861
- if (agentName) {
6862
- proxyArgs.push("--agent-name", agentName);
6863
- }
6864
- proxyArgs.push("--verbose", "--", server.command, ...server.args ?? []);
6865
- return {
6866
- command: "npx",
6867
- args: proxyArgs,
6868
- env
6869
- };
6870
- }
6871
- async function prompt(question) {
6872
- const rl = createInterface2({ input: process.stdin, output: process.stderr });
6873
- return new Promise((res) => {
6874
- rl.question(question, (answer) => {
6875
- rl.close();
6876
- res(answer.trim());
6877
- });
6878
- });
6879
- }
6880
- function parseInitArgs(argv) {
6881
- const args = argv.slice(2);
6882
- const options = {
6883
- all: false,
6884
- tools: [],
6885
- global: false,
6886
- restore: false
6887
- };
6888
- for (let i = 0; i < args.length; i++) {
6889
- switch (args[i]) {
6890
- case "--config":
6891
- options.configPath = args[++i];
6892
- break;
6893
- case "--policy":
6894
- options.policy = args[++i];
6895
- break;
6896
- case "--api-key":
6897
- options.apiKey = args[++i];
6898
- break;
6899
- case "--all":
6900
- options.all = true;
6901
- break;
6902
- case "--global":
6903
- case "-g":
6904
- options.global = true;
6905
- break;
6906
- case "--restore":
6907
- case "--uninstall":
6908
- options.restore = true;
6909
- break;
6910
- case "--claude-code":
6911
- options.tools.push("claude-code");
6912
- break;
6913
- case "--gemini":
6914
- options.tools.push("gemini");
6915
- break;
6916
- case "--help":
6917
- case "-h":
6918
- printHelp();
6919
- process.exit(0);
6920
- }
6921
- }
6922
- return options;
6923
- }
6924
- function printHelp() {
6925
- const help = `
6926
- SolonGate Init \u2014 Protect your MCP servers in seconds
6927
-
6928
- USAGE
6929
- npx @solongate/proxy init --all
6930
- npx @solongate/proxy init --global # system-wide (every project)
6931
-
6932
- OPTIONS
6933
- --config <path> Path to MCP config file (default: auto-detect)
6934
- --policy <file> Custom policy JSON file (auto-detects policy.json)
6935
- --api-key <key> SolonGate API key (sg_live_... or sg_test_...)
6936
- --all Protect all servers without prompting
6937
- --global, -g Install a SYSTEM-WIDE Claude Code hook (~/.claude) that
6938
- guards EVERY session on the machine with your cloud
6939
- policy (OPA WASM) \u2014 like the air-gapped product.
6940
- --restore With --global: undo the system-wide install.
6941
- -h, --help Show this help message
6942
-
6943
- AI TOOL HOOKS (default: all)
6944
- --claude-code Install hooks for Claude Code
6945
- --gemini Install hooks for Gemini CLI
6946
-
6947
- EXAMPLES
6948
- npx @solongate/proxy init --all # Protect everything, all tools
6949
- npx @solongate/proxy init --all --claude-code # Only Claude Code hooks
6950
- npx @solongate/proxy init --all --policy policy.json # With custom policy
6951
- npx @solongate/proxy init --global --api-key sg_live_\u2026 # System-wide enforcement
6952
- npx @solongate/proxy init --global --restore # Undo system-wide install
6953
- `;
6954
- console.log(help);
6955
- }
6956
- function readHookScript(filename) {
6957
- return readFileSync6(join5(HOOKS_DIR2, filename), "utf-8");
6958
- }
6959
- function readGuardForGlobal() {
6960
- const bundled = join5(HOOKS_DIR2, "guard.bundled.mjs");
6961
- if (existsSync5(bundled)) return readFileSync6(bundled, "utf-8");
6962
- return readFileSync6(join5(HOOKS_DIR2, "guard.mjs"), "utf-8");
6963
- }
6964
- function unlockProtectedDirs() {
6965
- const dirs = [".solongate", ".claude", ".gemini"];
6966
- for (const dir of dirs) {
6967
- const fullDir = resolve4(dir);
6968
- if (!existsSync5(fullDir)) continue;
6969
- try {
6970
- if (process.platform === "win32") {
6971
- try {
6972
- execFileSync3("icacls", [fullDir, "/remove:d", "*S-1-1-0", "/T", "/Q"], { stdio: "ignore" });
6973
- } catch {
6974
- }
6975
- try {
6976
- execFileSync3("attrib", ["-R", "/S", "/D", fullDir], { stdio: "ignore" });
6977
- } catch {
6978
- }
6979
- } else {
6980
- try {
6981
- execFileSync3("chattr", ["-i", "-R", fullDir], { stdio: "ignore" });
6982
- } catch {
6983
- }
6984
- execFileSync3("chmod", ["-R", "u+w", fullDir], { stdio: "ignore" });
6985
- }
6986
- } catch {
6987
- }
6988
- }
6989
- const protectedFiles = [".env", ".gitignore", ".mcp.json", "policy.json"];
6990
- for (const file of protectedFiles) {
6991
- const fullPath = resolve4(file);
6992
- if (!existsSync5(fullPath)) continue;
6993
- try {
6994
- if (process.platform === "win32") {
6995
- try {
6996
- execFileSync3("icacls", [fullPath, "/remove:d", "*S-1-1-0", "/Q"], { stdio: "ignore" });
6997
- } catch {
6998
- }
6999
- try {
7000
- execFileSync3("attrib", ["-R", fullPath], { stdio: "ignore" });
7001
- } catch {
7002
- }
7003
- } else {
7004
- try {
7005
- execFileSync3("chattr", ["-i", fullPath], { stdio: "ignore" });
7006
- } catch {
7007
- }
7008
- execFileSync3("chmod", ["u+w", fullPath], { stdio: "ignore" });
7009
- }
7010
- } catch {
7011
- }
7012
- }
7013
- }
7014
- function installHooks(selectedTools = [], wrappedMcpConfig) {
7015
- unlockProtectedDirs();
7016
- const hooksDir = resolve4(".solongate", "hooks");
7017
- mkdirSync5(hooksDir, { recursive: true });
7018
- const hookFiles = ["guard.mjs", "audit.mjs", "stop.mjs"];
7019
- let hooksUpdated = 0;
7020
- let hooksSkipped = 0;
7021
- for (const filename of hookFiles) {
7022
- const hookPath = join5(hooksDir, filename);
7023
- const latest = filename === "guard.mjs" ? readGuardForGlobal() : readHookScript(filename);
7024
- let needsWrite = true;
7025
- if (existsSync5(hookPath)) {
7026
- const current = readFileSync6(hookPath, "utf-8");
7027
- if (current === latest) {
7028
- needsWrite = false;
7029
- hooksSkipped++;
7030
- }
7031
- }
7032
- if (needsWrite) {
7033
- writeFileSync4(hookPath, latest);
7034
- hooksUpdated++;
7035
- console.log(` ${existsSync5(hookPath) ? "Updated" : "Created"} ${hookPath}`);
7036
- }
7037
- }
7038
- if (hooksSkipped > 0 && hooksUpdated === 0) {
7039
- console.log(` Hook files already up to date`);
7040
- }
7041
- const allClients = [
7042
- { name: "Claude Code", dir: ".claude", key: "claude-code", agentId: "claude-code", agentName: "Claude Code" },
7043
- { name: "Gemini CLI", dir: ".gemini", key: "gemini", agentId: "gemini-cli", agentName: "Gemini CLI" }
7044
- ];
7045
- const clients = selectedTools.length > 0 ? allClients.filter((c3) => selectedTools.includes(c3.key)) : allClients;
7046
- const activatedNames = [];
7047
- const skippedNames = [];
7048
- for (const client of clients) {
7049
- const clientDir = resolve4(client.dir);
7050
- mkdirSync5(clientDir, { recursive: true });
7051
- const nodeBin = process.execPath.replace(/\\/g, "/");
7052
- const guardCmd = `"${nodeBin}" .solongate/hooks/guard.mjs ${client.agentId} "${client.agentName}"`;
7053
- const auditCmd = `"${nodeBin}" .solongate/hooks/audit.mjs ${client.agentId} "${client.agentName}"`;
7054
- const stopCmd = `"${nodeBin}" .solongate/hooks/stop.mjs ${client.agentId} "${client.agentName}"`;
7055
- if (client.key === "gemini") {
7056
- const result = installGeminiConfig(clientDir, guardCmd, auditCmd, stopCmd, wrappedMcpConfig);
7057
- if (result === "skipped") skippedNames.push(client.name);
7058
- else activatedNames.push(client.name);
7059
- } else {
7060
- const result = installStandardHookConfig(clientDir, client.name, guardCmd, auditCmd, stopCmd);
7061
- if (result === "skipped") skippedNames.push(client.name);
7062
- else activatedNames.push(client.name);
7063
- }
7064
- }
7065
- console.log("");
7066
- if (activatedNames.length > 0) {
7067
- console.log(" Hooks installed:");
7068
- console.log(" guard.mjs \u2192 blocks policy-violating calls (pre-execution)");
7069
- console.log(" audit.mjs \u2192 logs all calls to dashboard (post-execution)");
7070
- console.log(" stop.mjs \u2192 tracks text-only responses (no tool calls)");
7071
- console.log(` Activated for: ${activatedNames.join(", ")}`);
7072
- }
7073
- if (skippedNames.length > 0) {
7074
- console.log(` Already configured: ${skippedNames.join(", ")}`);
7075
- }
7076
- }
7077
- function installStandardHookConfig(clientDir, clientName, guardCmd, auditCmd, stopCmd) {
7078
- const settingsPath = join5(clientDir, "settings.json");
7079
- const hookSettings = {
7080
- PreToolUse: [
7081
- { matcher: "", hooks: [{ type: "command", command: guardCmd }] }
7082
- ],
7083
- PostToolUse: [
7084
- { matcher: "", hooks: [{ type: "command", command: auditCmd }] }
7085
- ],
7086
- Stop: [
7087
- { matcher: "", hooks: [{ type: "command", command: stopCmd }] }
7088
- ]
7089
- };
7090
- let existing = {};
7091
- try {
7092
- existing = JSON.parse(readFileSync6(settingsPath, "utf-8"));
7093
- } catch {
7094
- }
7095
- const merged = { ...existing, hooks: hookSettings };
7096
- const mergedStr = JSON.stringify(merged, null, 2) + "\n";
7097
- const existingStr = existsSync5(settingsPath) ? readFileSync6(settingsPath, "utf-8") : "";
7098
- if (mergedStr === existingStr) return "skipped";
7099
- writeFileSync4(settingsPath, mergedStr);
7100
- console.log(` ${existingStr ? "Updated" : "Created"} ${settingsPath}`);
7101
- return "installed";
7102
- }
7103
- function installGeminiConfig(clientDir, guardCmd, auditCmd, _stopCmd, wrappedMcpConfig) {
7104
- const settingsPath = join5(clientDir, "settings.json");
7105
- let existing = {};
7106
- try {
7107
- existing = JSON.parse(readFileSync6(settingsPath, "utf-8"));
7108
- } catch {
7109
- }
7110
- const merged = { ...existing };
7111
- if (wrappedMcpConfig) {
7112
- const geminiMcp = {};
7113
- for (const [name, server] of Object.entries(wrappedMcpConfig.mcpServers)) {
7114
- const args = [...server.args ?? []];
7115
- const agentIdx = args.indexOf("--agent-name");
7116
- if (agentIdx >= 0 && agentIdx + 1 < args.length) {
7117
- args[agentIdx + 1] = "gemini-cli";
7118
- } else {
7119
- const sepIdx = args.indexOf("--");
7120
- if (sepIdx >= 0) args.splice(sepIdx, 0, "--agent-name", "gemini-cli");
7121
- }
7122
- geminiMcp[name] = { ...server, args };
7123
- }
7124
- merged.mcpServers = geminiMcp;
7125
- }
7126
- merged.hooks = {
7127
- BeforeTool: [
7128
- { matcher: ".*", hooks: [{ type: "command", command: guardCmd }] }
7129
- ],
7130
- AfterTool: [
7131
- { matcher: ".*", hooks: [{ type: "command", command: auditCmd }] }
7132
- ]
7133
- };
7134
- const mergedStr = JSON.stringify(merged, null, 2) + "\n";
7135
- const existingStr = existsSync5(settingsPath) ? readFileSync6(settingsPath, "utf-8") : "";
7136
- if (mergedStr === existingStr) return "skipped";
7137
- writeFileSync4(settingsPath, mergedStr);
7138
- console.log(` ${existingStr ? "Updated" : "Created"} ${settingsPath}`);
7139
- return "installed";
7140
- }
7141
- function ensureEnvFile() {
7142
- let envChanged = false;
7143
- let gitignoreChanged = false;
7144
- const envPath = resolve4(".env");
7145
- if (!existsSync5(envPath)) {
7146
- const envContent = `# SolonGate Configuration
7147
- # IMPORTANT: Never commit this file to git!
7148
-
7149
- # Your SolonGate API key \u2014 get one at https://dashboard.solongate.com
7150
- SOLONGATE_API_KEY=sg_live_your_key_here
7151
-
7152
- # AI Judge (semantic security layer) \u2014 get a free key at https://console.groq.com/keys
7153
- # Enable with: npx @solongate/proxy --ai-judge ...
7154
- GROQ_API_KEY=gsk_your_groq_key_here
7155
- `;
7156
- writeFileSync4(envPath, envContent);
7157
- console.log(` Created .env`);
7158
- console.log(` \u2192 Set your API key in .env (get one at https://dashboard.solongate.com)`);
7159
- envChanged = true;
7160
- } else {
7161
- const existingEnv = readFileSync6(envPath, "utf-8");
7162
- if (!existingEnv.includes("SOLONGATE_API_KEY")) {
7163
- const separator = existingEnv.endsWith("\n") ? "" : "\n";
7164
- const appendContent = `${separator}
7165
- # SolonGate API key \u2014 get one at https://dashboard.solongate.com
7166
- SOLONGATE_API_KEY=sg_live_your_key_here
7167
- `;
7168
- writeFileSync4(envPath, existingEnv + appendContent);
7169
- console.log(` Updated .env (added SOLONGATE_API_KEY)`);
7170
- console.log(` \u2192 Set your API key in .env (get one at https://dashboard.solongate.com)`);
7171
- envChanged = true;
7172
- }
7173
- }
7174
- const gitignorePath = resolve4(".gitignore");
7175
- const requiredLines = [
7176
- ".env",
7177
- ".env.local",
7178
- ".mcp.json",
7179
- ".solongate/**",
7180
- ".claude/**",
7181
- ".gemini/**"
7182
- ];
7183
- if (existsSync5(gitignorePath)) {
7184
- let gitignore = readFileSync6(gitignorePath, "utf-8");
7185
- const existingLines = new Set(gitignore.split("\n").map((l) => l.trim()));
7186
- const missing = requiredLines.filter((line) => !existingLines.has(line));
7187
- if (missing.length > 0) {
7188
- gitignore = gitignore.trimEnd() + "\n\n# SolonGate\n" + missing.join("\n") + "\n";
7189
- writeFileSync4(gitignorePath, gitignore);
7190
- console.log(` Updated .gitignore (+${missing.length} entries)`);
7191
- gitignoreChanged = true;
7192
- }
7193
- } else {
7194
- const content = "# SolonGate\n" + requiredLines.join("\n") + "\nnode_modules/\n";
7195
- writeFileSync4(gitignorePath, content);
7196
- console.log(` Created .gitignore`);
7197
- gitignoreChanged = true;
7198
- }
7199
- if (!envChanged && !gitignoreChanged) {
7200
- console.log(` .env and .gitignore already up to date`);
7201
- }
7202
- return { envChanged, gitignoreChanged };
7203
- }
7204
- async function main() {
7205
- const options = parseInitArgs(process.argv);
7206
- if (options.global) {
7207
- console.log("");
7208
- console.log(` ${c.bold}SolonGate \u2014 Global Install${c.reset}`);
7209
- console.log("");
7210
- if (options.restore) {
7211
- runGlobalRestore();
7212
- } else {
7213
- await runGlobalInstall({ apiKey: options.apiKey });
7214
- console.log("");
7215
- console.log(" \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\u2500\u2500\u2500\u2510");
7216
- console.log(" \u2502 Global enforcement active. \u2502");
7217
- console.log(" \u2502 Every Claude Code session on this machine is \u2502");
7218
- console.log(" \u2502 now guarded by your cloud policy (OPA WASM). \u2502");
7219
- console.log(" \u2502 \u2502");
7220
- console.log(" \u2502 Undo: init --global --restore \u2502");
7221
- console.log(" \u2502 Logs: https://dashboard.solongate.com \u2502");
7222
- console.log(" \u2502 Restart Claude Code to apply. \u2502");
7223
- console.log(" \u2514\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\u2500\u2500\u2500\u2518");
7224
- }
7225
- console.log("");
7226
- return;
7227
- }
7228
- const fullBanner = BANNER_FULL;
7229
- const mediumBanner = [
7230
- " \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2557 \u2588\u2588\u2557",
7231
- " \u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2554\u2550\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2551 \u2588\u2588\u2554\u2550\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2551",
7232
- " \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2554\u2588\u2588\u2557 \u2588\u2588\u2551",
7233
- " \u255A\u2550\u2550\u2550\u2550\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551\u255A\u2588\u2588\u2557\u2588\u2588\u2551",
7234
- " \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2551 \u255A\u2588\u2588\u2588\u2588\u2551",
7235
- " \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u2550\u2550\u255D",
7236
- " \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557",
7237
- " \u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u255A\u2550\u2550\u2588\u2588\u2554\u2550\u2550\u255D\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D",
7238
- " \u2588\u2588\u2551 \u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2588\u2588\u2588\u2557 ",
7239
- " \u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2554\u2550\u2550\u255D ",
7240
- " \u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557",
7241
- " \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D"
7242
- ];
7243
- const smallBanner = [
7244
- " \u250F\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2513",
7245
- " \u2503 \u2554\u2550\u2557\u2554\u2550\u2557\u2566 \u2554\u2550\u2557\u2554\u2557\u2554\u2554\u2550\u2557 \u2503",
7246
- " \u2503 \u255A\u2550\u2557\u2551 \u2551\u2551 \u2551 \u2551\u2551\u2551\u2551\u2551 \u2566 \u2503",
7247
- " \u2503 \u255A\u2550\u255D\u255A\u2550\u255D\u2569\u2550\u255D\u255A\u2550\u255D\u255D\u255A\u255D\u255A\u2550\u255D \u2503",
7248
- " \u2503 \u2554\u2550\u2557\u2554\u2550\u2557\u2554\u2566\u2557\u2554\u2550\u2557 \u2503",
7249
- " \u2503 \u2551 \u2566\u2560\u2550\u2563 \u2551 \u2551\u2563 \u2503",
7250
- " \u2503 \u255A\u2550\u255D\u2569 \u2569 \u2569 \u255A\u2550\u255D \u2503",
7251
- " \u2517\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u251B"
7252
- ];
7253
- const cols = process.stdout.columns || 80;
7254
- const bannerLines = cols >= 82 ? fullBanner : cols >= 50 ? mediumBanner : smallBanner;
7255
- const bannerColors = BANNER_COLORS;
7256
- console.log("");
7257
- for (let i = 0; i < bannerLines.length; i++) {
7258
- console.log(`${c.bold}${bannerColors[i % bannerColors.length]}${bannerLines[i]}${c.reset}`);
7259
- }
7260
- console.log("");
7261
- console.log(` ${c.dim}${c.italic}Init Setup${c.reset}`);
7262
- console.log("");
7263
- startSpinner("Scanning for MCP config...");
7264
- await sleep(400);
7265
- const configInfo = findConfigFile(options.configPath, true);
7266
- if (!configInfo) {
7267
- stopSpinner("\u2717 No MCP config found and could not create one.");
7268
- process.exit(1);
7269
- }
7270
- stopSpinner(`\u2713 Found config: ${configInfo.path}`);
7271
- console.log(` Type: ${configInfo.type === "claude-desktop" ? "Claude Desktop" : "MCP JSON"}`);
7272
- console.log("");
7273
- const config = readConfig(configInfo.path);
7274
- const serverNames = Object.keys(config.mcpServers);
7275
- if (serverNames.length === 0) {
7276
- console.log(" No MCP servers found in config.");
7277
- process.exit(1);
7278
- }
7279
- startSpinner("Analyzing servers...");
7280
- await sleep(300);
7281
- const toProtect = [];
7282
- const alreadyProtected = [];
7283
- const skipped = [];
7284
- for (const name of serverNames) {
7285
- const server = config.mcpServers[name];
7286
- if (isAlreadyProtected(server)) {
7287
- alreadyProtected.push(name);
7288
- } else {
7289
- if (options.all) {
7290
- toProtect.push(name);
7291
- }
7292
- }
7293
- }
7294
- stopSpinner(`\u2713 Found ${serverNames.length} MCP server(s)`);
7295
- console.log("");
7296
- for (const name of serverNames) {
7297
- const server = config.mcpServers[name];
7298
- if (alreadyProtected.includes(name)) {
7299
- console.log(` [protected] ${name}`);
7300
- } else {
7301
- console.log(` [exposed] ${name} \u2192 ${server.command} ${(server.args ?? []).join(" ")}`);
7302
- }
7303
- }
7304
- console.log("");
7305
- if (alreadyProtected.length === serverNames.length) {
7306
- console.log(" All servers are already protected by SolonGate!");
7307
- ensureEnvFile();
7308
- console.log("");
7309
- installHooks(options.tools, config);
7310
- process.exit(0);
7311
- }
7312
- if (!options.all) {
7313
- const exposed = serverNames.filter((n) => !alreadyProtected.includes(n));
7314
- for (const name of exposed) {
7315
- const answer = await prompt(` Protect "${name}"? [Y/n] `);
7316
- if (answer === "" || answer.toLowerCase() === "y" || answer.toLowerCase() === "yes") {
7317
- toProtect.push(name);
7318
- } else {
7319
- skipped.push(name);
7320
- }
7321
- }
7322
- }
7323
- if (toProtect.length === 0) {
7324
- console.log(" No servers selected for protection.");
7325
- ensureEnvFile();
7326
- process.exit(0);
7327
- }
7328
- console.log("");
7329
- startSpinner("Setting up environment...");
7330
- await sleep(300);
7331
- stopSpinner("\u2713 Environment");
7332
- ensureEnvFile();
7333
- console.log("");
7334
- let apiKey = options.apiKey || process.env.SOLONGATE_API_KEY || "";
7335
- if (!apiKey) {
7336
- const envPath = resolve4(".env");
7337
- if (existsSync5(envPath)) {
7338
- const envContent = readFileSync6(envPath, "utf-8");
7339
- const match = envContent.match(/^SOLONGATE_API_KEY=(sg_(?:live|test)_\w+)/m);
7340
- if (match) apiKey = match[1];
7341
- }
7342
- }
7343
- if (!apiKey || apiKey === "sg_live_your_key_here") {
7344
- if (options.all) {
7345
- apiKey = "sg_test_demo_init_key";
7346
- console.log(" No API key found \u2014 using demo test key.");
7347
- console.log(" Set your real key in .env for cloud features.");
7348
- console.log("");
7349
- } else {
7350
- apiKey = await prompt(" Enter your SolonGate API key (from https://dashboard.solongate.com): ");
7351
- }
7352
- if (!apiKey) {
7353
- console.log(" API key is required. Get one at https://dashboard.solongate.com");
7354
- process.exit(1);
7355
- }
7356
- }
7357
- if (!apiKey.startsWith("sg_live_") && !apiKey.startsWith("sg_test_")) {
7358
- console.log(" Invalid API key format. Must start with sg_live_ or sg_test_");
7359
- process.exit(1);
7360
- }
7361
- let policyValue;
7362
- if (options.policy) {
7363
- const policyPath = resolve4(options.policy);
7364
- if (existsSync5(policyPath)) {
7365
- policyValue = `./${options.policy}`;
7366
- console.log(` Policy: ${policyPath}`);
7367
- } else {
7368
- console.log(` Policy file not found: ${options.policy}`);
7369
- process.exit(1);
7370
- }
7371
- } else {
7372
- const defaultPolicy = resolve4("policy.json");
7373
- if (existsSync5(defaultPolicy)) {
7374
- policyValue = "./policy.json";
7375
- console.log(` Policy: ${defaultPolicy} (auto-detected)`);
7376
- } else {
7377
- console.log(` Policy: cloud-managed (fetched via API key)`);
7378
- }
7379
- }
7380
- console.log(` API Key: ${apiKey.slice(0, 12)}...${apiKey.slice(-4)}`);
7381
- console.log(` Protecting: ${toProtect.join(", ")}`);
7382
- console.log("");
7383
- startSpinner("Wrapping MCP servers with proxy...");
7384
- const newConfig = { mcpServers: {} };
7385
- for (const name of serverNames) {
7386
- if (toProtect.includes(name)) {
7387
- newConfig.mcpServers[name] = wrapServer(name, config.mcpServers[name], policyValue);
7388
- } else {
7389
- newConfig.mcpServers[name] = config.mcpServers[name];
7390
- }
7391
- }
7392
- const currentContent = readFileSync6(configInfo.path, "utf-8");
7393
- let newContent;
7394
- if (configInfo.type === "claude-desktop") {
7395
- const original = JSON.parse(currentContent);
7396
- original.mcpServers = newConfig.mcpServers;
7397
- newContent = JSON.stringify(original, null, 2) + "\n";
7398
- } else {
7399
- newContent = JSON.stringify(newConfig, null, 2) + "\n";
7400
- }
7401
- await sleep(400);
7402
- if (newContent === currentContent) {
7403
- stopSpinner("\u2713 Config already up to date");
7404
- } else {
7405
- writeFileSync4(configInfo.path, newContent);
7406
- stopSpinner("\u2713 Config updated");
7407
- }
7408
- console.log("");
7409
- startSpinner("Installing hooks...");
7410
- await sleep(300);
7411
- stopSpinner("\u2713 Hooks");
7412
- installHooks(options.tools, newConfig);
7413
- console.log("");
7414
- const allUpToDate = toProtect.length === 0 && alreadyProtected.length === serverNames.length;
7415
- console.log(" \u2500\u2500 Summary \u2500\u2500");
7416
- console.log("");
7417
- for (const name of toProtect) {
7418
- console.log(` \u2713 ${name} \u2014 protected`);
7419
- }
7420
- for (const name of alreadyProtected) {
7421
- console.log(` \u25CF ${name} \u2014 already protected`);
7422
- }
7423
- for (const name of skipped) {
7424
- console.log(` \u25CB ${name} \u2014 skipped`);
7425
- }
7426
- console.log("");
7427
- if (allUpToDate) {
7428
- console.log(" \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\u2500\u2500\u2500\u2510");
7429
- console.log(" \u2502 Everything is already up to date! \u2502");
7430
- console.log(" \u2502 \u2502");
7431
- console.log(" \u2502 All MCP servers protected, hooks configured. \u2502");
7432
- console.log(" \u2502 View logs: https://dashboard.solongate.com \u2502");
7433
- console.log(" \u2514\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\u2500\u2500\u2500\u2518");
7434
- } else {
7435
- console.log(" \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\u2500\u2500\u2500\u2510");
7436
- console.log(" \u2502 Setup complete! \u2502");
7437
- console.log(" \u2502 \u2502");
7438
- console.log(" \u2502 MCP servers \u2192 Protected via proxy \u2502");
7439
- console.log(" \u2502 AI tools \u2192 Guarded via hooks \u2502");
7440
- console.log(" \u2502 Claude Code, Gemini CLI \u2502");
7441
- console.log(" \u2502 API key \u2192 Set in .env \u2502");
7442
- console.log(" \u2502 \u2502");
7443
- console.log(" \u2502 View logs: https://dashboard.solongate.com \u2502");
7444
- console.log(" \u2502 \u2502");
7445
- console.log(" \u2502 Restart your MCP client to apply changes. \u2502");
7446
- console.log(" \u2514\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\u2500\u2500\u2500\u2518");
7447
- }
7448
- console.log("");
7449
- }
7450
- var SEARCH_PATHS, CLAUDE_DESKTOP_PATHS, sleep, SPINNER_FRAMES, spinnerInterval, spinnerFrame, __dirname2, HOOKS_DIR2;
7451
- var init_init = __esm({
7452
- "src/init.ts"() {
7453
- "use strict";
7454
- init_cli_utils();
7455
- init_global_install();
7456
- SEARCH_PATHS = [
7457
- ".mcp.json",
7458
- "mcp.json",
7459
- ".claude/mcp.json"
7460
- ];
7461
- CLAUDE_DESKTOP_PATHS = process.platform === "win32" ? [join5(process.env["APPDATA"] ?? "", "Claude", "claude_desktop_config.json")] : process.platform === "darwin" ? [join5(process.env["HOME"] ?? "", "Library", "Application Support", "Claude", "claude_desktop_config.json")] : [join5(process.env["HOME"] ?? "", ".config", "claude", "claude_desktop_config.json")];
7462
- sleep = (ms) => new Promise((r) => setTimeout(r, ms));
7463
- SPINNER_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
7464
- spinnerInterval = null;
7465
- spinnerFrame = 0;
7466
- __dirname2 = dirname3(fileURLToPath2(import.meta.url));
7467
- HOOKS_DIR2 = resolve4(__dirname2, "..", "hooks");
7468
- main().catch((err) => {
7469
- console.log(`Fatal: ${err instanceof Error ? err.message : String(err)}`);
7470
- process.exit(1);
7471
- });
7472
- }
7473
- });
7474
-
7475
6778
  // src/login.ts
7476
6779
  var login_exports = {};
7477
6780
  import { spawn } from "child_process";
7478
- function startSpinner2(text) {
6781
+ function startSpinner(text) {
7479
6782
  if (!process.stderr.isTTY) {
7480
6783
  process.stderr.write(` ${text}
7481
6784
  `);
@@ -7485,7 +6788,7 @@ function startSpinner2(text) {
7485
6788
  }
7486
6789
  let i = 0;
7487
6790
  const draw = () => {
7488
- const frame = SPINNER_FRAMES2[i = (i + 1) % SPINNER_FRAMES2.length];
6791
+ const frame = SPINNER_FRAMES[i = (i + 1) % SPINNER_FRAMES.length];
7489
6792
  process.stderr.write(`\r ${c.cyan}${frame}${c.reset} ${c.dim}${text}${c.reset}\x1B[K`);
7490
6793
  };
7491
6794
  draw();
@@ -7517,7 +6820,7 @@ function openBrowser(url) {
7517
6820
  } catch {
7518
6821
  }
7519
6822
  }
7520
- async function main2() {
6823
+ async function main() {
7521
6824
  const { apiUrl, install } = parseArgs2(process.argv);
7522
6825
  console.log("");
7523
6826
  console.log(` ${c.bold}${c.blue4}SolonGate${c.reset} ${c.dim}\u2014 Login${c.reset}`);
@@ -7544,9 +6847,9 @@ async function main2() {
7544
6847
  const pollMs = Math.max(2, Number(interval) || 3) * 1e3;
7545
6848
  const deadline = Date.now() + (Number(expires_in) || 600) * 1e3;
7546
6849
  let apiKey = "";
7547
- const stopSpinner2 = startSpinner2("Waiting for authorization\u2026");
6850
+ const stopSpinner = startSpinner("Waiting for authorization\u2026");
7548
6851
  while (Date.now() < deadline) {
7549
- await sleep2(pollMs);
6852
+ await sleep(pollMs);
7550
6853
  try {
7551
6854
  const res = await fetch(`${apiUrl}/api/v1/auth/device/poll`, {
7552
6855
  method: "POST",
@@ -7556,7 +6859,7 @@ async function main2() {
7556
6859
  const data = await res.json().catch(() => ({}));
7557
6860
  if (data?.status === "approved" && data?.api_key) {
7558
6861
  apiKey = data.api_key;
7559
- stopSpinner2();
6862
+ stopSpinner();
7560
6863
  console.log("");
7561
6864
  const who = data?.user?.name || data?.user?.email;
7562
6865
  const mail = data?.user?.email;
@@ -7572,19 +6875,19 @@ async function main2() {
7572
6875
  break;
7573
6876
  }
7574
6877
  if (data?.status === "expired" || data?.status === "not_found") {
7575
- stopSpinner2(` ${c.red}\u2717${c.reset} Code expired. Run \`login\` again.`);
6878
+ stopSpinner(` ${c.red}\u2717${c.reset} Code expired. Run \`login\` again.`);
7576
6879
  process.exit(1);
7577
6880
  }
7578
6881
  } catch {
7579
6882
  }
7580
6883
  }
7581
6884
  if (!apiKey) {
7582
- stopSpinner2(` ${c.red}\u2717${c.reset} Timed out waiting for authorization. Run \`login\` again.`);
6885
+ stopSpinner(` ${c.red}\u2717${c.reset} Timed out waiting for authorization. Run \`login\` again.`);
7583
6886
  process.exit(1);
7584
6887
  }
7585
6888
  if (!install) {
7586
6889
  console.log("");
7587
- console.log(" Logged in. Run `init --global` to enable system-wide enforcement.");
6890
+ console.log(" Logged in. Re-run `login` to enable system-wide enforcement.");
7588
6891
  return;
7589
6892
  }
7590
6893
  console.log("");
@@ -7595,8 +6898,7 @@ async function main2() {
7595
6898
  console.log(" \u2502 Every Claude Code session on this machine is \u2502");
7596
6899
  console.log(" \u2502 now guarded by your cloud policy (OPA WASM). \u2502");
7597
6900
  console.log(" \u2502 \u2502");
7598
- console.log(" \u2502 Undo: npx @solongate/proxy init --global \u2502");
7599
- console.log(" \u2502 --restore \u2502");
6901
+ console.log(" \u2502 Undo: npx @solongate/proxy logout \u2502");
7600
6902
  console.log(" \u2502 Manage policy: https://dashboard.solongate.com \u2502");
7601
6903
  console.log(" \u2502 Restart Claude Code to apply. \u2502");
7602
6904
  console.log(" \u2514\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\u2500\u2500\u2500\u2518");
@@ -7608,15 +6910,15 @@ async function main2() {
7608
6910
  console.log(` there for the guard + audit logging to take effect.${c.reset}`);
7609
6911
  console.log("");
7610
6912
  }
7611
- var sleep2, SPINNER_FRAMES2;
6913
+ var sleep, SPINNER_FRAMES;
7612
6914
  var init_login = __esm({
7613
6915
  "src/login.ts"() {
7614
6916
  "use strict";
7615
6917
  init_cli_utils();
7616
6918
  init_global_install();
7617
- sleep2 = (ms) => new Promise((r) => setTimeout(r, ms));
7618
- SPINNER_FRAMES2 = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
7619
- main2().catch((err) => {
6919
+ sleep = (ms) => new Promise((r) => setTimeout(r, ms));
6920
+ SPINNER_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
6921
+ main().catch((err) => {
7620
6922
  console.log(`Fatal: ${err instanceof Error ? err.message : String(err)}`);
7621
6923
  process.exit(1);
7622
6924
  });
@@ -7625,8 +6927,8 @@ var init_login = __esm({
7625
6927
 
7626
6928
  // src/inject.ts
7627
6929
  var inject_exports = {};
7628
- import { readFileSync as readFileSync7, writeFileSync as writeFileSync5, existsSync as existsSync6, copyFileSync } from "fs";
7629
- import { resolve as resolve5 } from "path";
6930
+ import { readFileSync as readFileSync6, writeFileSync as writeFileSync4, existsSync as existsSync5, copyFileSync } from "fs";
6931
+ import { resolve as resolve4 } from "path";
7630
6932
  import { execSync } from "child_process";
7631
6933
  function parseInjectArgs(argv) {
7632
6934
  const args = argv.slice(2);
@@ -7651,13 +6953,13 @@ function parseInjectArgs(argv) {
7651
6953
  break;
7652
6954
  case "--help":
7653
6955
  case "-h":
7654
- printHelp2();
6956
+ printHelp();
7655
6957
  process.exit(0);
7656
6958
  }
7657
6959
  }
7658
6960
  return opts;
7659
6961
  }
7660
- function printHelp2() {
6962
+ function printHelp() {
7661
6963
  log3(`
7662
6964
  SolonGate Inject \u2014 Add security to your MCP server in seconds
7663
6965
 
@@ -7683,9 +6985,9 @@ WHAT IT DOES
7683
6985
  `);
7684
6986
  }
7685
6987
  function detectProject() {
7686
- if (!existsSync6(resolve5("package.json"))) return false;
6988
+ if (!existsSync5(resolve4("package.json"))) return false;
7687
6989
  try {
7688
- const pkg = JSON.parse(readFileSync7(resolve5("package.json"), "utf-8"));
6990
+ const pkg = JSON.parse(readFileSync6(resolve4("package.json"), "utf-8"));
7689
6991
  const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };
7690
6992
  return !!(allDeps["@modelcontextprotocol/sdk"] || allDeps["@modelcontextprotocol/server"]);
7691
6993
  } catch {
@@ -7694,18 +6996,18 @@ function detectProject() {
7694
6996
  }
7695
6997
  function findTsEntryFile() {
7696
6998
  try {
7697
- const pkg = JSON.parse(readFileSync7(resolve5("package.json"), "utf-8"));
6999
+ const pkg = JSON.parse(readFileSync6(resolve4("package.json"), "utf-8"));
7698
7000
  if (pkg.bin) {
7699
7001
  const binPath = typeof pkg.bin === "string" ? pkg.bin : Object.values(pkg.bin)[0];
7700
7002
  if (typeof binPath === "string") {
7701
7003
  const srcPath = binPath.replace(/^\.\/dist\//, "./src/").replace(/\.js$/, ".ts");
7702
- if (existsSync6(resolve5(srcPath))) return resolve5(srcPath);
7703
- if (existsSync6(resolve5(binPath))) return resolve5(binPath);
7004
+ if (existsSync5(resolve4(srcPath))) return resolve4(srcPath);
7005
+ if (existsSync5(resolve4(binPath))) return resolve4(binPath);
7704
7006
  }
7705
7007
  }
7706
7008
  if (pkg.main) {
7707
7009
  const srcPath = pkg.main.replace(/^\.\/dist\//, "./src/").replace(/\.js$/, ".ts");
7708
- if (existsSync6(resolve5(srcPath))) return resolve5(srcPath);
7010
+ if (existsSync5(resolve4(srcPath))) return resolve4(srcPath);
7709
7011
  }
7710
7012
  } catch {
7711
7013
  }
@@ -7718,10 +7020,10 @@ function findTsEntryFile() {
7718
7020
  "main.ts"
7719
7021
  ];
7720
7022
  for (const c3 of candidates) {
7721
- const full = resolve5(c3);
7722
- if (existsSync6(full)) {
7023
+ const full = resolve4(c3);
7024
+ if (existsSync5(full)) {
7723
7025
  try {
7724
- const content = readFileSync7(full, "utf-8");
7026
+ const content = readFileSync6(full, "utf-8");
7725
7027
  if (content.includes("McpServer") || content.includes("McpServer")) {
7726
7028
  return full;
7727
7029
  }
@@ -7730,18 +7032,18 @@ function findTsEntryFile() {
7730
7032
  }
7731
7033
  }
7732
7034
  for (const c3 of candidates) {
7733
- if (existsSync6(resolve5(c3))) return resolve5(c3);
7035
+ if (existsSync5(resolve4(c3))) return resolve4(c3);
7734
7036
  }
7735
7037
  return null;
7736
7038
  }
7737
7039
  function detectPackageManager() {
7738
- if (existsSync6(resolve5("pnpm-lock.yaml"))) return "pnpm";
7739
- if (existsSync6(resolve5("yarn.lock"))) return "yarn";
7040
+ if (existsSync5(resolve4("pnpm-lock.yaml"))) return "pnpm";
7041
+ if (existsSync5(resolve4("yarn.lock"))) return "yarn";
7740
7042
  return "npm";
7741
7043
  }
7742
7044
  function installSdk() {
7743
7045
  try {
7744
- const pkg = JSON.parse(readFileSync7(resolve5("package.json"), "utf-8"));
7046
+ const pkg = JSON.parse(readFileSync6(resolve4("package.json"), "utf-8"));
7745
7047
  const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };
7746
7048
  if (allDeps["@solongate/proxy"]) {
7747
7049
  log3(" @solongate/proxy already installed");
@@ -7762,7 +7064,7 @@ function installSdk() {
7762
7064
  }
7763
7065
  }
7764
7066
  function injectTypeScript(filePath) {
7765
- const original = readFileSync7(filePath, "utf-8");
7067
+ const original = readFileSync6(filePath, "utf-8");
7766
7068
  const changes = [];
7767
7069
  let modified = original;
7768
7070
  if (modified.includes("SecureMcpServer")) {
@@ -7866,7 +7168,7 @@ function showDiff(result) {
7866
7168
  }
7867
7169
  log3("");
7868
7170
  }
7869
- async function main3() {
7171
+ async function main2() {
7870
7172
  const opts = parseInjectArgs(process.argv);
7871
7173
  printBanner("Inject SDK");
7872
7174
  if (!detectProject()) {
@@ -7878,8 +7180,8 @@ async function main3() {
7878
7180
  process.exit(1);
7879
7181
  }
7880
7182
  log3(" Language: TypeScript");
7881
- const entryFile = opts.file ? resolve5(opts.file) : findTsEntryFile();
7882
- if (!entryFile || !existsSync6(entryFile)) {
7183
+ const entryFile = opts.file ? resolve4(opts.file) : findTsEntryFile();
7184
+ if (!entryFile || !existsSync5(entryFile)) {
7883
7185
  log3(` Could not find entry file.${opts.file ? ` File not found: ${opts.file}` : ""}`);
7884
7186
  log3("");
7885
7187
  log3(" Specify it manually: --file <path>");
@@ -7892,7 +7194,7 @@ async function main3() {
7892
7194
  log3("");
7893
7195
  const backupPath = entryFile + ".solongate-backup";
7894
7196
  if (opts.restore) {
7895
- if (!existsSync6(backupPath)) {
7197
+ if (!existsSync5(backupPath)) {
7896
7198
  log3(" No backup found. Nothing to restore.");
7897
7199
  process.exit(1);
7898
7200
  }
@@ -7928,12 +7230,12 @@ async function main3() {
7928
7230
  log3(" To apply: npx @solongate/proxy inject");
7929
7231
  process.exit(0);
7930
7232
  }
7931
- if (!existsSync6(backupPath)) {
7233
+ if (!existsSync5(backupPath)) {
7932
7234
  copyFileSync(entryFile, backupPath);
7933
7235
  log3("");
7934
7236
  log3(` Backup: ${backupPath}`);
7935
7237
  }
7936
- writeFileSync5(entryFile, result.modified);
7238
+ writeFileSync4(entryFile, result.modified);
7937
7239
  log3("");
7938
7240
  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");
7939
7241
  log3(" \u2502 SolonGate SDK injected successfully! \u2502");
@@ -7953,7 +7255,7 @@ var init_inject = __esm({
7953
7255
  "src/inject.ts"() {
7954
7256
  "use strict";
7955
7257
  init_cli_utils();
7956
- main3().catch((err) => {
7258
+ main2().catch((err) => {
7957
7259
  log3(`Fatal: ${err instanceof Error ? err.message : String(err)}`);
7958
7260
  process.exit(1);
7959
7261
  });
@@ -7962,8 +7264,8 @@ var init_inject = __esm({
7962
7264
 
7963
7265
  // src/create.ts
7964
7266
  var create_exports = {};
7965
- import { mkdirSync as mkdirSync6, writeFileSync as writeFileSync6, existsSync as existsSync7 } from "fs";
7966
- import { resolve as resolve6, join as join6 } from "path";
7267
+ import { mkdirSync as mkdirSync5, writeFileSync as writeFileSync5, existsSync as existsSync6 } from "fs";
7268
+ import { resolve as resolve5, join as join5 } from "path";
7967
7269
  import { execSync as execSync2 } from "child_process";
7968
7270
  function withSpinner(message, fn) {
7969
7271
  const frames = ["\u28FE", "\u28FD", "\u28FB", "\u28BF", "\u287F", "\u28DF", "\u28EF", "\u28F7"];
@@ -8002,7 +7304,7 @@ function parseCreateArgs(argv) {
8002
7304
  break;
8003
7305
  case "--help":
8004
7306
  case "-h":
8005
- printHelp3();
7307
+ printHelp2();
8006
7308
  process.exit(0);
8007
7309
  break;
8008
7310
  default:
@@ -8024,7 +7326,7 @@ function parseCreateArgs(argv) {
8024
7326
  }
8025
7327
  return opts;
8026
7328
  }
8027
- function printHelp3() {
7329
+ function printHelp2() {
8028
7330
  log3(`
8029
7331
  SolonGate Create \u2014 Scaffold a secure MCP server in seconds
8030
7332
 
@@ -8042,8 +7344,8 @@ EXAMPLES
8042
7344
  `);
8043
7345
  }
8044
7346
  function createProject(dir, name, _policy) {
8045
- writeFileSync6(
8046
- join6(dir, "package.json"),
7347
+ writeFileSync5(
7348
+ join5(dir, "package.json"),
8047
7349
  JSON.stringify(
8048
7350
  {
8049
7351
  name,
@@ -8072,8 +7374,8 @@ function createProject(dir, name, _policy) {
8072
7374
  2
8073
7375
  ) + "\n"
8074
7376
  );
8075
- writeFileSync6(
8076
- join6(dir, "tsconfig.json"),
7377
+ writeFileSync5(
7378
+ join5(dir, "tsconfig.json"),
8077
7379
  JSON.stringify(
8078
7380
  {
8079
7381
  compilerOptions: {
@@ -8093,9 +7395,9 @@ function createProject(dir, name, _policy) {
8093
7395
  2
8094
7396
  ) + "\n"
8095
7397
  );
8096
- mkdirSync6(join6(dir, "src"), { recursive: true });
8097
- writeFileSync6(
8098
- join6(dir, "src", "index.ts"),
7398
+ mkdirSync5(join5(dir, "src"), { recursive: true });
7399
+ writeFileSync5(
7400
+ join5(dir, "src", "index.ts"),
8099
7401
  `#!/usr/bin/env node
8100
7402
 
8101
7403
  console.log = (...args: unknown[]) => {
@@ -8136,8 +7438,8 @@ console.log('');
8136
7438
  console.log('Press Ctrl+C to stop.');
8137
7439
  `
8138
7440
  );
8139
- writeFileSync6(
8140
- join6(dir, ".mcp.json"),
7441
+ writeFileSync5(
7442
+ join5(dir, ".mcp.json"),
8141
7443
  JSON.stringify(
8142
7444
  {
8143
7445
  mcpServers: {
@@ -8154,13 +7456,13 @@ console.log('Press Ctrl+C to stop.');
8154
7456
  2
8155
7457
  ) + "\n"
8156
7458
  );
8157
- writeFileSync6(
8158
- join6(dir, ".env"),
7459
+ writeFileSync5(
7460
+ join5(dir, ".env"),
8159
7461
  `SOLONGATE_API_KEY=sg_live_YOUR_KEY_HERE
8160
7462
  `
8161
7463
  );
8162
- writeFileSync6(
8163
- join6(dir, ".gitignore"),
7464
+ writeFileSync5(
7465
+ join5(dir, ".gitignore"),
8164
7466
  `node_modules/
8165
7467
  dist/
8166
7468
  *.solongate-backup
@@ -8170,16 +7472,16 @@ dist/
8170
7472
  `
8171
7473
  );
8172
7474
  }
8173
- async function main4() {
7475
+ async function main3() {
8174
7476
  const opts = parseCreateArgs(process.argv);
8175
- const dir = resolve6(opts.name);
7477
+ const dir = resolve5(opts.name);
8176
7478
  printBanner("Create MCP Server");
8177
- if (existsSync7(dir)) {
7479
+ if (existsSync6(dir)) {
8178
7480
  log3(` ${c.red}Error:${c.reset} Directory "${opts.name}" already exists.`);
8179
7481
  process.exit(1);
8180
7482
  }
8181
7483
  withSpinner(`Setting up ${opts.name}...`, () => {
8182
- mkdirSync6(dir, { recursive: true });
7484
+ mkdirSync5(dir, { recursive: true });
8183
7485
  createProject(dir, opts.name, opts.policy);
8184
7486
  });
8185
7487
  if (!opts.noInstall) {
@@ -8244,7 +7546,7 @@ var init_create = __esm({
8244
7546
  "src/create.ts"() {
8245
7547
  "use strict";
8246
7548
  init_cli_utils();
8247
- main4().catch((err) => {
7549
+ main3().catch((err) => {
8248
7550
  log3(`Fatal: ${err instanceof Error ? err.message : String(err)}`);
8249
7551
  process.exit(1);
8250
7552
  });
@@ -8253,14 +7555,14 @@ var init_create = __esm({
8253
7555
 
8254
7556
  // src/pull-push.ts
8255
7557
  var pull_push_exports = {};
8256
- import { readFileSync as readFileSync8, writeFileSync as writeFileSync7, existsSync as existsSync8 } from "fs";
8257
- import { resolve as resolve7 } from "path";
7558
+ import { readFileSync as readFileSync7, writeFileSync as writeFileSync6, existsSync as existsSync7 } from "fs";
7559
+ import { resolve as resolve6 } from "path";
8258
7560
  function loadEnv() {
8259
7561
  if (process.env.SOLONGATE_API_KEY) return;
8260
- const envPath = resolve7(".env");
8261
- if (!existsSync8(envPath)) return;
7562
+ const envPath = resolve6(".env");
7563
+ if (!existsSync7(envPath)) return;
8262
7564
  try {
8263
- const content = readFileSync8(envPath, "utf-8");
7565
+ const content = readFileSync7(envPath, "utf-8");
8264
7566
  for (const line of content.split("\n")) {
8265
7567
  const trimmed = line.trim();
8266
7568
  if (!trimmed || trimmed.startsWith("#")) continue;
@@ -8315,7 +7617,7 @@ function parseCliArgs() {
8315
7617
  log4(red("ERROR: Pull/push/list requires a live API key (sg_live_...)."));
8316
7618
  process.exit(1);
8317
7619
  }
8318
- return { command, apiKey, file: resolve7(file), policyId };
7620
+ return { command, apiKey, file: resolve6(file), policyId };
8319
7621
  }
8320
7622
  async function listPolicies(apiKey) {
8321
7623
  const res = await fetch(`${API_URL}/api/v1/policies`, {
@@ -8448,7 +7750,7 @@ async function pull(apiKey, file, policyId) {
8448
7750
  const policy = await fetchCloudPolicy(apiKey, API_URL, policyId);
8449
7751
  const { id: _id, ...policyWithoutId } = policy;
8450
7752
  const json = JSON.stringify(policyWithoutId, null, 2) + "\n";
8451
- writeFileSync7(file, json, "utf-8");
7753
+ writeFileSync6(file, json, "utf-8");
8452
7754
  log4("");
8453
7755
  log4(green(" Saved to: ") + file);
8454
7756
  log4(` ${dim("Name:")} ${policy.name}`);
@@ -8460,7 +7762,7 @@ async function pull(apiKey, file, policyId) {
8460
7762
  log4("");
8461
7763
  }
8462
7764
  async function push(apiKey, file, policyId) {
8463
- if (!existsSync8(file)) {
7765
+ if (!existsSync7(file)) {
8464
7766
  log4(red(`ERROR: File not found: ${file}`));
8465
7767
  process.exit(1);
8466
7768
  }
@@ -8477,7 +7779,7 @@ async function push(apiKey, file, policyId) {
8477
7779
  log4(" solongate-proxy list");
8478
7780
  process.exit(1);
8479
7781
  }
8480
- const content = readFileSync8(file, "utf-8");
7782
+ const content = readFileSync7(file, "utf-8");
8481
7783
  let policy;
8482
7784
  try {
8483
7785
  policy = JSON.parse(content);
@@ -8520,7 +7822,7 @@ async function push(apiKey, file, policyId) {
8520
7822
  log4(` ${dim("Method:")} ${method === "PUT" ? "Updated existing" : "Created new"}`);
8521
7823
  log4("");
8522
7824
  }
8523
- async function main5() {
7825
+ async function main4() {
8524
7826
  const { command, apiKey, file, policyId } = parseCliArgs();
8525
7827
  try {
8526
7828
  if (command === "pull") {
@@ -8565,7 +7867,7 @@ var init_pull_push = __esm({
8565
7867
  cyan = (s) => `\x1B[36m${s}\x1B[0m`;
8566
7868
  magenta = (s) => `\x1B[35m${s}\x1B[0m`;
8567
7869
  API_URL = "https://api.solongate.com";
8568
- main5();
7870
+ main4();
8569
7871
  }
8570
7872
  });
8571
7873
 
@@ -10994,7 +10296,7 @@ var Mutex = class {
10994
10296
  this.locked = true;
10995
10297
  return;
10996
10298
  }
10997
- return new Promise((resolve8, reject) => {
10299
+ return new Promise((resolve7, reject) => {
10998
10300
  const timer = setTimeout(() => {
10999
10301
  const idx = this.queue.indexOf(onReady);
11000
10302
  if (idx !== -1) this.queue.splice(idx, 1);
@@ -11002,7 +10304,7 @@ var Mutex = class {
11002
10304
  }, timeoutMs);
11003
10305
  const onReady = () => {
11004
10306
  clearTimeout(timer);
11005
- resolve8();
10307
+ resolve7();
11006
10308
  };
11007
10309
  this.queue.push(onReady);
11008
10310
  });
@@ -11622,7 +10924,7 @@ ${msg.content.text}`;
11622
10924
 
11623
10925
  // src/index.ts
11624
10926
  init_cli_utils();
11625
- var CLI_SUBCOMMANDS = /* @__PURE__ */ new Set(["init", "login", "logout", "create", "inject", "pull", "push", "list", "ls"]);
10927
+ var CLI_SUBCOMMANDS = /* @__PURE__ */ new Set(["login", "logout", "create", "inject", "pull", "push", "list", "ls"]);
11626
10928
  var IS_HUMAN_CLI = process.argv.length <= 2 || CLI_SUBCOMMANDS.has(process.argv[2] ?? "");
11627
10929
  if (!IS_HUMAN_CLI) {
11628
10930
  console.log = (...args) => {
@@ -11651,17 +10953,12 @@ function printWelcome() {
11651
10953
  console.log(` ${c.cyan}https://dashboard.solongate.com${c.reset}`);
11652
10954
  console.log("");
11653
10955
  }
11654
- async function main6() {
10956
+ async function main5() {
11655
10957
  const subcommand = process.argv[2];
11656
10958
  if (process.argv.length <= 2) {
11657
10959
  printWelcome();
11658
10960
  return;
11659
10961
  }
11660
- if (subcommand === "init") {
11661
- process.argv.splice(2, 1);
11662
- await Promise.resolve().then(() => (init_init(), init_exports));
11663
- return;
11664
- }
11665
10962
  if (subcommand === "login") {
11666
10963
  await Promise.resolve().then(() => (init_login(), login_exports));
11667
10964
  return;
@@ -11696,4 +10993,4 @@ async function main6() {
11696
10993
  process.exit(1);
11697
10994
  }
11698
10995
  }
11699
- main6();
10996
+ main5();