@node9/proxy 1.0.7 → 1.0.8
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/LICENSE +183 -21
- package/README.md +1 -106
- package/dist/cli.js +278 -121
- package/dist/cli.mjs +278 -121
- package/dist/index.js +139 -31
- package/dist/index.mjs +139 -31
- package/package.json +4 -2
package/dist/index.js
CHANGED
|
@@ -38,13 +38,14 @@ module.exports = __toCommonJS(src_exports);
|
|
|
38
38
|
var import_chalk2 = __toESM(require("chalk"));
|
|
39
39
|
var import_prompts = require("@inquirer/prompts");
|
|
40
40
|
var import_fs = __toESM(require("fs"));
|
|
41
|
-
var
|
|
41
|
+
var import_path2 = __toESM(require("path"));
|
|
42
42
|
var import_os = __toESM(require("os"));
|
|
43
43
|
var import_picomatch = __toESM(require("picomatch"));
|
|
44
44
|
var import_sh_syntax = require("sh-syntax");
|
|
45
45
|
|
|
46
46
|
// src/ui/native.ts
|
|
47
47
|
var import_child_process = require("child_process");
|
|
48
|
+
var import_path = __toESM(require("path"));
|
|
48
49
|
var import_chalk = __toESM(require("chalk"));
|
|
49
50
|
var isTestEnv = () => {
|
|
50
51
|
return process.env.NODE_ENV === "test" || process.env.VITEST === "true" || !!process.env.VITEST || process.env.CI === "true" || !!process.env.CI || process.env.NODE9_TESTING === "1";
|
|
@@ -54,8 +55,29 @@ function smartTruncate(str, maxLen = 500) {
|
|
|
54
55
|
const edge = Math.floor(maxLen / 2) - 3;
|
|
55
56
|
return `${str.slice(0, edge)} ... ${str.slice(-edge)}`;
|
|
56
57
|
}
|
|
57
|
-
function
|
|
58
|
-
|
|
58
|
+
function extractContext(text, matchedWord) {
|
|
59
|
+
const lines = text.split("\n");
|
|
60
|
+
if (lines.length <= 7 || !matchedWord) return smartTruncate(text, 500);
|
|
61
|
+
const escaped = matchedWord.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
62
|
+
const pattern = new RegExp(`\\b${escaped}\\b`, "i");
|
|
63
|
+
const allHits = lines.map((line, i) => ({ i, line })).filter(({ line }) => pattern.test(line));
|
|
64
|
+
if (allHits.length === 0) return smartTruncate(text, 500);
|
|
65
|
+
const nonComment = allHits.find(({ line }) => {
|
|
66
|
+
const trimmed = line.trim();
|
|
67
|
+
return !trimmed.startsWith("//") && !trimmed.startsWith("#");
|
|
68
|
+
});
|
|
69
|
+
const hitIndex = (nonComment ?? allHits[0]).i;
|
|
70
|
+
const start = Math.max(0, hitIndex - 3);
|
|
71
|
+
const end = Math.min(lines.length, hitIndex + 4);
|
|
72
|
+
const snippet = lines.slice(start, end).map((line, i) => `${start + i === hitIndex ? "\u{1F6D1} " : " "}${line}`).join("\n");
|
|
73
|
+
const head = start > 0 ? `... [${start} lines hidden] ...
|
|
74
|
+
` : "";
|
|
75
|
+
const tail = end < lines.length ? `
|
|
76
|
+
... [${lines.length - end} lines hidden] ...` : "";
|
|
77
|
+
return `${head}${snippet}${tail}`;
|
|
78
|
+
}
|
|
79
|
+
function formatArgs(args, matchedField, matchedWord) {
|
|
80
|
+
if (args === null || args === void 0) return { message: "(none)", intent: "EXEC" };
|
|
59
81
|
let parsed = args;
|
|
60
82
|
if (typeof args === "string") {
|
|
61
83
|
const trimmed = args.trim();
|
|
@@ -66,11 +88,39 @@ function formatArgs(args) {
|
|
|
66
88
|
parsed = args;
|
|
67
89
|
}
|
|
68
90
|
} else {
|
|
69
|
-
return smartTruncate(args, 600);
|
|
91
|
+
return { message: smartTruncate(args, 600), intent: "EXEC" };
|
|
70
92
|
}
|
|
71
93
|
}
|
|
72
94
|
if (typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
73
95
|
const obj = parsed;
|
|
96
|
+
if (obj.old_string !== void 0 && obj.new_string !== void 0) {
|
|
97
|
+
const file = obj.file_path ? import_path.default.basename(String(obj.file_path)) : "file";
|
|
98
|
+
const oldPreview = smartTruncate(String(obj.old_string), 120);
|
|
99
|
+
const newPreview = extractContext(String(obj.new_string), matchedWord);
|
|
100
|
+
return {
|
|
101
|
+
intent: "EDIT",
|
|
102
|
+
message: `\u{1F4DD} EDITING: ${file}
|
|
103
|
+
\u{1F4C2} PATH: ${obj.file_path}
|
|
104
|
+
|
|
105
|
+
--- REPLACING ---
|
|
106
|
+
${oldPreview}
|
|
107
|
+
|
|
108
|
+
+++ NEW CODE +++
|
|
109
|
+
${newPreview}`
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
if (matchedField && obj[matchedField] !== void 0) {
|
|
113
|
+
const otherKeys = Object.keys(obj).filter((k) => k !== matchedField);
|
|
114
|
+
const context = otherKeys.length > 0 ? `\u2699\uFE0F Context: ${otherKeys.map((k) => `${k}=${smartTruncate(typeof obj[k] === "object" ? JSON.stringify(obj[k]) : String(obj[k]), 30)}`).join(", ")}
|
|
115
|
+
|
|
116
|
+
` : "";
|
|
117
|
+
const content = extractContext(String(obj[matchedField]), matchedWord);
|
|
118
|
+
return {
|
|
119
|
+
intent: "EXEC",
|
|
120
|
+
message: `${context}\u{1F6D1} [${matchedField.toUpperCase()}]:
|
|
121
|
+
${content}`
|
|
122
|
+
};
|
|
123
|
+
}
|
|
74
124
|
const codeKeys = [
|
|
75
125
|
"command",
|
|
76
126
|
"cmd",
|
|
@@ -91,14 +141,18 @@ function formatArgs(args) {
|
|
|
91
141
|
if (foundKey) {
|
|
92
142
|
const val = obj[foundKey];
|
|
93
143
|
const str = typeof val === "string" ? val : JSON.stringify(val);
|
|
94
|
-
return
|
|
95
|
-
|
|
144
|
+
return {
|
|
145
|
+
intent: "EXEC",
|
|
146
|
+
message: `[${foundKey.toUpperCase()}]:
|
|
147
|
+
${smartTruncate(str, 500)}`
|
|
148
|
+
};
|
|
96
149
|
}
|
|
97
|
-
|
|
150
|
+
const msg = Object.entries(obj).slice(0, 5).map(
|
|
98
151
|
([k, v]) => ` ${k}: ${smartTruncate(typeof v === "string" ? v : JSON.stringify(v), 300)}`
|
|
99
152
|
).join("\n");
|
|
153
|
+
return { intent: "EXEC", message: msg };
|
|
100
154
|
}
|
|
101
|
-
return smartTruncate(JSON.stringify(parsed), 200);
|
|
155
|
+
return { intent: "EXEC", message: smartTruncate(JSON.stringify(parsed), 200) };
|
|
102
156
|
}
|
|
103
157
|
function sendDesktopNotification(title, body) {
|
|
104
158
|
if (isTestEnv()) return;
|
|
@@ -151,10 +205,11 @@ function buildPangoMessage(toolName, formattedArgs, agent, explainableLabel, loc
|
|
|
151
205
|
}
|
|
152
206
|
return lines.join("\n");
|
|
153
207
|
}
|
|
154
|
-
async function askNativePopup(toolName, args, agent, explainableLabel, locked = false, signal) {
|
|
208
|
+
async function askNativePopup(toolName, args, agent, explainableLabel, locked = false, signal, matchedField, matchedWord) {
|
|
155
209
|
if (isTestEnv()) return "deny";
|
|
156
|
-
const formattedArgs = formatArgs(args);
|
|
157
|
-
const
|
|
210
|
+
const { message: formattedArgs, intent } = formatArgs(args, matchedField, matchedWord);
|
|
211
|
+
const intentLabel = intent === "EDIT" ? "Code Edit" : "Action Approval";
|
|
212
|
+
const title = locked ? `\u26A1 Node9 \u2014 Locked` : `\u{1F6E1}\uFE0F Node9 \u2014 ${intentLabel}`;
|
|
158
213
|
const message = buildPlainMessage(toolName, formattedArgs, agent, explainableLabel, locked);
|
|
159
214
|
process.stderr.write(import_chalk.default.yellow(`
|
|
160
215
|
\u{1F6E1}\uFE0F Node9: Intercepted "${toolName}" \u2014 awaiting user...
|
|
@@ -232,10 +287,10 @@ end run`;
|
|
|
232
287
|
}
|
|
233
288
|
|
|
234
289
|
// src/core.ts
|
|
235
|
-
var PAUSED_FILE =
|
|
236
|
-
var TRUST_FILE =
|
|
237
|
-
var LOCAL_AUDIT_LOG =
|
|
238
|
-
var HOOK_DEBUG_LOG =
|
|
290
|
+
var PAUSED_FILE = import_path2.default.join(import_os.default.homedir(), ".node9", "PAUSED");
|
|
291
|
+
var TRUST_FILE = import_path2.default.join(import_os.default.homedir(), ".node9", "trust.json");
|
|
292
|
+
var LOCAL_AUDIT_LOG = import_path2.default.join(import_os.default.homedir(), ".node9", "audit.log");
|
|
293
|
+
var HOOK_DEBUG_LOG = import_path2.default.join(import_os.default.homedir(), ".node9", "hook-debug.log");
|
|
239
294
|
function checkPause() {
|
|
240
295
|
try {
|
|
241
296
|
if (!import_fs.default.existsSync(PAUSED_FILE)) return { paused: false };
|
|
@@ -253,7 +308,7 @@ function checkPause() {
|
|
|
253
308
|
}
|
|
254
309
|
}
|
|
255
310
|
function atomicWriteSync(filePath, data, options) {
|
|
256
|
-
const dir =
|
|
311
|
+
const dir = import_path2.default.dirname(filePath);
|
|
257
312
|
if (!import_fs.default.existsSync(dir)) import_fs.default.mkdirSync(dir, { recursive: true });
|
|
258
313
|
const tmpPath = `${filePath}.${import_os.default.hostname()}.${process.pid}.tmp`;
|
|
259
314
|
import_fs.default.writeFileSync(tmpPath, data, options);
|
|
@@ -294,7 +349,7 @@ function writeTrustSession(toolName, durationMs) {
|
|
|
294
349
|
}
|
|
295
350
|
function appendToLog(logPath, entry) {
|
|
296
351
|
try {
|
|
297
|
-
const dir =
|
|
352
|
+
const dir = import_path2.default.dirname(logPath);
|
|
298
353
|
if (!import_fs.default.existsSync(dir)) import_fs.default.mkdirSync(dir, { recursive: true });
|
|
299
354
|
import_fs.default.appendFileSync(logPath, JSON.stringify(entry) + "\n");
|
|
300
355
|
} catch {
|
|
@@ -338,9 +393,9 @@ function matchesPattern(text, patterns) {
|
|
|
338
393
|
const withoutDotSlash = text.replace(/^\.\//, "");
|
|
339
394
|
return isMatch(withoutDotSlash) || isMatch(`./${withoutDotSlash}`);
|
|
340
395
|
}
|
|
341
|
-
function getNestedValue(obj,
|
|
396
|
+
function getNestedValue(obj, path3) {
|
|
342
397
|
if (!obj || typeof obj !== "object") return null;
|
|
343
|
-
return
|
|
398
|
+
return path3.split(".").reduce((prev, curr) => prev?.[curr], obj);
|
|
344
399
|
}
|
|
345
400
|
function evaluateSmartConditions(args, rule) {
|
|
346
401
|
if (!rule.conditions || rule.conditions.length === 0) return true;
|
|
@@ -529,6 +584,18 @@ var DEFAULT_CONFIG = {
|
|
|
529
584
|
"terminal.execute": "command",
|
|
530
585
|
"postgres:query": "sql"
|
|
531
586
|
},
|
|
587
|
+
snapshot: {
|
|
588
|
+
tools: [
|
|
589
|
+
"str_replace_based_edit_tool",
|
|
590
|
+
"write_file",
|
|
591
|
+
"edit_file",
|
|
592
|
+
"create_file",
|
|
593
|
+
"edit",
|
|
594
|
+
"replace"
|
|
595
|
+
],
|
|
596
|
+
onlyPaths: [],
|
|
597
|
+
ignorePaths: ["**/node_modules/**", "dist/**", "build/**", ".next/**", "**/*.log"]
|
|
598
|
+
},
|
|
532
599
|
rules: [
|
|
533
600
|
{
|
|
534
601
|
action: "rm",
|
|
@@ -564,7 +631,7 @@ var DEFAULT_CONFIG = {
|
|
|
564
631
|
var cachedConfig = null;
|
|
565
632
|
function getInternalToken() {
|
|
566
633
|
try {
|
|
567
|
-
const pidFile =
|
|
634
|
+
const pidFile = import_path2.default.join(import_os.default.homedir(), ".node9", "daemon.pid");
|
|
568
635
|
if (!import_fs.default.existsSync(pidFile)) return null;
|
|
569
636
|
const data = JSON.parse(import_fs.default.readFileSync(pidFile, "utf-8"));
|
|
570
637
|
process.kill(data.pid, 0);
|
|
@@ -668,9 +735,29 @@ async function evaluatePolicy(toolName, args, agent) {
|
|
|
668
735
|
})
|
|
669
736
|
);
|
|
670
737
|
if (isDangerous) {
|
|
738
|
+
let matchedField;
|
|
739
|
+
if (matchedDangerousWord && args && typeof args === "object" && !Array.isArray(args)) {
|
|
740
|
+
const obj = args;
|
|
741
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
742
|
+
if (typeof value === "string") {
|
|
743
|
+
try {
|
|
744
|
+
if (new RegExp(
|
|
745
|
+
`\\b${matchedDangerousWord.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}\\b`,
|
|
746
|
+
"i"
|
|
747
|
+
).test(value)) {
|
|
748
|
+
matchedField = key;
|
|
749
|
+
break;
|
|
750
|
+
}
|
|
751
|
+
} catch {
|
|
752
|
+
}
|
|
753
|
+
}
|
|
754
|
+
}
|
|
755
|
+
}
|
|
671
756
|
return {
|
|
672
757
|
decision: "review",
|
|
673
|
-
blockedByLabel: `Project/Global Config \u2014 dangerous word: "${matchedDangerousWord}"
|
|
758
|
+
blockedByLabel: `Project/Global Config \u2014 dangerous word: "${matchedDangerousWord}"`,
|
|
759
|
+
matchedWord: matchedDangerousWord,
|
|
760
|
+
matchedField
|
|
674
761
|
};
|
|
675
762
|
}
|
|
676
763
|
if (config.settings.mode === "strict") {
|
|
@@ -688,7 +775,7 @@ var DAEMON_PORT = 7391;
|
|
|
688
775
|
var DAEMON_HOST = "127.0.0.1";
|
|
689
776
|
function isDaemonRunning() {
|
|
690
777
|
try {
|
|
691
|
-
const pidFile =
|
|
778
|
+
const pidFile = import_path2.default.join(import_os.default.homedir(), ".node9", "daemon.pid");
|
|
692
779
|
if (!import_fs.default.existsSync(pidFile)) return false;
|
|
693
780
|
const { pid, port } = JSON.parse(import_fs.default.readFileSync(pidFile, "utf-8"));
|
|
694
781
|
if (port !== DAEMON_PORT) return false;
|
|
@@ -700,7 +787,7 @@ function isDaemonRunning() {
|
|
|
700
787
|
}
|
|
701
788
|
function getPersistentDecision(toolName) {
|
|
702
789
|
try {
|
|
703
|
-
const file =
|
|
790
|
+
const file = import_path2.default.join(import_os.default.homedir(), ".node9", "decisions.json");
|
|
704
791
|
if (!import_fs.default.existsSync(file)) return null;
|
|
705
792
|
const decisions = JSON.parse(import_fs.default.readFileSync(file, "utf-8"));
|
|
706
793
|
const d = decisions[toolName];
|
|
@@ -771,7 +858,7 @@ async function resolveViaDaemon(id, decision, internalToken) {
|
|
|
771
858
|
signal: AbortSignal.timeout(3e3)
|
|
772
859
|
});
|
|
773
860
|
}
|
|
774
|
-
async function authorizeHeadless(toolName, args, allowTerminalFallback = false, meta) {
|
|
861
|
+
async function authorizeHeadless(toolName, args, allowTerminalFallback = false, meta, options) {
|
|
775
862
|
if (process.env.NODE9_PAUSED === "1") return { approved: true, checkedBy: "paused" };
|
|
776
863
|
const pauseState = checkPause();
|
|
777
864
|
if (pauseState.paused) return { approved: true, checkedBy: "paused" };
|
|
@@ -791,6 +878,8 @@ async function authorizeHeadless(toolName, args, allowTerminalFallback = false,
|
|
|
791
878
|
}
|
|
792
879
|
const isManual = meta?.agent === "Terminal";
|
|
793
880
|
let explainableLabel = "Local Config";
|
|
881
|
+
let policyMatchedField;
|
|
882
|
+
let policyMatchedWord;
|
|
794
883
|
if (config.settings.mode === "audit") {
|
|
795
884
|
if (!isIgnoredTool(toolName)) {
|
|
796
885
|
const policyResult = await evaluatePolicy(toolName, args, meta?.agent);
|
|
@@ -826,6 +915,8 @@ async function authorizeHeadless(toolName, args, allowTerminalFallback = false,
|
|
|
826
915
|
};
|
|
827
916
|
}
|
|
828
917
|
explainableLabel = policyResult.blockedByLabel || "Local Config";
|
|
918
|
+
policyMatchedField = policyResult.matchedField;
|
|
919
|
+
policyMatchedWord = policyResult.matchedWord;
|
|
829
920
|
const persistent = getPersistentDecision(toolName);
|
|
830
921
|
if (persistent === "allow") {
|
|
831
922
|
if (creds?.apiKey) auditLocalAllow(toolName, args, "persistent", creds, meta);
|
|
@@ -918,7 +1009,7 @@ async function authorizeHeadless(toolName, args, allowTerminalFallback = false,
|
|
|
918
1009
|
racePromises.push(
|
|
919
1010
|
(async () => {
|
|
920
1011
|
try {
|
|
921
|
-
if (isDaemonRunning() && internalToken) {
|
|
1012
|
+
if (isDaemonRunning() && internalToken && !options?.calledFromDaemon) {
|
|
922
1013
|
viewerId = await notifyDaemonViewer(toolName, args, meta).catch(() => null);
|
|
923
1014
|
}
|
|
924
1015
|
const cloudResult = await pollNode9SaaS(cloudRequestId, creds, signal);
|
|
@@ -946,7 +1037,9 @@ async function authorizeHeadless(toolName, args, allowTerminalFallback = false,
|
|
|
946
1037
|
meta?.agent,
|
|
947
1038
|
explainableLabel,
|
|
948
1039
|
isRemoteLocked,
|
|
949
|
-
signal
|
|
1040
|
+
signal,
|
|
1041
|
+
policyMatchedField,
|
|
1042
|
+
policyMatchedWord
|
|
950
1043
|
);
|
|
951
1044
|
if (decision === "always_allow") {
|
|
952
1045
|
writeTrustSession(toolName, 36e5);
|
|
@@ -963,7 +1056,7 @@ async function authorizeHeadless(toolName, args, allowTerminalFallback = false,
|
|
|
963
1056
|
})()
|
|
964
1057
|
);
|
|
965
1058
|
}
|
|
966
|
-
if (approvers.browser && isDaemonRunning()) {
|
|
1059
|
+
if (approvers.browser && isDaemonRunning() && !options?.calledFromDaemon) {
|
|
967
1060
|
racePromises.push(
|
|
968
1061
|
(async () => {
|
|
969
1062
|
try {
|
|
@@ -1099,8 +1192,8 @@ REASON: Action blocked because no approval channels are available. (Native/Brows
|
|
|
1099
1192
|
}
|
|
1100
1193
|
function getConfig() {
|
|
1101
1194
|
if (cachedConfig) return cachedConfig;
|
|
1102
|
-
const globalPath =
|
|
1103
|
-
const projectPath =
|
|
1195
|
+
const globalPath = import_path2.default.join(import_os.default.homedir(), ".node9", "config.json");
|
|
1196
|
+
const projectPath = import_path2.default.join(process.cwd(), "node9.config.json");
|
|
1104
1197
|
const globalConfig = tryLoadConfig(globalPath);
|
|
1105
1198
|
const projectConfig = tryLoadConfig(projectPath);
|
|
1106
1199
|
const mergedSettings = {
|
|
@@ -1113,7 +1206,12 @@ function getConfig() {
|
|
|
1113
1206
|
ignoredTools: [...DEFAULT_CONFIG.policy.ignoredTools],
|
|
1114
1207
|
toolInspection: { ...DEFAULT_CONFIG.policy.toolInspection },
|
|
1115
1208
|
rules: [...DEFAULT_CONFIG.policy.rules],
|
|
1116
|
-
smartRules: [...DEFAULT_CONFIG.policy.smartRules]
|
|
1209
|
+
smartRules: [...DEFAULT_CONFIG.policy.smartRules],
|
|
1210
|
+
snapshot: {
|
|
1211
|
+
tools: [...DEFAULT_CONFIG.policy.snapshot.tools],
|
|
1212
|
+
onlyPaths: [...DEFAULT_CONFIG.policy.snapshot.onlyPaths],
|
|
1213
|
+
ignorePaths: [...DEFAULT_CONFIG.policy.snapshot.ignorePaths]
|
|
1214
|
+
}
|
|
1117
1215
|
};
|
|
1118
1216
|
const applyLayer = (source) => {
|
|
1119
1217
|
if (!source) return;
|
|
@@ -1125,6 +1223,7 @@ function getConfig() {
|
|
|
1125
1223
|
if (s.enableHookLogDebug !== void 0)
|
|
1126
1224
|
mergedSettings.enableHookLogDebug = s.enableHookLogDebug;
|
|
1127
1225
|
if (s.approvers) mergedSettings.approvers = { ...mergedSettings.approvers, ...s.approvers };
|
|
1226
|
+
if (s.approvalTimeoutMs !== void 0) mergedSettings.approvalTimeoutMs = s.approvalTimeoutMs;
|
|
1128
1227
|
if (s.environment !== void 0) mergedSettings.environment = s.environment;
|
|
1129
1228
|
if (p.sandboxPaths) mergedPolicy.sandboxPaths.push(...p.sandboxPaths);
|
|
1130
1229
|
if (p.ignoredTools) mergedPolicy.ignoredTools.push(...p.ignoredTools);
|
|
@@ -1133,6 +1232,12 @@ function getConfig() {
|
|
|
1133
1232
|
mergedPolicy.toolInspection = { ...mergedPolicy.toolInspection, ...p.toolInspection };
|
|
1134
1233
|
if (p.rules) mergedPolicy.rules.push(...p.rules);
|
|
1135
1234
|
if (p.smartRules) mergedPolicy.smartRules.push(...p.smartRules);
|
|
1235
|
+
if (p.snapshot) {
|
|
1236
|
+
const s2 = p.snapshot;
|
|
1237
|
+
if (s2.tools) mergedPolicy.snapshot.tools.push(...s2.tools);
|
|
1238
|
+
if (s2.onlyPaths) mergedPolicy.snapshot.onlyPaths.push(...s2.onlyPaths);
|
|
1239
|
+
if (s2.ignorePaths) mergedPolicy.snapshot.ignorePaths.push(...s2.ignorePaths);
|
|
1240
|
+
}
|
|
1136
1241
|
};
|
|
1137
1242
|
applyLayer(globalConfig);
|
|
1138
1243
|
applyLayer(projectConfig);
|
|
@@ -1140,6 +1245,9 @@ function getConfig() {
|
|
|
1140
1245
|
mergedPolicy.sandboxPaths = [...new Set(mergedPolicy.sandboxPaths)];
|
|
1141
1246
|
mergedPolicy.dangerousWords = [...new Set(mergedPolicy.dangerousWords)];
|
|
1142
1247
|
mergedPolicy.ignoredTools = [...new Set(mergedPolicy.ignoredTools)];
|
|
1248
|
+
mergedPolicy.snapshot.tools = [...new Set(mergedPolicy.snapshot.tools)];
|
|
1249
|
+
mergedPolicy.snapshot.onlyPaths = [...new Set(mergedPolicy.snapshot.onlyPaths)];
|
|
1250
|
+
mergedPolicy.snapshot.ignorePaths = [...new Set(mergedPolicy.snapshot.ignorePaths)];
|
|
1143
1251
|
cachedConfig = {
|
|
1144
1252
|
settings: mergedSettings,
|
|
1145
1253
|
policy: mergedPolicy,
|
|
@@ -1168,7 +1276,7 @@ function getCredentials() {
|
|
|
1168
1276
|
};
|
|
1169
1277
|
}
|
|
1170
1278
|
try {
|
|
1171
|
-
const credPath =
|
|
1279
|
+
const credPath = import_path2.default.join(import_os.default.homedir(), ".node9", "credentials.json");
|
|
1172
1280
|
if (import_fs.default.existsSync(credPath)) {
|
|
1173
1281
|
const creds = JSON.parse(import_fs.default.readFileSync(credPath, "utf-8"));
|
|
1174
1282
|
const profileName = process.env.NODE9_PROFILE || "default";
|