@node9/proxy 1.67.5 → 2.0.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/cli.js +575 -938
- package/dist/cli.mjs +568 -931
- package/dist/dashboard.mjs +0 -60
- package/dist/index.js +0 -50
- package/dist/index.mjs +0 -50
- package/package.json +1 -1
package/dist/cli.mjs
CHANGED
|
@@ -248,8 +248,8 @@ function sanitizeConfig(raw) {
|
|
|
248
248
|
}
|
|
249
249
|
}
|
|
250
250
|
const lines = result.error.issues.map((issue) => {
|
|
251
|
-
const
|
|
252
|
-
return ` \u2022 ${
|
|
251
|
+
const path71 = issue.path.length > 0 ? issue.path.join(".") : "root";
|
|
252
|
+
return ` \u2022 ${path71}: ${issue.message}`;
|
|
253
253
|
});
|
|
254
254
|
return {
|
|
255
255
|
sanitized,
|
|
@@ -634,9 +634,9 @@ function matchesPattern(text, patterns) {
|
|
|
634
634
|
const withoutDotSlash = text.replace(/^\.\//, "");
|
|
635
635
|
return isMatch(withoutDotSlash) || isMatch(`./${withoutDotSlash}`);
|
|
636
636
|
}
|
|
637
|
-
function getNestedValue(obj,
|
|
637
|
+
function getNestedValue(obj, path71) {
|
|
638
638
|
if (!obj || typeof obj !== "object") return null;
|
|
639
|
-
const segments =
|
|
639
|
+
const segments = path71.split(".");
|
|
640
640
|
for (const seg of segments) {
|
|
641
641
|
if (FORBIDDEN_PATH_SEGMENTS.has(seg)) return null;
|
|
642
642
|
}
|
|
@@ -5105,11 +5105,6 @@ function getConfig(cwd) {
|
|
|
5105
5105
|
ignoredTools: [...DEFAULT_CONFIG.policy.ignoredTools],
|
|
5106
5106
|
toolInspection: { ...DEFAULT_CONFIG.policy.toolInspection },
|
|
5107
5107
|
smartRules: [...DEFAULT_CONFIG.policy.smartRules],
|
|
5108
|
-
snapshot: {
|
|
5109
|
-
tools: [...DEFAULT_CONFIG.policy.snapshot.tools],
|
|
5110
|
-
onlyPaths: [...DEFAULT_CONFIG.policy.snapshot.onlyPaths],
|
|
5111
|
-
ignorePaths: [...DEFAULT_CONFIG.policy.snapshot.ignorePaths]
|
|
5112
|
-
},
|
|
5113
5108
|
dlp: { ...DEFAULT_CONFIG.policy.dlp },
|
|
5114
5109
|
egress: {
|
|
5115
5110
|
...DEFAULT_CONFIG.policy.egress,
|
|
@@ -5177,12 +5172,6 @@ function getConfig(cwd) {
|
|
|
5177
5172
|
);
|
|
5178
5173
|
mergedPolicy.smartRules = [...filteredBlocks, ...localRules, ...filteredNonBlocks];
|
|
5179
5174
|
}
|
|
5180
|
-
if (p.snapshot) {
|
|
5181
|
-
const s2 = p.snapshot;
|
|
5182
|
-
if (s2.tools) mergedPolicy.snapshot.tools.push(...s2.tools);
|
|
5183
|
-
if (s2.onlyPaths) mergedPolicy.snapshot.onlyPaths.push(...s2.onlyPaths);
|
|
5184
|
-
if (s2.ignorePaths) mergedPolicy.snapshot.ignorePaths.push(...s2.ignorePaths);
|
|
5185
|
-
}
|
|
5186
5175
|
if (p.dlp) {
|
|
5187
5176
|
const d = p.dlp;
|
|
5188
5177
|
if (d.enabled !== void 0) mergedPolicy.dlp.enabled = d.enabled;
|
|
@@ -5388,13 +5377,13 @@ function getConfig(cwd) {
|
|
|
5388
5377
|
}
|
|
5389
5378
|
if (Array.isArray(mc.jailPaths)) {
|
|
5390
5379
|
for (const jp of mc.jailPaths) {
|
|
5391
|
-
const
|
|
5392
|
-
if (!
|
|
5380
|
+
const path71 = typeof jp?.path === "string" ? jp.path.trim() : "";
|
|
5381
|
+
if (!path71) continue;
|
|
5393
5382
|
const verdict = jp?.verdict === "review" ? "review" : "block";
|
|
5394
|
-
for (const r of pathRules(
|
|
5383
|
+
for (const r of pathRules(path71, verdict, "org-managed jail")) {
|
|
5395
5384
|
mergedPolicy.smartRules.push({ ...r, name: `org:${r.name}` });
|
|
5396
5385
|
}
|
|
5397
|
-
mergedPolicy.managedJailPaths.push({ path:
|
|
5386
|
+
mergedPolicy.managedJailPaths.push({ path: path71, verdict });
|
|
5398
5387
|
}
|
|
5399
5388
|
}
|
|
5400
5389
|
if (Array.isArray(mc.trustedHosts)) {
|
|
@@ -5517,10 +5506,6 @@ function getConfig(cwd) {
|
|
|
5517
5506
|
mergedPolicy.dangerousWords = [...new Set(mergedPolicy.dangerousWords)];
|
|
5518
5507
|
mergedPolicy.ignoredTools = [...new Set(mergedPolicy.ignoredTools)];
|
|
5519
5508
|
mergedPolicy.skillPinning.roots = [...new Set(mergedPolicy.skillPinning.roots)];
|
|
5520
|
-
mergedPolicy.snapshot.tools = [...new Set(mergedPolicy.snapshot.tools)];
|
|
5521
|
-
mergedPolicy.snapshot.onlyPaths = [...new Set(mergedPolicy.snapshot.onlyPaths)];
|
|
5522
|
-
mergedPolicy.snapshot.ignorePaths = [...new Set(mergedPolicy.snapshot.ignorePaths)];
|
|
5523
|
-
mergedSettings.enableUndo = false;
|
|
5524
5509
|
const result = {
|
|
5525
5510
|
settings: mergedSettings,
|
|
5526
5511
|
policy: mergedPolicy,
|
|
@@ -5603,19 +5588,6 @@ var init_config = __esm({
|
|
|
5603
5588
|
settings: {
|
|
5604
5589
|
mode: "standard",
|
|
5605
5590
|
autoStartDaemon: true,
|
|
5606
|
-
// The undo feature was REMOVED. This default is one of two places that say
|
|
5607
|
-
// so; the other is the pin further down, which overwrites whatever a config
|
|
5608
|
-
// file, the dashboard or the cloud supplies. Setting `enableUndo` anywhere
|
|
5609
|
-
// has no effect — do not restore the advice that used to live here, because
|
|
5610
|
-
// a comment recommending a knob that is silently discarded is the same lie
|
|
5611
|
-
// on disk the pin exists to prevent.
|
|
5612
|
-
//
|
|
5613
|
-
// Why it went: the store was a per-project bare git repo with no size
|
|
5614
|
-
// ceiling, and eviction dropped the index row without deleting the objects.
|
|
5615
|
-
// On one machine it reached 378G (352G of it orphaned tmp_pack_* from an
|
|
5616
|
-
// interrupted `git gc`) and filled the disk. A security tool must not be
|
|
5617
|
-
// what fills a customer's disk. Leftovers: `node9 undo --purge`.
|
|
5618
|
-
enableUndo: false,
|
|
5619
5591
|
enableHookLogDebug: true,
|
|
5620
5592
|
approvalTimeoutMs: 12e4,
|
|
5621
5593
|
// 120-second auto-deny timeout
|
|
@@ -5656,25 +5628,6 @@ var init_config = __esm({
|
|
|
5656
5628
|
"terminal.execute": "command",
|
|
5657
5629
|
"postgres:query": "sql"
|
|
5658
5630
|
},
|
|
5659
|
-
snapshot: {
|
|
5660
|
-
tools: [
|
|
5661
|
-
"str_replace_based_edit_tool",
|
|
5662
|
-
"write_file",
|
|
5663
|
-
"edit_file",
|
|
5664
|
-
"create_file",
|
|
5665
|
-
"edit",
|
|
5666
|
-
"replace",
|
|
5667
|
-
// Claude / canonicalised Hermes — shouldSnapshot lowercases the
|
|
5668
|
-
// incoming name before set-membership, so we list the lowercase
|
|
5669
|
-
// forms of `Bash`/`Write`/`Edit`/`MultiEdit`. Without these,
|
|
5670
|
-
// post-canonicalisation Hermes `patch` / `write_file` (which now
|
|
5671
|
-
// arrive as `Edit` / `Write`) silently skipped snapshotting.
|
|
5672
|
-
"write",
|
|
5673
|
-
"multiedit"
|
|
5674
|
-
],
|
|
5675
|
-
onlyPaths: [],
|
|
5676
|
-
ignorePaths: ["**/node_modules/**", "dist/**", "build/**", ".next/**", "**/*.log"]
|
|
5677
|
-
},
|
|
5678
5631
|
smartRules: [
|
|
5679
5632
|
// ── rm safety (critical — always evaluated first) ──────────────────────
|
|
5680
5633
|
{
|
|
@@ -6023,19 +5976,6 @@ var init_provenance = __esm({
|
|
|
6023
5976
|
import fs7 from "fs";
|
|
6024
5977
|
import path7 from "path";
|
|
6025
5978
|
import os6 from "os";
|
|
6026
|
-
import pm2 from "picomatch";
|
|
6027
|
-
function shouldSnapshot(toolName, args, config) {
|
|
6028
|
-
if (!config.settings.enableUndo) return false;
|
|
6029
|
-
const snap = config.policy.snapshot;
|
|
6030
|
-
if (!snap.tools.includes(toolName.toLowerCase())) return false;
|
|
6031
|
-
const a = args && typeof args === "object" ? args : {};
|
|
6032
|
-
const filePath = String(a.file_path ?? a.path ?? a.filename ?? "");
|
|
6033
|
-
if (filePath) {
|
|
6034
|
-
if (snap.ignorePaths.length && pm2(snap.ignorePaths)(filePath)) return false;
|
|
6035
|
-
if (snap.onlyPaths.length && !pm2(snap.onlyPaths)(filePath)) return false;
|
|
6036
|
-
}
|
|
6037
|
-
return true;
|
|
6038
|
-
}
|
|
6039
5979
|
async function evaluatePolicy2(toolName, args, agent, cwd, opts) {
|
|
6040
5980
|
const config = getConfig();
|
|
6041
5981
|
const activeEnvironment = getActiveEnvironment(config) ?? void 0;
|
|
@@ -16908,16 +16848,6 @@ function bindActivitySocket() {
|
|
|
16908
16848
|
sessionHistory.recordTestFail(data.ts);
|
|
16909
16849
|
return;
|
|
16910
16850
|
}
|
|
16911
|
-
if (data.status === "snapshot") {
|
|
16912
|
-
broadcast("snapshot", {
|
|
16913
|
-
hash: data.hash,
|
|
16914
|
-
tool: data.tool,
|
|
16915
|
-
argsSummary: data.argsSummary,
|
|
16916
|
-
fileCount: data.fileCount,
|
|
16917
|
-
ts: data.ts
|
|
16918
|
-
});
|
|
16919
|
-
return;
|
|
16920
|
-
}
|
|
16921
16851
|
if (data.status === "execution-completed") {
|
|
16922
16852
|
broadcast("execution-result", {
|
|
16923
16853
|
id: data.id,
|
|
@@ -22818,7 +22748,7 @@ var require_util = __commonJS({
|
|
|
22818
22748
|
var { kDestroyed, kBodyUsed, kListeners, kBody } = require_symbols();
|
|
22819
22749
|
var { IncomingMessage } = __require("http");
|
|
22820
22750
|
var stream = __require("stream");
|
|
22821
|
-
var
|
|
22751
|
+
var net3 = __require("net");
|
|
22822
22752
|
var { stringify } = __require("querystring");
|
|
22823
22753
|
var { EventEmitter: EE } = __require("events");
|
|
22824
22754
|
var timers = require_timers();
|
|
@@ -22930,14 +22860,14 @@ var require_util = __commonJS({
|
|
|
22930
22860
|
}
|
|
22931
22861
|
const port = url.port != null ? url.port : url.protocol === "https:" ? 443 : 80;
|
|
22932
22862
|
let origin = url.origin != null ? url.origin : `${url.protocol || ""}//${url.hostname || ""}:${port}`;
|
|
22933
|
-
let
|
|
22863
|
+
let path71 = url.path != null ? url.path : `${url.pathname || ""}${url.search || ""}`;
|
|
22934
22864
|
if (origin[origin.length - 1] === "/") {
|
|
22935
22865
|
origin = origin.slice(0, origin.length - 1);
|
|
22936
22866
|
}
|
|
22937
|
-
if (
|
|
22938
|
-
|
|
22867
|
+
if (path71 && path71[0] !== "/") {
|
|
22868
|
+
path71 = `/${path71}`;
|
|
22939
22869
|
}
|
|
22940
|
-
return new URL(`${origin}${
|
|
22870
|
+
return new URL(`${origin}${path71}`);
|
|
22941
22871
|
}
|
|
22942
22872
|
if (!isHttpOrHttpsPrefixed(url.origin || url.protocol)) {
|
|
22943
22873
|
throw new InvalidArgumentError("Invalid URL protocol: the URL must start with `http:` or `https:`.");
|
|
@@ -22967,7 +22897,7 @@ var require_util = __commonJS({
|
|
|
22967
22897
|
}
|
|
22968
22898
|
assert(typeof host === "string");
|
|
22969
22899
|
const servername = getHostname(host);
|
|
22970
|
-
if (
|
|
22900
|
+
if (net3.isIP(servername)) {
|
|
22971
22901
|
return "";
|
|
22972
22902
|
}
|
|
22973
22903
|
return servername;
|
|
@@ -23758,9 +23688,9 @@ var require_diagnostics = __commonJS({
|
|
|
23758
23688
|
"undici:client:sendHeaders",
|
|
23759
23689
|
(evt) => {
|
|
23760
23690
|
const {
|
|
23761
|
-
request: { method, path:
|
|
23691
|
+
request: { method, path: path71, origin }
|
|
23762
23692
|
} = evt;
|
|
23763
|
-
debugLog("sending request to %s %s%s", method, origin,
|
|
23693
|
+
debugLog("sending request to %s %s%s", method, origin, path71);
|
|
23764
23694
|
}
|
|
23765
23695
|
);
|
|
23766
23696
|
}
|
|
@@ -23778,14 +23708,14 @@ var require_diagnostics = __commonJS({
|
|
|
23778
23708
|
"undici:request:headers",
|
|
23779
23709
|
(evt) => {
|
|
23780
23710
|
const {
|
|
23781
|
-
request: { method, path:
|
|
23711
|
+
request: { method, path: path71, origin },
|
|
23782
23712
|
response: { statusCode }
|
|
23783
23713
|
} = evt;
|
|
23784
23714
|
debugLog(
|
|
23785
23715
|
"received response to %s %s%s - HTTP %d",
|
|
23786
23716
|
method,
|
|
23787
23717
|
origin,
|
|
23788
|
-
|
|
23718
|
+
path71,
|
|
23789
23719
|
statusCode
|
|
23790
23720
|
);
|
|
23791
23721
|
}
|
|
@@ -23794,23 +23724,23 @@ var require_diagnostics = __commonJS({
|
|
|
23794
23724
|
"undici:request:trailers",
|
|
23795
23725
|
(evt) => {
|
|
23796
23726
|
const {
|
|
23797
|
-
request: { method, path:
|
|
23727
|
+
request: { method, path: path71, origin }
|
|
23798
23728
|
} = evt;
|
|
23799
|
-
debugLog("trailers received from %s %s%s", method, origin,
|
|
23729
|
+
debugLog("trailers received from %s %s%s", method, origin, path71);
|
|
23800
23730
|
}
|
|
23801
23731
|
);
|
|
23802
23732
|
diagnosticsChannel.subscribe(
|
|
23803
23733
|
"undici:request:error",
|
|
23804
23734
|
(evt) => {
|
|
23805
23735
|
const {
|
|
23806
|
-
request: { method, path:
|
|
23736
|
+
request: { method, path: path71, origin },
|
|
23807
23737
|
error
|
|
23808
23738
|
} = evt;
|
|
23809
23739
|
debugLog(
|
|
23810
23740
|
"request to %s %s%s errored - %s",
|
|
23811
23741
|
method,
|
|
23812
23742
|
origin,
|
|
23813
|
-
|
|
23743
|
+
path71,
|
|
23814
23744
|
error.message
|
|
23815
23745
|
);
|
|
23816
23746
|
}
|
|
@@ -23913,7 +23843,7 @@ var require_request = __commonJS({
|
|
|
23913
23843
|
var kHandler = /* @__PURE__ */ Symbol("handler");
|
|
23914
23844
|
var Request = class {
|
|
23915
23845
|
constructor(origin, {
|
|
23916
|
-
path:
|
|
23846
|
+
path: path71,
|
|
23917
23847
|
method,
|
|
23918
23848
|
body,
|
|
23919
23849
|
headers,
|
|
@@ -23930,11 +23860,11 @@ var require_request = __commonJS({
|
|
|
23930
23860
|
maxRedirections,
|
|
23931
23861
|
typeOfService
|
|
23932
23862
|
}, handler) {
|
|
23933
|
-
if (typeof
|
|
23863
|
+
if (typeof path71 !== "string") {
|
|
23934
23864
|
throw new InvalidArgumentError("path must be a string");
|
|
23935
|
-
} else if (
|
|
23865
|
+
} else if (path71[0] !== "/" && !(path71.startsWith("http://") || path71.startsWith("https://")) && method !== "CONNECT") {
|
|
23936
23866
|
throw new InvalidArgumentError("path must be an absolute URL or start with a slash");
|
|
23937
|
-
} else if (invalidPathRegex.test(
|
|
23867
|
+
} else if (invalidPathRegex.test(path71)) {
|
|
23938
23868
|
throw new InvalidArgumentError("invalid request path");
|
|
23939
23869
|
}
|
|
23940
23870
|
if (typeof method !== "string") {
|
|
@@ -24009,7 +23939,7 @@ var require_request = __commonJS({
|
|
|
24009
23939
|
this.completed = false;
|
|
24010
23940
|
this.aborted = false;
|
|
24011
23941
|
this.upgrade = upgrade || null;
|
|
24012
|
-
this.path = query ? serializePathWithQuery(
|
|
23942
|
+
this.path = query ? serializePathWithQuery(path71, query) : path71;
|
|
24013
23943
|
this.origin = origin;
|
|
24014
23944
|
this.protocol = getProtocolFromUrlString(origin);
|
|
24015
23945
|
this.idempotent = idempotent == null ? method === "HEAD" || method === "GET" : idempotent;
|
|
@@ -24588,7 +24518,7 @@ var require_dispatcher_base = __commonJS({
|
|
|
24588
24518
|
var require_connect = __commonJS({
|
|
24589
24519
|
"node_modules/undici/lib/core/connect.js"(exports, module) {
|
|
24590
24520
|
"use strict";
|
|
24591
|
-
var
|
|
24521
|
+
var net3 = __require("net");
|
|
24592
24522
|
var assert = __require("assert");
|
|
24593
24523
|
var util = require_util();
|
|
24594
24524
|
var { InvalidArgumentError } = require_errors();
|
|
@@ -24657,7 +24587,7 @@ var require_connect = __commonJS({
|
|
|
24657
24587
|
} else {
|
|
24658
24588
|
assert(!httpSocket, "httpSocket can only be sent on TLS update");
|
|
24659
24589
|
port = port || 80;
|
|
24660
|
-
socket =
|
|
24590
|
+
socket = net3.connect({
|
|
24661
24591
|
highWaterMark: 64 * 1024,
|
|
24662
24592
|
// Same as nodejs fs streams.
|
|
24663
24593
|
...options,
|
|
@@ -29048,7 +28978,7 @@ var require_client_h1 = __commonJS({
|
|
|
29048
28978
|
return method !== "GET" && method !== "HEAD" && method !== "OPTIONS" && method !== "TRACE" && method !== "CONNECT";
|
|
29049
28979
|
}
|
|
29050
28980
|
function writeH1(client, request2) {
|
|
29051
|
-
const { method, path:
|
|
28981
|
+
const { method, path: path71, host, upgrade, blocking, reset } = request2;
|
|
29052
28982
|
let { body, headers, contentLength } = request2;
|
|
29053
28983
|
const expectsPayload = method === "PUT" || method === "POST" || method === "PATCH" || method === "QUERY" || method === "PROPFIND" || method === "PROPPATCH";
|
|
29054
28984
|
if (util.isFormDataLike(body)) {
|
|
@@ -29117,7 +29047,7 @@ var require_client_h1 = __commonJS({
|
|
|
29117
29047
|
if (socket.setTypeOfService) {
|
|
29118
29048
|
socket.setTypeOfService(request2.typeOfService);
|
|
29119
29049
|
}
|
|
29120
|
-
let header = `${method} ${
|
|
29050
|
+
let header = `${method} ${path71} HTTP/1.1\r
|
|
29121
29051
|
`;
|
|
29122
29052
|
if (typeof host === "string") {
|
|
29123
29053
|
header += `host: ${host}\r
|
|
@@ -29770,7 +29700,7 @@ var require_client_h2 = __commonJS({
|
|
|
29770
29700
|
function writeH2(client, request2) {
|
|
29771
29701
|
const requestTimeout = request2.bodyTimeout ?? client[kBodyTimeout];
|
|
29772
29702
|
const session = client[kHTTP2Session];
|
|
29773
|
-
const { method, path:
|
|
29703
|
+
const { method, path: path71, host, upgrade, expectContinue, signal, protocol, headers: reqHeaders } = request2;
|
|
29774
29704
|
let { body } = request2;
|
|
29775
29705
|
if (upgrade != null && upgrade !== "websocket") {
|
|
29776
29706
|
util.errorRequest(client, request2, new InvalidArgumentError(`Custom upgrade "${upgrade}" not supported over HTTP/2`));
|
|
@@ -29838,7 +29768,7 @@ var require_client_h2 = __commonJS({
|
|
|
29838
29768
|
}
|
|
29839
29769
|
headers[HTTP2_HEADER_METHOD] = "CONNECT";
|
|
29840
29770
|
headers[HTTP2_HEADER_PROTOCOL] = "websocket";
|
|
29841
|
-
headers[HTTP2_HEADER_PATH] =
|
|
29771
|
+
headers[HTTP2_HEADER_PATH] = path71;
|
|
29842
29772
|
if (protocol === "ws:" || protocol === "wss:") {
|
|
29843
29773
|
headers[HTTP2_HEADER_SCHEME] = protocol === "ws:" ? "http" : "https";
|
|
29844
29774
|
} else {
|
|
@@ -29879,7 +29809,7 @@ var require_client_h2 = __commonJS({
|
|
|
29879
29809
|
stream.setTimeout(requestTimeout);
|
|
29880
29810
|
return true;
|
|
29881
29811
|
}
|
|
29882
|
-
headers[HTTP2_HEADER_PATH] =
|
|
29812
|
+
headers[HTTP2_HEADER_PATH] = path71;
|
|
29883
29813
|
headers[HTTP2_HEADER_SCHEME] = protocol === "http:" ? "http" : "https";
|
|
29884
29814
|
const expectsPayload = method === "PUT" || method === "POST" || method === "PATCH";
|
|
29885
29815
|
if (body && typeof body.read === "function") {
|
|
@@ -30195,7 +30125,7 @@ var require_client = __commonJS({
|
|
|
30195
30125
|
"node_modules/undici/lib/dispatcher/client.js"(exports, module) {
|
|
30196
30126
|
"use strict";
|
|
30197
30127
|
var assert = __require("assert");
|
|
30198
|
-
var
|
|
30128
|
+
var net3 = __require("net");
|
|
30199
30129
|
var http7 = __require("http");
|
|
30200
30130
|
var util = require_util();
|
|
30201
30131
|
var { ClientStats } = require_stats();
|
|
@@ -30349,7 +30279,7 @@ var require_client = __commonJS({
|
|
|
30349
30279
|
if (maxRequestsPerClient != null && (!Number.isInteger(maxRequestsPerClient) || maxRequestsPerClient < 0)) {
|
|
30350
30280
|
throw new InvalidArgumentError("maxRequestsPerClient must be a positive number");
|
|
30351
30281
|
}
|
|
30352
|
-
if (localAddress != null && (typeof localAddress !== "string" ||
|
|
30282
|
+
if (localAddress != null && (typeof localAddress !== "string" || net3.isIP(localAddress) === 0)) {
|
|
30353
30283
|
throw new InvalidArgumentError("localAddress must be valid string IP address");
|
|
30354
30284
|
}
|
|
30355
30285
|
if (maxResponseSize != null && (!Number.isInteger(maxResponseSize) || maxResponseSize < -1)) {
|
|
@@ -30521,7 +30451,7 @@ var require_client = __commonJS({
|
|
|
30521
30451
|
const idx = hostname.indexOf("]");
|
|
30522
30452
|
assert(idx !== -1);
|
|
30523
30453
|
const ip = hostname.substring(1, idx);
|
|
30524
|
-
assert(
|
|
30454
|
+
assert(net3.isIPv6(ip));
|
|
30525
30455
|
hostname = ip;
|
|
30526
30456
|
}
|
|
30527
30457
|
client[kConnecting] = true;
|
|
@@ -31464,10 +31394,10 @@ var require_socks5_utils = __commonJS({
|
|
|
31464
31394
|
"node_modules/undici/lib/core/socks5-utils.js"(exports, module) {
|
|
31465
31395
|
"use strict";
|
|
31466
31396
|
var { Buffer: Buffer2 } = __require("buffer");
|
|
31467
|
-
var
|
|
31397
|
+
var net3 = __require("net");
|
|
31468
31398
|
var { InvalidArgumentError } = require_errors();
|
|
31469
31399
|
function parseAddress(address) {
|
|
31470
|
-
if (
|
|
31400
|
+
if (net3.isIPv4(address)) {
|
|
31471
31401
|
const parts = address.split(".").map(Number);
|
|
31472
31402
|
return {
|
|
31473
31403
|
type: 1,
|
|
@@ -31475,7 +31405,7 @@ var require_socks5_utils = __commonJS({
|
|
|
31475
31405
|
buffer: Buffer2.from(parts)
|
|
31476
31406
|
};
|
|
31477
31407
|
}
|
|
31478
|
-
if (
|
|
31408
|
+
if (net3.isIPv6(address)) {
|
|
31479
31409
|
return {
|
|
31480
31410
|
type: 4,
|
|
31481
31411
|
// IPv6
|
|
@@ -31935,7 +31865,7 @@ var require_socks5_client = __commonJS({
|
|
|
31935
31865
|
var require_socks5_proxy_agent = __commonJS({
|
|
31936
31866
|
"node_modules/undici/lib/dispatcher/socks5-proxy-agent.js"(exports, module) {
|
|
31937
31867
|
"use strict";
|
|
31938
|
-
var
|
|
31868
|
+
var net3 = __require("net");
|
|
31939
31869
|
var { URL: URL5 } = __require("url");
|
|
31940
31870
|
var tls;
|
|
31941
31871
|
var DispatcherBase = require_dispatcher_base();
|
|
@@ -31997,7 +31927,7 @@ var require_socks5_proxy_agent = __commonJS({
|
|
|
31997
31927
|
socket2.removeListener("connect", onConnect);
|
|
31998
31928
|
reject(err2);
|
|
31999
31929
|
};
|
|
32000
|
-
const socket2 =
|
|
31930
|
+
const socket2 = net3.connect({
|
|
32001
31931
|
host: proxyHost,
|
|
32002
31932
|
port: proxyPort
|
|
32003
31933
|
});
|
|
@@ -32181,10 +32111,10 @@ var require_proxy_agent = __commonJS({
|
|
|
32181
32111
|
};
|
|
32182
32112
|
const {
|
|
32183
32113
|
origin,
|
|
32184
|
-
path:
|
|
32114
|
+
path: path71 = "/",
|
|
32185
32115
|
headers = {}
|
|
32186
32116
|
} = opts;
|
|
32187
|
-
opts.path = origin +
|
|
32117
|
+
opts.path = origin + path71;
|
|
32188
32118
|
if (!("host" in headers) && !("Host" in headers)) {
|
|
32189
32119
|
const { host } = new URL(origin);
|
|
32190
32120
|
headers.host = host;
|
|
@@ -34247,20 +34177,20 @@ var require_mock_utils = __commonJS({
|
|
|
34247
34177
|
}
|
|
34248
34178
|
return normalizedQp;
|
|
34249
34179
|
}
|
|
34250
|
-
function safeUrl(
|
|
34251
|
-
if (typeof
|
|
34252
|
-
return
|
|
34180
|
+
function safeUrl(path71) {
|
|
34181
|
+
if (typeof path71 !== "string") {
|
|
34182
|
+
return path71;
|
|
34253
34183
|
}
|
|
34254
|
-
const pathSegments =
|
|
34184
|
+
const pathSegments = path71.split("?", 3);
|
|
34255
34185
|
if (pathSegments.length !== 2) {
|
|
34256
|
-
return
|
|
34186
|
+
return path71;
|
|
34257
34187
|
}
|
|
34258
34188
|
const qp = new URLSearchParams(pathSegments.pop());
|
|
34259
34189
|
qp.sort();
|
|
34260
34190
|
return [...pathSegments, qp.toString()].join("?");
|
|
34261
34191
|
}
|
|
34262
|
-
function matchKey(mockDispatch2, { path:
|
|
34263
|
-
const pathMatch = matchValue(mockDispatch2.path,
|
|
34192
|
+
function matchKey(mockDispatch2, { path: path71, method, body, headers }) {
|
|
34193
|
+
const pathMatch = matchValue(mockDispatch2.path, path71);
|
|
34264
34194
|
const methodMatch = matchValue(mockDispatch2.method, method);
|
|
34265
34195
|
const bodyMatch = typeof mockDispatch2.body !== "undefined" ? matchValue(mockDispatch2.body, body) : true;
|
|
34266
34196
|
const headersMatch = matchHeaders(mockDispatch2, headers);
|
|
@@ -34285,8 +34215,8 @@ var require_mock_utils = __commonJS({
|
|
|
34285
34215
|
const basePath = key.query ? serializePathWithQuery(key.path, key.query) : key.path;
|
|
34286
34216
|
const resolvedPath = typeof basePath === "string" ? safeUrl(basePath) : basePath;
|
|
34287
34217
|
const resolvedPathWithoutTrailingSlash = removeTrailingSlash(resolvedPath);
|
|
34288
|
-
let matchedMockDispatches = mockDispatches.filter(({ consumed }) => !consumed).filter(({ path:
|
|
34289
|
-
return ignoreTrailingSlash ? matchValue(removeTrailingSlash(safeUrl(
|
|
34218
|
+
let matchedMockDispatches = mockDispatches.filter(({ consumed }) => !consumed).filter(({ path: path71, ignoreTrailingSlash }) => {
|
|
34219
|
+
return ignoreTrailingSlash ? matchValue(removeTrailingSlash(safeUrl(path71)), resolvedPathWithoutTrailingSlash) : matchValue(safeUrl(path71), resolvedPath);
|
|
34290
34220
|
});
|
|
34291
34221
|
if (matchedMockDispatches.length === 0) {
|
|
34292
34222
|
throw new MockNotMatchedError(`Mock dispatch not matched for path '${resolvedPath}'`);
|
|
@@ -34325,19 +34255,19 @@ var require_mock_utils = __commonJS({
|
|
|
34325
34255
|
mockDispatches.splice(index, 1);
|
|
34326
34256
|
}
|
|
34327
34257
|
}
|
|
34328
|
-
function removeTrailingSlash(
|
|
34329
|
-
while (
|
|
34330
|
-
|
|
34258
|
+
function removeTrailingSlash(path71) {
|
|
34259
|
+
while (path71.endsWith("/")) {
|
|
34260
|
+
path71 = path71.slice(0, -1);
|
|
34331
34261
|
}
|
|
34332
|
-
if (
|
|
34333
|
-
|
|
34262
|
+
if (path71.length === 0) {
|
|
34263
|
+
path71 = "/";
|
|
34334
34264
|
}
|
|
34335
|
-
return
|
|
34265
|
+
return path71;
|
|
34336
34266
|
}
|
|
34337
34267
|
function buildKey(opts) {
|
|
34338
|
-
const { path:
|
|
34268
|
+
const { path: path71, method, body, headers, query } = opts;
|
|
34339
34269
|
return {
|
|
34340
|
-
path:
|
|
34270
|
+
path: path71,
|
|
34341
34271
|
method,
|
|
34342
34272
|
body,
|
|
34343
34273
|
headers,
|
|
@@ -35027,10 +34957,10 @@ var require_pending_interceptors_formatter = __commonJS({
|
|
|
35027
34957
|
}
|
|
35028
34958
|
format(pendingInterceptors) {
|
|
35029
34959
|
const withPrettyHeaders = pendingInterceptors.map(
|
|
35030
|
-
({ method, path:
|
|
34960
|
+
({ method, path: path71, data: { statusCode }, persist, times, timesInvoked, origin }) => ({
|
|
35031
34961
|
Method: method,
|
|
35032
34962
|
Origin: origin,
|
|
35033
|
-
Path:
|
|
34963
|
+
Path: path71,
|
|
35034
34964
|
"Status code": statusCode,
|
|
35035
34965
|
Persistent: persist ? PERSISTENT : NOT_PERSISTENT,
|
|
35036
34966
|
Invocations: timesInvoked,
|
|
@@ -35112,9 +35042,9 @@ var require_mock_agent = __commonJS({
|
|
|
35112
35042
|
const acceptNonStandardSearchParameters = this[kMockAgentAcceptsNonStandardSearchParameters];
|
|
35113
35043
|
const dispatchOpts = { ...opts };
|
|
35114
35044
|
if (acceptNonStandardSearchParameters && dispatchOpts.path) {
|
|
35115
|
-
const [
|
|
35045
|
+
const [path71, searchParams] = dispatchOpts.path.split("?");
|
|
35116
35046
|
const normalizedSearchParams = normalizeSearchParams(searchParams, acceptNonStandardSearchParameters);
|
|
35117
|
-
dispatchOpts.path = `${
|
|
35047
|
+
dispatchOpts.path = `${path71}?${normalizedSearchParams}`;
|
|
35118
35048
|
}
|
|
35119
35049
|
return this[kAgent].dispatch(dispatchOpts, handler);
|
|
35120
35050
|
}
|
|
@@ -35242,8 +35172,8 @@ var require_snapshot_utils = __commonJS({
|
|
|
35242
35172
|
match: new Set(matchHeaders.map((header) => caseSensitive ? header : header.toLowerCase()))
|
|
35243
35173
|
};
|
|
35244
35174
|
}
|
|
35245
|
-
var
|
|
35246
|
-
var hashId =
|
|
35175
|
+
var crypto9 = runtimeFeatures.has("crypto") ? __require("crypto") : null;
|
|
35176
|
+
var hashId = crypto9?.hash ? (value) => crypto9.hash("sha256", value, "base64url") : (value) => Buffer.from(value).toString("base64url");
|
|
35247
35177
|
function isUndiciHeaders(headers) {
|
|
35248
35178
|
return Array.isArray(headers) && (headers.length & 1) === 0;
|
|
35249
35179
|
}
|
|
@@ -35515,12 +35445,12 @@ var require_snapshot_recorder = __commonJS({
|
|
|
35515
35445
|
* @return {Promise<void>} - Resolves when snapshots are loaded
|
|
35516
35446
|
*/
|
|
35517
35447
|
async loadSnapshots(filePath) {
|
|
35518
|
-
const
|
|
35519
|
-
if (!
|
|
35448
|
+
const path71 = filePath || this.#snapshotPath;
|
|
35449
|
+
if (!path71) {
|
|
35520
35450
|
throw new InvalidArgumentError("Snapshot path is required");
|
|
35521
35451
|
}
|
|
35522
35452
|
try {
|
|
35523
|
-
const data = await readFile(resolve2(
|
|
35453
|
+
const data = await readFile(resolve2(path71), "utf8");
|
|
35524
35454
|
const parsed = JSON.parse(data);
|
|
35525
35455
|
if (Array.isArray(parsed)) {
|
|
35526
35456
|
this.#snapshots.clear();
|
|
@@ -35534,7 +35464,7 @@ var require_snapshot_recorder = __commonJS({
|
|
|
35534
35464
|
if (error.code === "ENOENT") {
|
|
35535
35465
|
this.#snapshots.clear();
|
|
35536
35466
|
} else {
|
|
35537
|
-
throw new UndiciError(`Failed to load snapshots from ${
|
|
35467
|
+
throw new UndiciError(`Failed to load snapshots from ${path71}`, { cause: error });
|
|
35538
35468
|
}
|
|
35539
35469
|
}
|
|
35540
35470
|
}
|
|
@@ -35545,11 +35475,11 @@ var require_snapshot_recorder = __commonJS({
|
|
|
35545
35475
|
* @returns {Promise<void>} - Resolves when snapshots are saved
|
|
35546
35476
|
*/
|
|
35547
35477
|
async saveSnapshots(filePath) {
|
|
35548
|
-
const
|
|
35549
|
-
if (!
|
|
35478
|
+
const path71 = filePath || this.#snapshotPath;
|
|
35479
|
+
if (!path71) {
|
|
35550
35480
|
throw new InvalidArgumentError("Snapshot path is required");
|
|
35551
35481
|
}
|
|
35552
|
-
const resolvedPath = resolve2(
|
|
35482
|
+
const resolvedPath = resolve2(path71);
|
|
35553
35483
|
await mkdir(dirname2(resolvedPath), { recursive: true });
|
|
35554
35484
|
const data = Array.from(this.#snapshots.entries()).map(([hash, snapshot]) => ({
|
|
35555
35485
|
hash,
|
|
@@ -36174,15 +36104,15 @@ var require_redirect_handler = __commonJS({
|
|
|
36174
36104
|
return;
|
|
36175
36105
|
}
|
|
36176
36106
|
const { origin, pathname, search } = util.parseURL(new URL(this.location, this.opts.origin && new URL(this.opts.path, this.opts.origin)));
|
|
36177
|
-
const
|
|
36178
|
-
const redirectUrlString = `${origin}${
|
|
36107
|
+
const path71 = search ? `${pathname}${search}` : pathname;
|
|
36108
|
+
const redirectUrlString = `${origin}${path71}`;
|
|
36179
36109
|
for (const historyUrl of this.history) {
|
|
36180
36110
|
if (historyUrl.toString() === redirectUrlString) {
|
|
36181
36111
|
throw new InvalidArgumentError(`Redirect loop detected. Cannot redirect to ${origin}. This typically happens when using a Client or Pool with cross-origin redirects. Use an Agent for cross-origin redirects.`);
|
|
36182
36112
|
}
|
|
36183
36113
|
}
|
|
36184
36114
|
this.opts.headers = cleanRequestHeaders(this.opts.headers, statusCode === 303, this.opts.origin !== origin);
|
|
36185
|
-
this.opts.path =
|
|
36115
|
+
this.opts.path = path71;
|
|
36186
36116
|
this.opts.origin = origin;
|
|
36187
36117
|
this.opts.query = null;
|
|
36188
36118
|
}
|
|
@@ -41301,10 +41231,10 @@ var require_subresource_integrity = __commonJS({
|
|
|
41301
41231
|
var assert = __require("assert");
|
|
41302
41232
|
var { runtimeFeatures } = require_runtime_features();
|
|
41303
41233
|
var validSRIHashAlgorithmTokenSet = /* @__PURE__ */ new Map([["sha256", 0], ["sha384", 1], ["sha512", 2]]);
|
|
41304
|
-
var
|
|
41234
|
+
var crypto9;
|
|
41305
41235
|
if (runtimeFeatures.has("crypto")) {
|
|
41306
|
-
|
|
41307
|
-
const cryptoHashes =
|
|
41236
|
+
crypto9 = __require("crypto");
|
|
41237
|
+
const cryptoHashes = crypto9.getHashes();
|
|
41308
41238
|
if (cryptoHashes.length === 0) {
|
|
41309
41239
|
validSRIHashAlgorithmTokenSet.clear();
|
|
41310
41240
|
}
|
|
@@ -41394,7 +41324,7 @@ var require_subresource_integrity = __commonJS({
|
|
|
41394
41324
|
return result;
|
|
41395
41325
|
}
|
|
41396
41326
|
var applyAlgorithmToBytes = (algorithm, bytes) => {
|
|
41397
|
-
return
|
|
41327
|
+
return crypto9.hash(algorithm, bytes, "base64");
|
|
41398
41328
|
};
|
|
41399
41329
|
function caseSensitiveMatch(actualValue, expectedValue) {
|
|
41400
41330
|
let actualValueLength = actualValue.length;
|
|
@@ -42389,11 +42319,11 @@ var require_fetch = __commonJS({
|
|
|
42389
42319
|
function dispatch({ body }) {
|
|
42390
42320
|
const url = requestCurrentURL(request2);
|
|
42391
42321
|
const agent = fetchParams.controller.dispatcher;
|
|
42392
|
-
const
|
|
42322
|
+
const path71 = url.pathname + url.search;
|
|
42393
42323
|
const hasTrailingQuestionMark = url.search.length === 0 && url.href[url.href.length - url.hash.length - 1] === "?";
|
|
42394
42324
|
return new Promise((resolve2, reject) => agent.dispatch(
|
|
42395
42325
|
{
|
|
42396
|
-
path: hasTrailingQuestionMark ? `${
|
|
42326
|
+
path: hasTrailingQuestionMark ? `${path71}?` : path71,
|
|
42397
42327
|
origin: url.origin,
|
|
42398
42328
|
method: request2.method,
|
|
42399
42329
|
body: agent.isMockActive ? request2.body && (request2.body.source || request2.body.stream) : body,
|
|
@@ -43324,9 +43254,9 @@ var require_util4 = __commonJS({
|
|
|
43324
43254
|
}
|
|
43325
43255
|
}
|
|
43326
43256
|
}
|
|
43327
|
-
function validateCookiePath(
|
|
43328
|
-
for (let i = 0; i <
|
|
43329
|
-
const code =
|
|
43257
|
+
function validateCookiePath(path71) {
|
|
43258
|
+
for (let i = 0; i < path71.length; ++i) {
|
|
43259
|
+
const code = path71.charCodeAt(i);
|
|
43330
43260
|
if (code < 32 || // exclude CTLs (0-31)
|
|
43331
43261
|
code === 127 || // DEL
|
|
43332
43262
|
code === 59) {
|
|
@@ -44328,7 +44258,7 @@ var require_connection = __commonJS({
|
|
|
44328
44258
|
var { WebsocketFrameSend } = require_frame();
|
|
44329
44259
|
var assert = __require("assert");
|
|
44330
44260
|
var { runtimeFeatures } = require_runtime_features();
|
|
44331
|
-
var
|
|
44261
|
+
var crypto9 = runtimeFeatures.has("crypto") ? __require("crypto") : null;
|
|
44332
44262
|
var warningEmitted = false;
|
|
44333
44263
|
function establishWebSocketConnection(url, protocols, client, handler, options) {
|
|
44334
44264
|
const requestURL = url;
|
|
@@ -44348,7 +44278,7 @@ var require_connection = __commonJS({
|
|
|
44348
44278
|
const headersList = getHeadersList(new Headers(options.headers));
|
|
44349
44279
|
request2.headersList = headersList;
|
|
44350
44280
|
}
|
|
44351
|
-
const keyValue =
|
|
44281
|
+
const keyValue = crypto9.randomBytes(16).toString("base64");
|
|
44352
44282
|
request2.headersList.append("sec-websocket-key", keyValue, true);
|
|
44353
44283
|
request2.headersList.append("sec-websocket-version", "13", true);
|
|
44354
44284
|
for (const protocol of protocols) {
|
|
@@ -44388,7 +44318,7 @@ var require_connection = __commonJS({
|
|
|
44388
44318
|
return;
|
|
44389
44319
|
}
|
|
44390
44320
|
const secWSAccept = response.headersList.get("Sec-WebSocket-Accept");
|
|
44391
|
-
const digest =
|
|
44321
|
+
const digest = crypto9.hash("sha1", keyValue + uid, "base64");
|
|
44392
44322
|
if (secWSAccept !== digest) {
|
|
44393
44323
|
failWebsocketConnection(handler, 1002, "Incorrect hash received in Sec-WebSocket-Accept header.");
|
|
44394
44324
|
return;
|
|
@@ -46496,11 +46426,11 @@ var require_undici = __commonJS({
|
|
|
46496
46426
|
if (typeof opts.path !== "string") {
|
|
46497
46427
|
throw new InvalidArgumentError("invalid opts.path");
|
|
46498
46428
|
}
|
|
46499
|
-
let
|
|
46429
|
+
let path71 = opts.path;
|
|
46500
46430
|
if (!opts.path.startsWith("/")) {
|
|
46501
|
-
|
|
46431
|
+
path71 = `/${path71}`;
|
|
46502
46432
|
}
|
|
46503
|
-
url = new URL(util.parseOrigin(url).origin +
|
|
46433
|
+
url = new URL(util.parseOrigin(url).origin + path71);
|
|
46504
46434
|
} else {
|
|
46505
46435
|
if (!opts) {
|
|
46506
46436
|
opts = typeof url === "object" ? url : {};
|
|
@@ -46620,11 +46550,11 @@ __export(tail_exports, {
|
|
|
46620
46550
|
});
|
|
46621
46551
|
import http5 from "http";
|
|
46622
46552
|
import chalk39 from "chalk";
|
|
46623
|
-
import
|
|
46624
|
-
import
|
|
46625
|
-
import
|
|
46553
|
+
import fs73 from "fs";
|
|
46554
|
+
import os61 from "os";
|
|
46555
|
+
import path68 from "path";
|
|
46626
46556
|
import readline5 from "readline";
|
|
46627
|
-
import { spawn as
|
|
46557
|
+
import { spawn as spawn7 } from "child_process";
|
|
46628
46558
|
function eventsUrl(port, canApprove) {
|
|
46629
46559
|
return `http://127.0.0.1:${port}/events${canApprove ? "?capabilities=input" : ""}`;
|
|
46630
46560
|
}
|
|
@@ -46649,20 +46579,20 @@ function getModelContextLimit(model) {
|
|
|
46649
46579
|
return 2e5;
|
|
46650
46580
|
}
|
|
46651
46581
|
function readSessionUsage() {
|
|
46652
|
-
const projectsDir =
|
|
46653
|
-
if (!
|
|
46582
|
+
const projectsDir = path68.join(os61.homedir(), ".claude", "projects");
|
|
46583
|
+
if (!fs73.existsSync(projectsDir)) return null;
|
|
46654
46584
|
let latestFile = null;
|
|
46655
46585
|
let latestMtime = 0;
|
|
46656
46586
|
try {
|
|
46657
|
-
for (const dir of
|
|
46658
|
-
const dirPath =
|
|
46587
|
+
for (const dir of fs73.readdirSync(projectsDir)) {
|
|
46588
|
+
const dirPath = path68.join(projectsDir, dir);
|
|
46659
46589
|
try {
|
|
46660
|
-
if (!
|
|
46661
|
-
for (const file of
|
|
46590
|
+
if (!fs73.statSync(dirPath).isDirectory()) continue;
|
|
46591
|
+
for (const file of fs73.readdirSync(dirPath)) {
|
|
46662
46592
|
if (!file.endsWith(".jsonl") || file.startsWith("agent-")) continue;
|
|
46663
|
-
const filePath =
|
|
46593
|
+
const filePath = path68.join(dirPath, file);
|
|
46664
46594
|
try {
|
|
46665
|
-
const mtime =
|
|
46595
|
+
const mtime = fs73.statSync(filePath).mtimeMs;
|
|
46666
46596
|
if (mtime > latestMtime) {
|
|
46667
46597
|
latestMtime = mtime;
|
|
46668
46598
|
latestFile = filePath;
|
|
@@ -46677,7 +46607,7 @@ function readSessionUsage() {
|
|
|
46677
46607
|
}
|
|
46678
46608
|
if (!latestFile) return null;
|
|
46679
46609
|
try {
|
|
46680
|
-
const lines =
|
|
46610
|
+
const lines = fs73.readFileSync(latestFile, "utf-8").split("\n");
|
|
46681
46611
|
let lastModel = "";
|
|
46682
46612
|
let lastInput = 0;
|
|
46683
46613
|
let lastOutput = 0;
|
|
@@ -46738,7 +46668,7 @@ function formatBase(activity) {
|
|
|
46738
46668
|
const time = new Date(activity.ts).toLocaleTimeString([], { hour12: false });
|
|
46739
46669
|
const icon = getIcon(activity.tool);
|
|
46740
46670
|
const toolName = activity.tool.slice(0, 16).padEnd(16);
|
|
46741
|
-
const argsStr = JSON.stringify(activity.args ?? {}).replace(/\s+/g, " ").replaceAll(
|
|
46671
|
+
const argsStr = JSON.stringify(activity.args ?? {}).replace(/\s+/g, " ").replaceAll(os61.homedir(), "~");
|
|
46742
46672
|
const argsPreview = argsStr.length > 70 ? argsStr.slice(0, 70) + "\u2026" : argsStr;
|
|
46743
46673
|
return `${chalk39.gray(time)} ${icon} ${agentLabel(activity.agent, activity.mcpServer, activity.sessionId)}${chalk39.white.bold(toolName)} ${chalk39.dim(argsPreview)}`;
|
|
46744
46674
|
}
|
|
@@ -46777,9 +46707,9 @@ function renderPending(activity) {
|
|
|
46777
46707
|
}
|
|
46778
46708
|
async function ensureDaemon() {
|
|
46779
46709
|
let pidPort = null;
|
|
46780
|
-
if (
|
|
46710
|
+
if (fs73.existsSync(PID_FILE)) {
|
|
46781
46711
|
try {
|
|
46782
|
-
const { port } = JSON.parse(
|
|
46712
|
+
const { port } = JSON.parse(fs73.readFileSync(PID_FILE, "utf-8"));
|
|
46783
46713
|
pidPort = port;
|
|
46784
46714
|
} catch {
|
|
46785
46715
|
console.error(chalk39.dim("\u26A0\uFE0F Could not read PID file; falling back to default port."));
|
|
@@ -46796,7 +46726,7 @@ async function ensureDaemon() {
|
|
|
46796
46726
|
console.log(chalk39.dim("\u{1F6E1}\uFE0F Starting Node9 daemon..."));
|
|
46797
46727
|
const startupFd = openStartupLogFd();
|
|
46798
46728
|
recordStartupState("starting");
|
|
46799
|
-
const child =
|
|
46729
|
+
const child = spawn7(process.execPath, [process.argv[1], "daemon"], {
|
|
46800
46730
|
detached: true,
|
|
46801
46731
|
stdio: ["ignore", "ignore", startupFd ?? "ignore"],
|
|
46802
46732
|
env: { ...process.env, NODE9_AUTO_STARTED: "1" }
|
|
@@ -46805,7 +46735,7 @@ async function ensureDaemon() {
|
|
|
46805
46735
|
child.unref();
|
|
46806
46736
|
if (startupFd !== void 0) {
|
|
46807
46737
|
try {
|
|
46808
|
-
|
|
46738
|
+
fs73.closeSync(startupFd);
|
|
46809
46739
|
} catch {
|
|
46810
46740
|
}
|
|
46811
46741
|
}
|
|
@@ -46944,9 +46874,9 @@ function buildRecoveryCardLines(req) {
|
|
|
46944
46874
|
];
|
|
46945
46875
|
}
|
|
46946
46876
|
function readApproversFromDisk() {
|
|
46947
|
-
const configPath =
|
|
46877
|
+
const configPath = path68.join(os61.homedir(), ".node9", "config.json");
|
|
46948
46878
|
try {
|
|
46949
|
-
const raw = JSON.parse(
|
|
46879
|
+
const raw = JSON.parse(fs73.readFileSync(configPath, "utf-8"));
|
|
46950
46880
|
const settings = raw.settings ?? {};
|
|
46951
46881
|
return settings.approvers ?? {};
|
|
46952
46882
|
} catch {
|
|
@@ -46962,15 +46892,15 @@ function approverStatusLine() {
|
|
|
46962
46892
|
return `${fmt("native", "native")} ${fmt("cloud", "cloud")} ${fmt("terminal", "terminal")}`;
|
|
46963
46893
|
}
|
|
46964
46894
|
function toggleApprover(channel) {
|
|
46965
|
-
const configPath =
|
|
46895
|
+
const configPath = path68.join(os61.homedir(), ".node9", "config.json");
|
|
46966
46896
|
try {
|
|
46967
|
-
const raw = JSON.parse(
|
|
46897
|
+
const raw = JSON.parse(fs73.readFileSync(configPath, "utf-8"));
|
|
46968
46898
|
const settings = raw.settings ?? {};
|
|
46969
46899
|
const approvers = settings.approvers ?? {};
|
|
46970
46900
|
approvers[channel] = approvers[channel] === false;
|
|
46971
46901
|
settings.approvers = approvers;
|
|
46972
46902
|
raw.settings = settings;
|
|
46973
|
-
|
|
46903
|
+
fs73.writeFileSync(configPath, JSON.stringify(raw, null, 2) + "\n");
|
|
46974
46904
|
} catch (err2) {
|
|
46975
46905
|
process.stderr.write(`[node9] toggleApprover failed: ${String(err2)}
|
|
46976
46906
|
`);
|
|
@@ -47142,8 +47072,8 @@ async function startTail(options = {}) {
|
|
|
47142
47072
|
}
|
|
47143
47073
|
postDecisionHttp(req2.id, httpDecision, authToken, port, httpOpts).catch((err2) => {
|
|
47144
47074
|
try {
|
|
47145
|
-
|
|
47146
|
-
|
|
47075
|
+
fs73.appendFileSync(
|
|
47076
|
+
path68.join(os61.homedir(), ".node9", "hook-debug.log"),
|
|
47147
47077
|
`[tail] POST /decision failed: ${String(err2)}
|
|
47148
47078
|
`
|
|
47149
47079
|
);
|
|
@@ -47207,9 +47137,9 @@ async function startTail(options = {}) {
|
|
|
47207
47137
|
};
|
|
47208
47138
|
process.stdin.on("keypress", onKeypress);
|
|
47209
47139
|
}
|
|
47210
|
-
const auditLog =
|
|
47140
|
+
const auditLog = path68.join(os61.homedir(), ".node9", "audit.log");
|
|
47211
47141
|
try {
|
|
47212
|
-
const unackedDlp =
|
|
47142
|
+
const unackedDlp = fs73.readFileSync(auditLog, "utf-8").split("\n").filter((l) => l.includes('"response-dlp"')).length;
|
|
47213
47143
|
if (unackedDlp > 0) {
|
|
47214
47144
|
console.log("");
|
|
47215
47145
|
console.log(
|
|
@@ -47249,7 +47179,7 @@ async function startTail(options = {}) {
|
|
|
47249
47179
|
if (stallWarned) return;
|
|
47250
47180
|
if (Date.now() - lastActivityFromDaemon < STALL_THRESHOLD_MS) return;
|
|
47251
47181
|
try {
|
|
47252
|
-
const auditMtime =
|
|
47182
|
+
const auditMtime = fs73.statSync(auditLog).mtimeMs;
|
|
47253
47183
|
if (Date.now() - auditMtime >= STALL_THRESHOLD_MS) return;
|
|
47254
47184
|
console.log("");
|
|
47255
47185
|
console.log(
|
|
@@ -47393,19 +47323,6 @@ async function startTail(options = {}) {
|
|
|
47393
47323
|
activityPending.set(data.id, data);
|
|
47394
47324
|
renderPending(data);
|
|
47395
47325
|
}
|
|
47396
|
-
if (event === "snapshot") {
|
|
47397
|
-
const time = new Date(data.ts).toLocaleTimeString([], { hour12: false });
|
|
47398
|
-
const hash = data.hash ?? "";
|
|
47399
|
-
const rawSummary = data.argsSummary ?? data.tool;
|
|
47400
|
-
const summary = shortenPathSummary(rawSummary);
|
|
47401
|
-
const fileCount = data.fileCount ?? 0;
|
|
47402
|
-
const files = fileCount > 0 ? chalk39.dim(` \xB7 ${fileCount} file${fileCount === 1 ? "" : "s"}`) : "";
|
|
47403
|
-
process.stdout.write(
|
|
47404
|
-
`${chalk39.dim(time)} ${chalk39.cyan("\u{1F4F8} snapshot")} ${chalk39.dim(hash)} ${summary}${files}
|
|
47405
|
-
`
|
|
47406
|
-
);
|
|
47407
|
-
return;
|
|
47408
|
-
}
|
|
47409
47326
|
if (event === "activity-result") {
|
|
47410
47327
|
const original = activityPending.get(data.id);
|
|
47411
47328
|
if (original) {
|
|
@@ -47441,7 +47358,7 @@ var init_tail = __esm({
|
|
|
47441
47358
|
init_startup_log();
|
|
47442
47359
|
init_daemon2();
|
|
47443
47360
|
init_daemon();
|
|
47444
|
-
PID_FILE =
|
|
47361
|
+
PID_FILE = path68.join(os61.homedir(), ".node9", "daemon.pid");
|
|
47445
47362
|
ICONS = {
|
|
47446
47363
|
bash: "\u{1F4BB}",
|
|
47447
47364
|
shell: "\u{1F4BB}",
|
|
@@ -47489,9 +47406,9 @@ __export(hud_exports, {
|
|
|
47489
47406
|
main: () => main,
|
|
47490
47407
|
renderEnvironmentLine: () => renderEnvironmentLine
|
|
47491
47408
|
});
|
|
47492
|
-
import
|
|
47493
|
-
import
|
|
47494
|
-
import
|
|
47409
|
+
import fs74 from "fs";
|
|
47410
|
+
import path69 from "path";
|
|
47411
|
+
import os62 from "os";
|
|
47495
47412
|
import http6 from "http";
|
|
47496
47413
|
async function readStdin() {
|
|
47497
47414
|
const chunks = [];
|
|
@@ -47567,9 +47484,9 @@ function formatTimeLeft(resetsAt) {
|
|
|
47567
47484
|
return ` (${m}m left)`;
|
|
47568
47485
|
}
|
|
47569
47486
|
function safeReadJson(filePath) {
|
|
47570
|
-
if (!
|
|
47487
|
+
if (!fs74.existsSync(filePath)) return null;
|
|
47571
47488
|
try {
|
|
47572
|
-
return JSON.parse(
|
|
47489
|
+
return JSON.parse(fs74.readFileSync(filePath, "utf-8"));
|
|
47573
47490
|
} catch {
|
|
47574
47491
|
return null;
|
|
47575
47492
|
}
|
|
@@ -47590,12 +47507,12 @@ function countHooksInFile(filePath) {
|
|
|
47590
47507
|
return Object.keys(cfg.hooks).length;
|
|
47591
47508
|
}
|
|
47592
47509
|
function countRulesInDir(rulesDir) {
|
|
47593
|
-
if (!
|
|
47510
|
+
if (!fs74.existsSync(rulesDir)) return 0;
|
|
47594
47511
|
let count = 0;
|
|
47595
47512
|
try {
|
|
47596
|
-
for (const entry of
|
|
47513
|
+
for (const entry of fs74.readdirSync(rulesDir, { withFileTypes: true })) {
|
|
47597
47514
|
if (entry.isDirectory()) {
|
|
47598
|
-
count += countRulesInDir(
|
|
47515
|
+
count += countRulesInDir(path69.join(rulesDir, entry.name));
|
|
47599
47516
|
} else if (entry.isFile() && entry.name.endsWith(".md")) {
|
|
47600
47517
|
count++;
|
|
47601
47518
|
}
|
|
@@ -47606,46 +47523,46 @@ function countRulesInDir(rulesDir) {
|
|
|
47606
47523
|
}
|
|
47607
47524
|
function isSamePath(a, b) {
|
|
47608
47525
|
try {
|
|
47609
|
-
return
|
|
47526
|
+
return path69.resolve(a) === path69.resolve(b);
|
|
47610
47527
|
} catch {
|
|
47611
47528
|
return false;
|
|
47612
47529
|
}
|
|
47613
47530
|
}
|
|
47614
47531
|
function countConfigs(cwd) {
|
|
47615
|
-
const homeDir2 =
|
|
47616
|
-
const claudeDir =
|
|
47532
|
+
const homeDir2 = os62.homedir();
|
|
47533
|
+
const claudeDir = path69.join(homeDir2, ".claude");
|
|
47617
47534
|
let claudeMdCount = 0;
|
|
47618
47535
|
let rulesCount = 0;
|
|
47619
47536
|
let hooksCount = 0;
|
|
47620
47537
|
const userMcpServers = /* @__PURE__ */ new Set();
|
|
47621
47538
|
const projectMcpServers = /* @__PURE__ */ new Set();
|
|
47622
|
-
if (
|
|
47623
|
-
rulesCount += countRulesInDir(
|
|
47624
|
-
const userSettings =
|
|
47539
|
+
if (fs74.existsSync(path69.join(claudeDir, "CLAUDE.md"))) claudeMdCount++;
|
|
47540
|
+
rulesCount += countRulesInDir(path69.join(claudeDir, "rules"));
|
|
47541
|
+
const userSettings = path69.join(claudeDir, "settings.json");
|
|
47625
47542
|
for (const name of getMcpServerNames(userSettings)) userMcpServers.add(name);
|
|
47626
47543
|
hooksCount += countHooksInFile(userSettings);
|
|
47627
|
-
const userClaudeJson =
|
|
47544
|
+
const userClaudeJson = path69.join(homeDir2, ".claude.json");
|
|
47628
47545
|
for (const name of getMcpServerNames(userClaudeJson)) userMcpServers.add(name);
|
|
47629
47546
|
for (const name of getDisabledMcpServers(userClaudeJson, "disabledMcpServers")) {
|
|
47630
47547
|
userMcpServers.delete(name);
|
|
47631
47548
|
}
|
|
47632
47549
|
if (cwd) {
|
|
47633
|
-
if (
|
|
47634
|
-
if (
|
|
47635
|
-
const projectClaudeDir =
|
|
47550
|
+
if (fs74.existsSync(path69.join(cwd, "CLAUDE.md"))) claudeMdCount++;
|
|
47551
|
+
if (fs74.existsSync(path69.join(cwd, "CLAUDE.local.md"))) claudeMdCount++;
|
|
47552
|
+
const projectClaudeDir = path69.join(cwd, ".claude");
|
|
47636
47553
|
const overlapsUserScope = isSamePath(projectClaudeDir, claudeDir);
|
|
47637
47554
|
if (!overlapsUserScope) {
|
|
47638
|
-
if (
|
|
47639
|
-
rulesCount += countRulesInDir(
|
|
47640
|
-
const projSettings =
|
|
47555
|
+
if (fs74.existsSync(path69.join(projectClaudeDir, "CLAUDE.md"))) claudeMdCount++;
|
|
47556
|
+
rulesCount += countRulesInDir(path69.join(projectClaudeDir, "rules"));
|
|
47557
|
+
const projSettings = path69.join(projectClaudeDir, "settings.json");
|
|
47641
47558
|
for (const name of getMcpServerNames(projSettings)) projectMcpServers.add(name);
|
|
47642
47559
|
hooksCount += countHooksInFile(projSettings);
|
|
47643
47560
|
}
|
|
47644
|
-
if (
|
|
47645
|
-
const localSettings =
|
|
47561
|
+
if (fs74.existsSync(path69.join(projectClaudeDir, "CLAUDE.local.md"))) claudeMdCount++;
|
|
47562
|
+
const localSettings = path69.join(projectClaudeDir, "settings.local.json");
|
|
47646
47563
|
for (const name of getMcpServerNames(localSettings)) projectMcpServers.add(name);
|
|
47647
47564
|
hooksCount += countHooksInFile(localSettings);
|
|
47648
|
-
const mcpJsonServers = getMcpServerNames(
|
|
47565
|
+
const mcpJsonServers = getMcpServerNames(path69.join(cwd, ".mcp.json"));
|
|
47649
47566
|
const disabledMcpJson = getDisabledMcpServers(localSettings, "disabledMcpjsonServers");
|
|
47650
47567
|
for (const name of disabledMcpJson) mcpJsonServers.delete(name);
|
|
47651
47568
|
for (const name of mcpJsonServers) projectMcpServers.add(name);
|
|
@@ -47678,12 +47595,12 @@ function readActiveShieldsHud() {
|
|
|
47678
47595
|
return shieldsCache.value;
|
|
47679
47596
|
}
|
|
47680
47597
|
try {
|
|
47681
|
-
const shieldsPath =
|
|
47682
|
-
if (!
|
|
47598
|
+
const shieldsPath = path69.join(os62.homedir(), ".node9", "shields.json");
|
|
47599
|
+
if (!fs74.existsSync(shieldsPath)) {
|
|
47683
47600
|
shieldsCache = { value: [], ts: now };
|
|
47684
47601
|
return [];
|
|
47685
47602
|
}
|
|
47686
|
-
const parsed = JSON.parse(
|
|
47603
|
+
const parsed = JSON.parse(fs74.readFileSync(shieldsPath, "utf-8"));
|
|
47687
47604
|
if (!Array.isArray(parsed.active)) {
|
|
47688
47605
|
shieldsCache = { value: [], ts: now };
|
|
47689
47606
|
return [];
|
|
@@ -47785,17 +47702,17 @@ function renderContextLine(stdin) {
|
|
|
47785
47702
|
async function main() {
|
|
47786
47703
|
try {
|
|
47787
47704
|
const [stdin, daemonStatus2] = await Promise.all([readStdin(), queryDaemon()]);
|
|
47788
|
-
if (
|
|
47705
|
+
if (fs74.existsSync(path69.join(os62.homedir(), ".node9", "hud-debug"))) {
|
|
47789
47706
|
try {
|
|
47790
|
-
const logPath =
|
|
47707
|
+
const logPath = path69.join(os62.homedir(), ".node9", "hud-debug.log");
|
|
47791
47708
|
const MAX_LOG_SIZE = 10 * 1024 * 1024;
|
|
47792
47709
|
let size = 0;
|
|
47793
47710
|
try {
|
|
47794
|
-
size =
|
|
47711
|
+
size = fs74.statSync(logPath).size;
|
|
47795
47712
|
} catch {
|
|
47796
47713
|
}
|
|
47797
47714
|
if (size < MAX_LOG_SIZE) {
|
|
47798
|
-
|
|
47715
|
+
fs74.appendFileSync(
|
|
47799
47716
|
logPath,
|
|
47800
47717
|
JSON.stringify({ ts: (/* @__PURE__ */ new Date()).toISOString(), stdin }) + "\n"
|
|
47801
47718
|
);
|
|
@@ -47816,11 +47733,11 @@ async function main() {
|
|
|
47816
47733
|
try {
|
|
47817
47734
|
const cwd = stdin.cwd ?? process.cwd();
|
|
47818
47735
|
for (const configPath of [
|
|
47819
|
-
|
|
47820
|
-
|
|
47736
|
+
path69.join(cwd, "node9.config.json"),
|
|
47737
|
+
path69.join(os62.homedir(), ".node9", "config.json")
|
|
47821
47738
|
]) {
|
|
47822
|
-
if (!
|
|
47823
|
-
const cfg = JSON.parse(
|
|
47739
|
+
if (!fs74.existsSync(configPath)) continue;
|
|
47740
|
+
const cfg = JSON.parse(fs74.readFileSync(configPath, "utf-8"));
|
|
47824
47741
|
const hud = cfg.settings?.hud;
|
|
47825
47742
|
if (hud && "showEnvironmentCounts" in hud) return hud.showEnvironmentCounts !== false;
|
|
47826
47743
|
}
|
|
@@ -47962,10 +47879,10 @@ function writeCredentialsAndConfig(apiKey, opts = {}) {
|
|
|
47962
47879
|
// src/cli.ts
|
|
47963
47880
|
init_daemon2();
|
|
47964
47881
|
import chalk40 from "chalk";
|
|
47965
|
-
import
|
|
47966
|
-
import
|
|
47967
|
-
import
|
|
47968
|
-
import { spawn as
|
|
47882
|
+
import fs75 from "fs";
|
|
47883
|
+
import path70 from "path";
|
|
47884
|
+
import os63 from "os";
|
|
47885
|
+
import { spawn as spawn8 } from "child_process";
|
|
47969
47886
|
import { confirm as confirm3 } from "@inquirer/prompts";
|
|
47970
47887
|
|
|
47971
47888
|
// src/utils/duration.ts
|
|
@@ -48249,286 +48166,24 @@ init_state();
|
|
|
48249
48166
|
init_daemon();
|
|
48250
48167
|
init_startup_log();
|
|
48251
48168
|
init_config();
|
|
48252
|
-
init_policy();
|
|
48253
48169
|
import chalk9 from "chalk";
|
|
48254
|
-
import
|
|
48255
|
-
import { spawn as
|
|
48256
|
-
import
|
|
48257
|
-
import
|
|
48170
|
+
import fs49 from "fs";
|
|
48171
|
+
import { spawn as spawn4 } from "child_process";
|
|
48172
|
+
import path47 from "path";
|
|
48173
|
+
import os44 from "os";
|
|
48258
48174
|
|
|
48259
|
-
// src/
|
|
48260
|
-
import { spawnSync as spawnSync3, spawn as spawn4 } from "child_process";
|
|
48261
|
-
import crypto7 from "crypto";
|
|
48175
|
+
// src/skill-pin.ts
|
|
48262
48176
|
import fs47 from "fs";
|
|
48263
|
-
import net3 from "net";
|
|
48264
48177
|
import path45 from "path";
|
|
48265
48178
|
import os42 from "os";
|
|
48266
|
-
|
|
48267
|
-
function notifySnapshotTaken(hash, tool, argsSummary, fileCount) {
|
|
48268
|
-
try {
|
|
48269
|
-
const payload = JSON.stringify({
|
|
48270
|
-
status: "snapshot",
|
|
48271
|
-
hash,
|
|
48272
|
-
tool,
|
|
48273
|
-
argsSummary,
|
|
48274
|
-
fileCount,
|
|
48275
|
-
ts: Date.now()
|
|
48276
|
-
});
|
|
48277
|
-
const sock = net3.createConnection(ACTIVITY_SOCKET_PATH3);
|
|
48278
|
-
sock.on("connect", () => {
|
|
48279
|
-
sock.end(payload);
|
|
48280
|
-
});
|
|
48281
|
-
sock.on("error", () => {
|
|
48282
|
-
});
|
|
48283
|
-
} catch {
|
|
48284
|
-
}
|
|
48285
|
-
}
|
|
48286
|
-
var SNAPSHOT_STACK_PATH = path45.join(os42.homedir(), ".node9", "snapshots.json");
|
|
48287
|
-
var UNDO_LATEST_PATH = path45.join(os42.homedir(), ".node9", "undo_latest.txt");
|
|
48288
|
-
var MAX_SNAPSHOTS = 10;
|
|
48289
|
-
var GIT_TIMEOUT = 15e3;
|
|
48290
|
-
function readStack() {
|
|
48291
|
-
try {
|
|
48292
|
-
if (fs47.existsSync(SNAPSHOT_STACK_PATH))
|
|
48293
|
-
return JSON.parse(fs47.readFileSync(SNAPSHOT_STACK_PATH, "utf-8"));
|
|
48294
|
-
} catch {
|
|
48295
|
-
}
|
|
48296
|
-
return [];
|
|
48297
|
-
}
|
|
48298
|
-
function writeStack(stack) {
|
|
48299
|
-
const dir = path45.dirname(SNAPSHOT_STACK_PATH);
|
|
48300
|
-
if (!fs47.existsSync(dir)) fs47.mkdirSync(dir, { recursive: true });
|
|
48301
|
-
fs47.writeFileSync(SNAPSHOT_STACK_PATH, JSON.stringify(stack, null, 2));
|
|
48302
|
-
}
|
|
48303
|
-
function extractFilePath(args) {
|
|
48304
|
-
if (!args || typeof args !== "object") return null;
|
|
48305
|
-
const a = args;
|
|
48306
|
-
const fp = a.file_path ?? a.path ?? a.filename;
|
|
48307
|
-
return typeof fp === "string" ? fp : null;
|
|
48308
|
-
}
|
|
48309
|
-
function buildArgsSummary(tool, args) {
|
|
48310
|
-
const filePath = extractFilePath(args);
|
|
48311
|
-
if (filePath) return filePath;
|
|
48312
|
-
if (!args || typeof args !== "object") return "";
|
|
48313
|
-
const a = args;
|
|
48314
|
-
const cmd = a.command ?? a.cmd;
|
|
48315
|
-
if (typeof cmd === "string") return cmd.slice(0, 80);
|
|
48316
|
-
const sql = a.sql ?? a.query;
|
|
48317
|
-
if (typeof sql === "string") return sql.slice(0, 80);
|
|
48318
|
-
return "";
|
|
48319
|
-
}
|
|
48320
|
-
function findProjectRoot(filePath) {
|
|
48321
|
-
let dir = path45.dirname(filePath);
|
|
48322
|
-
while (true) {
|
|
48323
|
-
if (fs47.existsSync(path45.join(dir, ".git")) || fs47.existsSync(path45.join(dir, "package.json"))) {
|
|
48324
|
-
return dir;
|
|
48325
|
-
}
|
|
48326
|
-
const parent = path45.dirname(dir);
|
|
48327
|
-
if (parent === dir) return process.cwd();
|
|
48328
|
-
dir = parent;
|
|
48329
|
-
}
|
|
48330
|
-
}
|
|
48331
|
-
function normalizeCwdForHash(cwd) {
|
|
48332
|
-
let normalized;
|
|
48333
|
-
try {
|
|
48334
|
-
normalized = fs47.realpathSync(cwd);
|
|
48335
|
-
} catch {
|
|
48336
|
-
normalized = cwd;
|
|
48337
|
-
}
|
|
48338
|
-
normalized = normalized.replace(/\\/g, "/");
|
|
48339
|
-
if (process.platform === "win32") normalized = normalized.toLowerCase();
|
|
48340
|
-
return normalized;
|
|
48341
|
-
}
|
|
48342
|
-
function getShadowRepoDir(cwd) {
|
|
48343
|
-
const hash = crypto7.createHash("sha256").update(normalizeCwdForHash(cwd)).digest("hex").slice(0, 16);
|
|
48344
|
-
return path45.join(os42.homedir(), ".node9", "snapshots", hash);
|
|
48345
|
-
}
|
|
48346
|
-
function cleanOrphanedIndexFiles(shadowDir) {
|
|
48347
|
-
try {
|
|
48348
|
-
const cutoff = Date.now() - 6e4;
|
|
48349
|
-
for (const f of fs47.readdirSync(shadowDir)) {
|
|
48350
|
-
if (f.startsWith("index_")) {
|
|
48351
|
-
const fp = path45.join(shadowDir, f);
|
|
48352
|
-
try {
|
|
48353
|
-
if (fs47.statSync(fp).mtimeMs < cutoff) fs47.unlinkSync(fp);
|
|
48354
|
-
} catch {
|
|
48355
|
-
}
|
|
48356
|
-
}
|
|
48357
|
-
}
|
|
48358
|
-
} catch {
|
|
48359
|
-
}
|
|
48360
|
-
}
|
|
48361
|
-
function writeShadowExcludes(shadowDir, ignorePaths) {
|
|
48362
|
-
const hardcoded = [".git", ".node9"];
|
|
48363
|
-
const lines = [...hardcoded, ...ignorePaths].join("\n");
|
|
48364
|
-
try {
|
|
48365
|
-
fs47.writeFileSync(path45.join(shadowDir, "info", "exclude"), lines + "\n", "utf8");
|
|
48366
|
-
} catch {
|
|
48367
|
-
}
|
|
48368
|
-
}
|
|
48369
|
-
function ensureShadowRepo(shadowDir, cwd) {
|
|
48370
|
-
cleanOrphanedIndexFiles(shadowDir);
|
|
48371
|
-
const normalizedCwd = normalizeCwdForHash(cwd);
|
|
48372
|
-
const shadowEnvBase = { ...process.env, GIT_DIR: shadowDir, GIT_WORK_TREE: cwd };
|
|
48373
|
-
const check = spawnSync3("git", ["rev-parse", "--git-dir"], {
|
|
48374
|
-
env: shadowEnvBase,
|
|
48375
|
-
timeout: 3e3
|
|
48376
|
-
});
|
|
48377
|
-
if (check.status === 0) {
|
|
48378
|
-
const ptPath = path45.join(shadowDir, "project-path.txt");
|
|
48379
|
-
try {
|
|
48380
|
-
const stored = fs47.readFileSync(ptPath, "utf8").trim();
|
|
48381
|
-
if (stored === normalizedCwd) return true;
|
|
48382
|
-
if (process.env.NODE9_DEBUG === "1")
|
|
48383
|
-
console.error(
|
|
48384
|
-
`[Node9] Shadow repo path mismatch: stored="${stored}" expected="${normalizedCwd}" \u2014 reinitializing`
|
|
48385
|
-
);
|
|
48386
|
-
fs47.rmSync(shadowDir, { recursive: true, force: true });
|
|
48387
|
-
} catch {
|
|
48388
|
-
try {
|
|
48389
|
-
fs47.writeFileSync(ptPath, normalizedCwd, "utf8");
|
|
48390
|
-
} catch {
|
|
48391
|
-
}
|
|
48392
|
-
return true;
|
|
48393
|
-
}
|
|
48394
|
-
}
|
|
48395
|
-
try {
|
|
48396
|
-
fs47.mkdirSync(shadowDir, { recursive: true });
|
|
48397
|
-
} catch {
|
|
48398
|
-
}
|
|
48399
|
-
const init = spawnSync3("git", ["init", "--bare", shadowDir], { timeout: 5e3 });
|
|
48400
|
-
if (init.status !== 0 || init.error) {
|
|
48401
|
-
const reason = init.error ? init.error.message : init.stderr?.toString();
|
|
48402
|
-
if (process.env.NODE9_DEBUG === "1") console.error("[Node9] git init --bare failed:", reason);
|
|
48403
|
-
return false;
|
|
48404
|
-
}
|
|
48405
|
-
const configFile = path45.join(shadowDir, "config");
|
|
48406
|
-
spawnSync3("git", ["config", "--file", configFile, "core.untrackedCache", "true"], {
|
|
48407
|
-
timeout: 3e3
|
|
48408
|
-
});
|
|
48409
|
-
spawnSync3("git", ["config", "--file", configFile, "core.fsmonitor", "true"], {
|
|
48410
|
-
timeout: 3e3
|
|
48411
|
-
});
|
|
48412
|
-
try {
|
|
48413
|
-
fs47.writeFileSync(path45.join(shadowDir, "project-path.txt"), normalizedCwd, "utf8");
|
|
48414
|
-
} catch {
|
|
48415
|
-
}
|
|
48416
|
-
return true;
|
|
48417
|
-
}
|
|
48418
|
-
async function createShadowSnapshot(tool = "unknown", args = {}, ignorePaths = []) {
|
|
48419
|
-
let indexFile = null;
|
|
48420
|
-
try {
|
|
48421
|
-
const rawFilePath = extractFilePath(args);
|
|
48422
|
-
const absFilePath = rawFilePath && path45.isAbsolute(rawFilePath) ? rawFilePath : null;
|
|
48423
|
-
const cwd = absFilePath ? findProjectRoot(absFilePath) : process.cwd();
|
|
48424
|
-
const shadowDir = getShadowRepoDir(cwd);
|
|
48425
|
-
if (!ensureShadowRepo(shadowDir, cwd)) return null;
|
|
48426
|
-
writeShadowExcludes(shadowDir, ignorePaths);
|
|
48427
|
-
indexFile = path45.join(shadowDir, `index_${process.pid}_${Date.now()}`);
|
|
48428
|
-
const shadowEnv = {
|
|
48429
|
-
...process.env,
|
|
48430
|
-
GIT_DIR: shadowDir,
|
|
48431
|
-
GIT_WORK_TREE: cwd,
|
|
48432
|
-
GIT_INDEX_FILE: indexFile
|
|
48433
|
-
};
|
|
48434
|
-
spawnSync3("git", ["add", "-A"], { env: shadowEnv, timeout: GIT_TIMEOUT });
|
|
48435
|
-
const treeRes = spawnSync3("git", ["write-tree"], { env: shadowEnv, timeout: GIT_TIMEOUT });
|
|
48436
|
-
const treeHash = treeRes.stdout?.toString().trim();
|
|
48437
|
-
if (!treeHash || treeRes.status !== 0) return null;
|
|
48438
|
-
const commitRes = spawnSync3(
|
|
48439
|
-
"git",
|
|
48440
|
-
["commit-tree", treeHash, "-m", `Node9 AI Snapshot: ${(/* @__PURE__ */ new Date()).toISOString()}`],
|
|
48441
|
-
{ env: shadowEnv, timeout: GIT_TIMEOUT }
|
|
48442
|
-
);
|
|
48443
|
-
const commitHash = commitRes.stdout?.toString().trim();
|
|
48444
|
-
if (!commitHash || commitRes.status !== 0) return null;
|
|
48445
|
-
const stack = readStack();
|
|
48446
|
-
const prevEntry = [...stack].reverse().find((e) => e.cwd === cwd);
|
|
48447
|
-
let capturedFiles = [];
|
|
48448
|
-
let capturedDiff = null;
|
|
48449
|
-
if (prevEntry) {
|
|
48450
|
-
const filesRes = spawnSync3("git", ["diff", "--name-only", prevEntry.hash, commitHash], {
|
|
48451
|
-
env: shadowEnv,
|
|
48452
|
-
timeout: GIT_TIMEOUT
|
|
48453
|
-
});
|
|
48454
|
-
if (filesRes.status === 0) {
|
|
48455
|
-
capturedFiles = filesRes.stdout?.toString().trim().split("\n").filter(Boolean) ?? [];
|
|
48456
|
-
}
|
|
48457
|
-
if (capturedFiles.length === 0) {
|
|
48458
|
-
return prevEntry.hash;
|
|
48459
|
-
}
|
|
48460
|
-
const diffRes = spawnSync3("git", ["diff", prevEntry.hash, commitHash], {
|
|
48461
|
-
env: shadowEnv,
|
|
48462
|
-
timeout: GIT_TIMEOUT
|
|
48463
|
-
});
|
|
48464
|
-
if (diffRes.status === 0) {
|
|
48465
|
-
capturedDiff = diffRes.stdout?.toString() || null;
|
|
48466
|
-
}
|
|
48467
|
-
} else {
|
|
48468
|
-
const filesRes = spawnSync3("git", ["ls-tree", "-r", "--name-only", commitHash], {
|
|
48469
|
-
env: shadowEnv,
|
|
48470
|
-
timeout: GIT_TIMEOUT
|
|
48471
|
-
});
|
|
48472
|
-
if (filesRes.status === 0) {
|
|
48473
|
-
capturedFiles = filesRes.stdout?.toString().trim().split("\n").filter(Boolean) ?? [];
|
|
48474
|
-
}
|
|
48475
|
-
capturedDiff = null;
|
|
48476
|
-
}
|
|
48477
|
-
stack.push({
|
|
48478
|
-
hash: commitHash,
|
|
48479
|
-
tool,
|
|
48480
|
-
argsSummary: buildArgsSummary(tool, args),
|
|
48481
|
-
files: capturedFiles,
|
|
48482
|
-
diff: capturedDiff,
|
|
48483
|
-
cwd,
|
|
48484
|
-
timestamp: Date.now()
|
|
48485
|
-
});
|
|
48486
|
-
const shouldGc = stack.length % 5 === 0;
|
|
48487
|
-
let cwdCount = 0;
|
|
48488
|
-
let oldestCwdIdx = -1;
|
|
48489
|
-
for (let i = 0; i < stack.length; i++) {
|
|
48490
|
-
if (stack[i].cwd === cwd) {
|
|
48491
|
-
if (oldestCwdIdx === -1) oldestCwdIdx = i;
|
|
48492
|
-
cwdCount++;
|
|
48493
|
-
}
|
|
48494
|
-
}
|
|
48495
|
-
if (cwdCount > MAX_SNAPSHOTS) stack.splice(oldestCwdIdx, 1);
|
|
48496
|
-
writeStack(stack);
|
|
48497
|
-
const entry = stack[stack.length - 1];
|
|
48498
|
-
notifySnapshotTaken(commitHash.slice(0, 7), tool, entry.argsSummary, capturedFiles.length);
|
|
48499
|
-
fs47.writeFileSync(UNDO_LATEST_PATH, commitHash);
|
|
48500
|
-
if (shouldGc) {
|
|
48501
|
-
spawn4("git", ["gc", "--auto"], { env: shadowEnv, detached: true, stdio: "ignore" }).unref();
|
|
48502
|
-
}
|
|
48503
|
-
return commitHash;
|
|
48504
|
-
} catch (err2) {
|
|
48505
|
-
if (process.env.NODE9_DEBUG === "1") console.error("[Node9 Undo Engine Error]:", err2);
|
|
48506
|
-
return null;
|
|
48507
|
-
} finally {
|
|
48508
|
-
if (indexFile) {
|
|
48509
|
-
try {
|
|
48510
|
-
fs47.unlinkSync(indexFile);
|
|
48511
|
-
} catch {
|
|
48512
|
-
}
|
|
48513
|
-
}
|
|
48514
|
-
}
|
|
48515
|
-
}
|
|
48516
|
-
function getSnapshotHistory() {
|
|
48517
|
-
return readStack();
|
|
48518
|
-
}
|
|
48519
|
-
|
|
48520
|
-
// src/skill-pin.ts
|
|
48521
|
-
import fs48 from "fs";
|
|
48522
|
-
import path46 from "path";
|
|
48523
|
-
import os43 from "os";
|
|
48524
|
-
import crypto8 from "crypto";
|
|
48179
|
+
import crypto7 from "crypto";
|
|
48525
48180
|
function getPinsFilePath2() {
|
|
48526
|
-
return
|
|
48181
|
+
return path45.join(os42.homedir(), ".node9", "skill-pins.json");
|
|
48527
48182
|
}
|
|
48528
48183
|
var MAX_FILES = 5e3;
|
|
48529
48184
|
var MAX_TOTAL_BYTES = 50 * 1024 * 1024;
|
|
48530
48185
|
function sha256Bytes(buf) {
|
|
48531
|
-
return
|
|
48186
|
+
return crypto7.createHash("sha256").update(buf).digest("hex");
|
|
48532
48187
|
}
|
|
48533
48188
|
function walkDir(root) {
|
|
48534
48189
|
const out = [];
|
|
@@ -48537,18 +48192,18 @@ function walkDir(root) {
|
|
|
48537
48192
|
if (out.length >= MAX_FILES) return;
|
|
48538
48193
|
let entries;
|
|
48539
48194
|
try {
|
|
48540
|
-
entries =
|
|
48195
|
+
entries = fs47.readdirSync(dir, { withFileTypes: true });
|
|
48541
48196
|
} catch {
|
|
48542
48197
|
return;
|
|
48543
48198
|
}
|
|
48544
48199
|
entries.sort((a, b) => a.name.localeCompare(b.name));
|
|
48545
48200
|
for (const entry of entries) {
|
|
48546
48201
|
if (out.length >= MAX_FILES) return;
|
|
48547
|
-
const full =
|
|
48548
|
-
const rel = relDir ?
|
|
48202
|
+
const full = path45.join(dir, entry.name);
|
|
48203
|
+
const rel = relDir ? path45.posix.join(relDir, entry.name) : entry.name;
|
|
48549
48204
|
let lst;
|
|
48550
48205
|
try {
|
|
48551
|
-
lst =
|
|
48206
|
+
lst = fs47.lstatSync(full);
|
|
48552
48207
|
} catch {
|
|
48553
48208
|
continue;
|
|
48554
48209
|
}
|
|
@@ -48560,7 +48215,7 @@ function walkDir(root) {
|
|
|
48560
48215
|
if (!lst.isFile()) continue;
|
|
48561
48216
|
if (totalBytes + lst.size > MAX_TOTAL_BYTES) continue;
|
|
48562
48217
|
try {
|
|
48563
|
-
const buf =
|
|
48218
|
+
const buf = fs47.readFileSync(full);
|
|
48564
48219
|
totalBytes += buf.length;
|
|
48565
48220
|
out.push({ rel, hash: sha256Bytes(buf) });
|
|
48566
48221
|
} catch {
|
|
@@ -48574,32 +48229,32 @@ function walkDir(root) {
|
|
|
48574
48229
|
function hashSkillRoot(absPath) {
|
|
48575
48230
|
let lst;
|
|
48576
48231
|
try {
|
|
48577
|
-
lst =
|
|
48232
|
+
lst = fs47.lstatSync(absPath);
|
|
48578
48233
|
} catch {
|
|
48579
48234
|
return { exists: false, contentHash: "", fileCount: 0 };
|
|
48580
48235
|
}
|
|
48581
48236
|
if (lst.isSymbolicLink()) return { exists: false, contentHash: "", fileCount: 0 };
|
|
48582
48237
|
if (lst.isFile()) {
|
|
48583
48238
|
try {
|
|
48584
|
-
return { exists: true, contentHash: sha256Bytes(
|
|
48239
|
+
return { exists: true, contentHash: sha256Bytes(fs47.readFileSync(absPath)), fileCount: 1 };
|
|
48585
48240
|
} catch {
|
|
48586
48241
|
return { exists: false, contentHash: "", fileCount: 0 };
|
|
48587
48242
|
}
|
|
48588
48243
|
}
|
|
48589
48244
|
if (lst.isDirectory()) {
|
|
48590
48245
|
const entries = walkDir(absPath);
|
|
48591
|
-
const contentHash =
|
|
48246
|
+
const contentHash = crypto7.createHash("sha256").update(entries.join("\n")).digest("hex");
|
|
48592
48247
|
return { exists: true, contentHash, fileCount: entries.length };
|
|
48593
48248
|
}
|
|
48594
48249
|
return { exists: false, contentHash: "", fileCount: 0 };
|
|
48595
48250
|
}
|
|
48596
48251
|
function getRootKey(absPath) {
|
|
48597
|
-
return
|
|
48252
|
+
return crypto7.createHash("sha256").update(absPath).digest("hex").slice(0, 16);
|
|
48598
48253
|
}
|
|
48599
48254
|
function readSkillPinsSafe() {
|
|
48600
48255
|
const filePath = getPinsFilePath2();
|
|
48601
48256
|
try {
|
|
48602
|
-
const raw =
|
|
48257
|
+
const raw = fs47.readFileSync(filePath, "utf-8");
|
|
48603
48258
|
if (!raw.trim()) return { ok: false, reason: "corrupt", detail: "empty file" };
|
|
48604
48259
|
const parsed = JSON.parse(raw);
|
|
48605
48260
|
if (!parsed.roots || typeof parsed.roots !== "object" || Array.isArray(parsed.roots)) {
|
|
@@ -48619,10 +48274,10 @@ function readSkillPins() {
|
|
|
48619
48274
|
}
|
|
48620
48275
|
function writeSkillPins(data) {
|
|
48621
48276
|
const filePath = getPinsFilePath2();
|
|
48622
|
-
|
|
48623
|
-
const tmp = `${filePath}.${
|
|
48624
|
-
|
|
48625
|
-
|
|
48277
|
+
fs47.mkdirSync(path45.dirname(filePath), { recursive: true });
|
|
48278
|
+
const tmp = `${filePath}.${crypto7.randomBytes(6).toString("hex")}.tmp`;
|
|
48279
|
+
fs47.writeFileSync(tmp, JSON.stringify(data, null, 2), { mode: 384 });
|
|
48280
|
+
fs47.renameSync(tmp, filePath);
|
|
48626
48281
|
}
|
|
48627
48282
|
function removePin2(rootKey) {
|
|
48628
48283
|
const pins = readSkillPins();
|
|
@@ -48666,36 +48321,36 @@ function verifyAndPinRoots(roots) {
|
|
|
48666
48321
|
return { kind: "verified" };
|
|
48667
48322
|
}
|
|
48668
48323
|
function defaultSkillRoots(_cwd) {
|
|
48669
|
-
const marketplaces =
|
|
48324
|
+
const marketplaces = path45.join(os42.homedir(), ".claude", "plugins", "marketplaces");
|
|
48670
48325
|
const roots = [];
|
|
48671
48326
|
let registries;
|
|
48672
48327
|
try {
|
|
48673
|
-
registries =
|
|
48328
|
+
registries = fs47.readdirSync(marketplaces, { withFileTypes: true });
|
|
48674
48329
|
} catch {
|
|
48675
48330
|
return [];
|
|
48676
48331
|
}
|
|
48677
48332
|
for (const registry of registries) {
|
|
48678
48333
|
if (!registry.isDirectory()) continue;
|
|
48679
|
-
const pluginsDir =
|
|
48334
|
+
const pluginsDir = path45.join(marketplaces, registry.name, "plugins");
|
|
48680
48335
|
let plugins;
|
|
48681
48336
|
try {
|
|
48682
|
-
plugins =
|
|
48337
|
+
plugins = fs47.readdirSync(pluginsDir, { withFileTypes: true });
|
|
48683
48338
|
} catch {
|
|
48684
48339
|
continue;
|
|
48685
48340
|
}
|
|
48686
48341
|
for (const plugin of plugins) {
|
|
48687
48342
|
if (!plugin.isDirectory()) continue;
|
|
48688
|
-
roots.push(
|
|
48343
|
+
roots.push(path45.join(pluginsDir, plugin.name));
|
|
48689
48344
|
}
|
|
48690
48345
|
}
|
|
48691
48346
|
return roots;
|
|
48692
48347
|
}
|
|
48693
48348
|
function resolveUserSkillRoot(entry, cwd) {
|
|
48694
48349
|
if (!entry) return null;
|
|
48695
|
-
if (entry.startsWith("~/") || entry === "~") return
|
|
48696
|
-
if (
|
|
48697
|
-
if (!cwd || !
|
|
48698
|
-
return
|
|
48350
|
+
if (entry.startsWith("~/") || entry === "~") return path45.join(os42.homedir(), entry.slice(1));
|
|
48351
|
+
if (path45.isAbsolute(entry)) return entry;
|
|
48352
|
+
if (!cwd || !path45.isAbsolute(cwd)) return null;
|
|
48353
|
+
return path45.join(cwd, entry);
|
|
48699
48354
|
}
|
|
48700
48355
|
|
|
48701
48356
|
// src/cli/commands/check.ts
|
|
@@ -48704,11 +48359,11 @@ init_audit();
|
|
|
48704
48359
|
|
|
48705
48360
|
// src/review-pending.ts
|
|
48706
48361
|
init_hasher();
|
|
48707
|
-
import
|
|
48708
|
-
import
|
|
48709
|
-
import
|
|
48362
|
+
import fs48 from "fs";
|
|
48363
|
+
import os43 from "os";
|
|
48364
|
+
import path46 from "path";
|
|
48710
48365
|
function storePath() {
|
|
48711
|
-
return process.env.NODE9_PENDING_STORE ||
|
|
48366
|
+
return process.env.NODE9_PENDING_STORE || path46.join(os43.homedir(), ".node9", "pending-reviews.json");
|
|
48712
48367
|
}
|
|
48713
48368
|
var TTL_TUID_MS = 72 * 60 * 60 * 1e3;
|
|
48714
48369
|
var TTL_MS2 = 6 * 60 * 60 * 1e3;
|
|
@@ -48726,7 +48381,7 @@ function reviewCorrelationKey(payload) {
|
|
|
48726
48381
|
}
|
|
48727
48382
|
function read() {
|
|
48728
48383
|
try {
|
|
48729
|
-
const parsed = JSON.parse(
|
|
48384
|
+
const parsed = JSON.parse(fs48.readFileSync(storePath(), "utf-8"));
|
|
48730
48385
|
if (parsed && Array.isArray(parsed.entries)) return parsed;
|
|
48731
48386
|
} catch {
|
|
48732
48387
|
}
|
|
@@ -48735,11 +48390,11 @@ function read() {
|
|
|
48735
48390
|
function write(store) {
|
|
48736
48391
|
try {
|
|
48737
48392
|
const p = storePath();
|
|
48738
|
-
const dir =
|
|
48739
|
-
if (!
|
|
48393
|
+
const dir = path46.dirname(p);
|
|
48394
|
+
if (!fs48.existsSync(dir)) fs48.mkdirSync(dir, { recursive: true });
|
|
48740
48395
|
const tmp = `${p}.${process.pid}.tmp`;
|
|
48741
|
-
|
|
48742
|
-
|
|
48396
|
+
fs48.writeFileSync(tmp, JSON.stringify(store));
|
|
48397
|
+
fs48.renameSync(tmp, p);
|
|
48743
48398
|
} catch {
|
|
48744
48399
|
}
|
|
48745
48400
|
}
|
|
@@ -48868,9 +48523,9 @@ function registerCheckCommand(program2) {
|
|
|
48868
48523
|
} catch (err2) {
|
|
48869
48524
|
const tempConfig = getConfig();
|
|
48870
48525
|
if (process.env.NODE9_DEBUG === "1" || tempConfig.settings.enableHookLogDebug) {
|
|
48871
|
-
const logPath =
|
|
48526
|
+
const logPath = path47.join(os44.homedir(), ".node9", "hook-debug.log");
|
|
48872
48527
|
const errMsg = err2 instanceof Error ? err2.message : String(err2);
|
|
48873
|
-
|
|
48528
|
+
fs49.appendFileSync(
|
|
48874
48529
|
logPath,
|
|
48875
48530
|
`[${(/* @__PURE__ */ new Date()).toISOString()}] JSON_PARSE_ERROR: ${errMsg}
|
|
48876
48531
|
RAW: ${raw}
|
|
@@ -48883,14 +48538,14 @@ RAW: ${raw}
|
|
|
48883
48538
|
const prompt = typeof payload.prompt === "string" ? payload.prompt : "";
|
|
48884
48539
|
if (process.env.NODE9_DEBUG === "1") {
|
|
48885
48540
|
try {
|
|
48886
|
-
const logPath =
|
|
48887
|
-
if (!
|
|
48888
|
-
|
|
48541
|
+
const logPath = path47.join(os44.homedir(), ".node9", "hook-debug.log");
|
|
48542
|
+
if (!fs49.existsSync(path47.dirname(logPath)))
|
|
48543
|
+
fs49.mkdirSync(path47.dirname(logPath), { recursive: true });
|
|
48889
48544
|
const sanitized = JSON.stringify({
|
|
48890
48545
|
...payload,
|
|
48891
48546
|
prompt: `<redacted, ${prompt.length} bytes>`
|
|
48892
48547
|
});
|
|
48893
|
-
|
|
48548
|
+
fs49.appendFileSync(logPath, `[${(/* @__PURE__ */ new Date()).toISOString()}] STDIN: ${sanitized}
|
|
48894
48549
|
`);
|
|
48895
48550
|
} catch {
|
|
48896
48551
|
}
|
|
@@ -48911,8 +48566,8 @@ RAW: ${raw}
|
|
|
48911
48566
|
);
|
|
48912
48567
|
const reason = `\u{1F6A8} Node9 DLP: ${dlpMatch.patternName} detected in prompt (${dlpMatch.redactedSample}). Prompt was not submitted \u2014 remove the credential and try again.`;
|
|
48913
48568
|
try {
|
|
48914
|
-
const ttyFd =
|
|
48915
|
-
|
|
48569
|
+
const ttyFd = fs49.openSync("/dev/tty", "w");
|
|
48570
|
+
fs49.writeSync(
|
|
48916
48571
|
ttyFd,
|
|
48917
48572
|
chalk9.bgRed.white.bold(`
|
|
48918
48573
|
\u{1F6A8} NODE9 DLP \u2014 PROMPT BLOCKED
|
|
@@ -48922,7 +48577,7 @@ RAW: ${raw}
|
|
|
48922
48577
|
|
|
48923
48578
|
`)
|
|
48924
48579
|
);
|
|
48925
|
-
|
|
48580
|
+
fs49.closeSync(ttyFd);
|
|
48926
48581
|
} catch {
|
|
48927
48582
|
}
|
|
48928
48583
|
const isCodex = agent2 === "Codex";
|
|
@@ -48941,17 +48596,17 @@ RAW: ${raw}
|
|
|
48941
48596
|
process.exit(2);
|
|
48942
48597
|
}
|
|
48943
48598
|
const payloadCwd = typeof payload.cwd === "string" ? payload.cwd : Array.isArray(payload.workspacePaths) && typeof payload.workspacePaths[0] === "string" ? payload.workspacePaths[0] : void 0;
|
|
48944
|
-
const safeCwdForConfig = typeof payloadCwd === "string" &&
|
|
48599
|
+
const safeCwdForConfig = typeof payloadCwd === "string" && path47.isAbsolute(payloadCwd) ? payloadCwd : void 0;
|
|
48945
48600
|
const config = getConfig(safeCwdForConfig);
|
|
48946
48601
|
const daemonDown = !isDaemonRunning();
|
|
48947
48602
|
if (config.settings.autoStartDaemon && daemonDown && !process.env.NODE9_NO_AUTO_DAEMON) {
|
|
48948
48603
|
try {
|
|
48949
48604
|
const scriptPath = process.argv[1];
|
|
48950
|
-
if (typeof scriptPath !== "string" || !
|
|
48605
|
+
if (typeof scriptPath !== "string" || !path47.isAbsolute(scriptPath))
|
|
48951
48606
|
throw new Error("node9: argv[1] is not an absolute path");
|
|
48952
|
-
const resolvedScript =
|
|
48953
|
-
const packageDist =
|
|
48954
|
-
if (!resolvedScript.startsWith(packageDist +
|
|
48607
|
+
const resolvedScript = fs49.realpathSync(scriptPath);
|
|
48608
|
+
const packageDist = fs49.realpathSync(path47.resolve(__dirname, "../.."));
|
|
48609
|
+
if (!resolvedScript.startsWith(packageDist + path47.sep) && resolvedScript !== packageDist)
|
|
48955
48610
|
throw new Error(
|
|
48956
48611
|
`node9: daemon spawn aborted \u2014 argv[1] (${resolvedScript}) is outside package dist (${packageDist})`
|
|
48957
48612
|
);
|
|
@@ -48969,7 +48624,7 @@ RAW: ${raw}
|
|
|
48969
48624
|
const startupFd = openStartupLogFd();
|
|
48970
48625
|
recordStartupState("starting");
|
|
48971
48626
|
try {
|
|
48972
|
-
const d =
|
|
48627
|
+
const d = spawn4(process.execPath, [scriptPath, "daemon"], {
|
|
48973
48628
|
detached: true,
|
|
48974
48629
|
stdio: ["ignore", "ignore", startupFd ?? "ignore"],
|
|
48975
48630
|
env: { ...safeEnv, NODE9_AUTO_STARTED: "1" }
|
|
@@ -48981,17 +48636,17 @@ RAW: ${raw}
|
|
|
48981
48636
|
} finally {
|
|
48982
48637
|
if (startupFd !== void 0) {
|
|
48983
48638
|
try {
|
|
48984
|
-
|
|
48639
|
+
fs49.closeSync(startupFd);
|
|
48985
48640
|
} catch {
|
|
48986
48641
|
}
|
|
48987
48642
|
}
|
|
48988
48643
|
}
|
|
48989
48644
|
} catch (spawnErr) {
|
|
48990
|
-
const logPath =
|
|
48645
|
+
const logPath = path47.join(os44.homedir(), ".node9", "hook-debug.log");
|
|
48991
48646
|
const msg = spawnErr instanceof Error ? spawnErr.message : String(spawnErr);
|
|
48992
48647
|
recordStartupState("failed", "spawn-aborted", msg);
|
|
48993
48648
|
try {
|
|
48994
|
-
|
|
48649
|
+
fs49.appendFileSync(
|
|
48995
48650
|
logPath,
|
|
48996
48651
|
`[${(/* @__PURE__ */ new Date()).toISOString()}] daemon-autostart-failed: ${msg}
|
|
48997
48652
|
`
|
|
@@ -49005,10 +48660,10 @@ RAW: ${raw}
|
|
|
49005
48660
|
);
|
|
49006
48661
|
}
|
|
49007
48662
|
if (process.env.NODE9_DEBUG === "1" || config.settings.enableHookLogDebug) {
|
|
49008
|
-
const logPath =
|
|
49009
|
-
if (!
|
|
49010
|
-
|
|
49011
|
-
|
|
48663
|
+
const logPath = path47.join(os44.homedir(), ".node9", "hook-debug.log");
|
|
48664
|
+
if (!fs49.existsSync(path47.dirname(logPath)))
|
|
48665
|
+
fs49.mkdirSync(path47.dirname(logPath), { recursive: true });
|
|
48666
|
+
fs49.appendFileSync(logPath, `[${(/* @__PURE__ */ new Date()).toISOString()}] STDIN: ${raw}
|
|
49012
48667
|
`);
|
|
49013
48668
|
}
|
|
49014
48669
|
const rawToolName = sanitize2(extractToolName(payload));
|
|
@@ -49022,8 +48677,8 @@ RAW: ${raw}
|
|
|
49022
48677
|
const isHumanDecision = blockedByContext.toLowerCase().includes("user") || blockedByContext.toLowerCase().includes("daemon") || blockedByContext.toLowerCase().includes("decision");
|
|
49023
48678
|
let ttyFd = null;
|
|
49024
48679
|
try {
|
|
49025
|
-
ttyFd =
|
|
49026
|
-
const writeTty = (line) =>
|
|
48680
|
+
ttyFd = fs49.openSync("/dev/tty", "w");
|
|
48681
|
+
const writeTty = (line) => fs49.writeSync(ttyFd, line + "\n");
|
|
49027
48682
|
if (blockedByContext.includes("DLP") || blockedByContext.includes("Secret Detected") || blockedByContext.includes("Credential Review")) {
|
|
49028
48683
|
writeTty(chalk9.bgRed.white.bold(`
|
|
49029
48684
|
\u{1F6A8} NODE9 DLP ALERT \u2014 CREDENTIAL DETECTED `));
|
|
@@ -49042,7 +48697,7 @@ RAW: ${raw}
|
|
|
49042
48697
|
} finally {
|
|
49043
48698
|
if (ttyFd !== null)
|
|
49044
48699
|
try {
|
|
49045
|
-
|
|
48700
|
+
fs49.closeSync(ttyFd);
|
|
49046
48701
|
} catch {
|
|
49047
48702
|
}
|
|
49048
48703
|
}
|
|
@@ -49103,8 +48758,8 @@ RAW: ${raw}
|
|
|
49103
48758
|
} catch {
|
|
49104
48759
|
}
|
|
49105
48760
|
try {
|
|
49106
|
-
const ttyFd =
|
|
49107
|
-
|
|
48761
|
+
const ttyFd = fs49.openSync("/dev/tty", "w");
|
|
48762
|
+
fs49.writeSync(
|
|
49108
48763
|
ttyFd,
|
|
49109
48764
|
chalk9.yellow(
|
|
49110
48765
|
`
|
|
@@ -49112,7 +48767,7 @@ RAW: ${raw}
|
|
|
49112
48767
|
`
|
|
49113
48768
|
)
|
|
49114
48769
|
);
|
|
49115
|
-
|
|
48770
|
+
fs49.closeSync(ttyFd);
|
|
49116
48771
|
} catch {
|
|
49117
48772
|
}
|
|
49118
48773
|
if (agent === "GitHub Copilot") {
|
|
@@ -49144,17 +48799,17 @@ RAW: ${raw}
|
|
|
49144
48799
|
const safeSessionId = /^[A-Za-z0-9_\-]{1,128}$/.test(rawSessionId) ? rawSessionId : "";
|
|
49145
48800
|
if (skillPinCfg.enabled && safeSessionId) {
|
|
49146
48801
|
try {
|
|
49147
|
-
const sessionsDir =
|
|
49148
|
-
const flagPath =
|
|
48802
|
+
const sessionsDir = path47.join(os44.homedir(), ".node9", "skill-sessions");
|
|
48803
|
+
const flagPath = path47.join(sessionsDir, `${safeSessionId}.json`);
|
|
49149
48804
|
let flag = null;
|
|
49150
48805
|
try {
|
|
49151
|
-
flag = JSON.parse(
|
|
48806
|
+
flag = JSON.parse(fs49.readFileSync(flagPath, "utf-8"));
|
|
49152
48807
|
} catch {
|
|
49153
48808
|
}
|
|
49154
48809
|
const writeFlag = (data2) => {
|
|
49155
48810
|
try {
|
|
49156
|
-
|
|
49157
|
-
|
|
48811
|
+
fs49.mkdirSync(sessionsDir, { recursive: true });
|
|
48812
|
+
fs49.writeFileSync(
|
|
49158
48813
|
flagPath,
|
|
49159
48814
|
JSON.stringify({ ...data2, timestamp: (/* @__PURE__ */ new Date()).toISOString() }, null, 2),
|
|
49160
48815
|
{ mode: 384 }
|
|
@@ -49165,8 +48820,8 @@ RAW: ${raw}
|
|
|
49165
48820
|
const sendSkillWarn = (detail, recoveryCmd) => {
|
|
49166
48821
|
let ttyFd = null;
|
|
49167
48822
|
try {
|
|
49168
|
-
ttyFd =
|
|
49169
|
-
const w = (line) =>
|
|
48823
|
+
ttyFd = fs49.openSync("/dev/tty", "w");
|
|
48824
|
+
const w = (line) => fs49.writeSync(ttyFd, line + "\n");
|
|
49170
48825
|
w(chalk9.yellow(`
|
|
49171
48826
|
\u26A0\uFE0F Node9: installed skill drift detected`));
|
|
49172
48827
|
w(chalk9.gray(` ${detail}`));
|
|
@@ -49181,7 +48836,7 @@ RAW: ${raw}
|
|
|
49181
48836
|
} finally {
|
|
49182
48837
|
if (ttyFd !== null)
|
|
49183
48838
|
try {
|
|
49184
|
-
|
|
48839
|
+
fs49.closeSync(ttyFd);
|
|
49185
48840
|
} catch {
|
|
49186
48841
|
}
|
|
49187
48842
|
}
|
|
@@ -49197,7 +48852,7 @@ RAW: ${raw}
|
|
|
49197
48852
|
return;
|
|
49198
48853
|
}
|
|
49199
48854
|
if (!flag || flag.state !== "verified" && flag.state !== "warned") {
|
|
49200
|
-
const absoluteCwd = typeof payloadCwd === "string" &&
|
|
48855
|
+
const absoluteCwd = typeof payloadCwd === "string" && path47.isAbsolute(payloadCwd) ? payloadCwd : void 0;
|
|
49201
48856
|
const extraRoots = skillPinCfg.roots;
|
|
49202
48857
|
const resolvedExtra = extraRoots.map((r) => resolveUserSkillRoot(r, absoluteCwd)).filter((r) => typeof r === "string");
|
|
49203
48858
|
const roots = [...defaultSkillRoots(absoluteCwd), ...resolvedExtra];
|
|
@@ -49238,10 +48893,10 @@ RAW: ${raw}
|
|
|
49238
48893
|
}
|
|
49239
48894
|
try {
|
|
49240
48895
|
const cutoff = Date.now() - 7 * 24 * 60 * 60 * 1e3;
|
|
49241
|
-
for (const name of
|
|
49242
|
-
const p =
|
|
48896
|
+
for (const name of fs49.readdirSync(sessionsDir)) {
|
|
48897
|
+
const p = path47.join(sessionsDir, name);
|
|
49243
48898
|
try {
|
|
49244
|
-
if (
|
|
48899
|
+
if (fs49.statSync(p).mtimeMs < cutoff) fs49.unlinkSync(p);
|
|
49245
48900
|
} catch {
|
|
49246
48901
|
}
|
|
49247
48902
|
}
|
|
@@ -49251,19 +48906,16 @@ RAW: ${raw}
|
|
|
49251
48906
|
} catch (err2) {
|
|
49252
48907
|
if (process.env.NODE9_DEBUG === "1") {
|
|
49253
48908
|
try {
|
|
49254
|
-
const dbg =
|
|
48909
|
+
const dbg = path47.join(os44.homedir(), ".node9", "hook-debug.log");
|
|
49255
48910
|
const msg = err2 instanceof Error ? err2.message : String(err2);
|
|
49256
|
-
|
|
48911
|
+
fs49.appendFileSync(dbg, `[${(/* @__PURE__ */ new Date()).toISOString()}] SKILL_PIN_ERROR: ${msg}
|
|
49257
48912
|
`);
|
|
49258
48913
|
} catch {
|
|
49259
48914
|
}
|
|
49260
48915
|
}
|
|
49261
48916
|
}
|
|
49262
48917
|
}
|
|
49263
|
-
|
|
49264
|
-
await createShadowSnapshot(toolName, toolInput, config.policy.snapshot.ignorePaths);
|
|
49265
|
-
}
|
|
49266
|
-
const safeCwdForAuth = typeof payloadCwd === "string" && path48.isAbsolute(payloadCwd) ? payloadCwd : void 0;
|
|
48918
|
+
const safeCwdForAuth = typeof payloadCwd === "string" && path47.isAbsolute(payloadCwd) ? payloadCwd : void 0;
|
|
49267
48919
|
const askMode = resolveAskMode(agent, opts, config);
|
|
49268
48920
|
const result = await authorizeHeadless(toolName, toolInput, meta, {
|
|
49269
48921
|
cwd: safeCwdForAuth,
|
|
@@ -49288,12 +48940,12 @@ RAW: ${raw}
|
|
|
49288
48940
|
}
|
|
49289
48941
|
if (result.noApprovalMechanism && !isDaemonRunning() && !process.env.NODE9_NO_AUTO_DAEMON && !process.stdout.isTTY && config.settings.autoStartDaemon) {
|
|
49290
48942
|
try {
|
|
49291
|
-
const tty =
|
|
49292
|
-
|
|
48943
|
+
const tty = fs49.openSync("/dev/tty", "w");
|
|
48944
|
+
fs49.writeSync(
|
|
49293
48945
|
tty,
|
|
49294
48946
|
chalk9.cyan("\n\u{1F6E1}\uFE0F Node9: Starting approval daemon automatically...\n")
|
|
49295
48947
|
);
|
|
49296
|
-
|
|
48948
|
+
fs49.closeSync(tty);
|
|
49297
48949
|
} catch {
|
|
49298
48950
|
}
|
|
49299
48951
|
const daemonReady = await autoStartDaemonAndWait();
|
|
@@ -49320,9 +48972,9 @@ RAW: ${raw}
|
|
|
49320
48972
|
});
|
|
49321
48973
|
} catch (err2) {
|
|
49322
48974
|
if (process.env.NODE9_DEBUG === "1") {
|
|
49323
|
-
const logPath =
|
|
48975
|
+
const logPath = path47.join(os44.homedir(), ".node9", "hook-debug.log");
|
|
49324
48976
|
const errMsg = err2 instanceof Error ? err2.message : String(err2);
|
|
49325
|
-
|
|
48977
|
+
fs49.appendFileSync(logPath, `[${(/* @__PURE__ */ new Date()).toISOString()}] ERROR: ${errMsg}
|
|
49326
48978
|
`);
|
|
49327
48979
|
}
|
|
49328
48980
|
process.exit(0);
|
|
@@ -49358,9 +49010,9 @@ RAW: ${raw}
|
|
|
49358
49010
|
// src/cli/commands/log.ts
|
|
49359
49011
|
init_audit();
|
|
49360
49012
|
init_config();
|
|
49361
|
-
import
|
|
49362
|
-
import
|
|
49363
|
-
import
|
|
49013
|
+
import fs50 from "fs";
|
|
49014
|
+
import path48 from "path";
|
|
49015
|
+
import os45 from "os";
|
|
49364
49016
|
init_daemon();
|
|
49365
49017
|
init_dlp();
|
|
49366
49018
|
init_hasher();
|
|
@@ -49494,10 +49146,10 @@ function registerLogCommand(program2) {
|
|
|
49494
49146
|
if (rawToolName !== tool) entry.agentToolName = rawToolName;
|
|
49495
49147
|
const payloadSessionId = payload.session_id ?? payload.conversationId;
|
|
49496
49148
|
if (payloadSessionId) entry.sessionId = payloadSessionId;
|
|
49497
|
-
const logPath =
|
|
49498
|
-
if (!
|
|
49499
|
-
|
|
49500
|
-
|
|
49149
|
+
const logPath = path48.join(os45.homedir(), ".node9", "audit.log");
|
|
49150
|
+
if (!fs50.existsSync(path48.dirname(logPath)))
|
|
49151
|
+
fs50.mkdirSync(path48.dirname(logPath), { recursive: true });
|
|
49152
|
+
fs50.appendFileSync(logPath, JSON.stringify(entry) + "\n");
|
|
49501
49153
|
if ((tool === "Bash" || tool === "bash") && isDaemonRunning()) {
|
|
49502
49154
|
const command = typeof rawInput === "object" && rawInput !== null && "command" in rawInput && typeof rawInput.command === "string" ? rawInput.command : null;
|
|
49503
49155
|
if (command) {
|
|
@@ -49531,7 +49183,7 @@ function registerLogCommand(program2) {
|
|
|
49531
49183
|
}
|
|
49532
49184
|
}
|
|
49533
49185
|
const payloadCwd = typeof payload.cwd === "string" ? payload.cwd : Array.isArray(payload.workspacePaths) && typeof payload.workspacePaths[0] === "string" ? payload.workspacePaths[0] : void 0;
|
|
49534
|
-
const safeCwd = typeof payloadCwd === "string" &&
|
|
49186
|
+
const safeCwd = typeof payloadCwd === "string" && path48.isAbsolute(payloadCwd) ? payloadCwd : void 0;
|
|
49535
49187
|
const config = getConfig(safeCwd);
|
|
49536
49188
|
if (resolvedReview) {
|
|
49537
49189
|
try {
|
|
@@ -49616,28 +49268,13 @@ function registerLogCommand(program2) {
|
|
|
49616
49268
|
}
|
|
49617
49269
|
}
|
|
49618
49270
|
}
|
|
49619
|
-
if ((tool === "Bash" || tool === "bash") && config.settings.enableUndo === true) {
|
|
49620
|
-
const bashCommand = typeof rawInput === "object" && rawInput !== null && "command" in rawInput && typeof rawInput.command === "string" ? rawInput.command : null;
|
|
49621
|
-
if (bashCommand) {
|
|
49622
|
-
const effectiveCwd = safeCwd ?? process.cwd();
|
|
49623
|
-
const history = getSnapshotHistory();
|
|
49624
|
-
const hasPrior = history.some((e) => e.cwd === effectiveCwd);
|
|
49625
|
-
if (hasPrior) {
|
|
49626
|
-
await createShadowSnapshot(
|
|
49627
|
-
"Bash",
|
|
49628
|
-
{ command: bashCommand },
|
|
49629
|
-
config.policy.snapshot.ignorePaths
|
|
49630
|
-
);
|
|
49631
|
-
}
|
|
49632
|
-
}
|
|
49633
|
-
}
|
|
49634
49271
|
} catch (err2) {
|
|
49635
49272
|
const msg = err2 instanceof Error ? err2.message : String(err2);
|
|
49636
49273
|
process.stderr.write(`[Node9] audit log error: ${msg}
|
|
49637
49274
|
`);
|
|
49638
|
-
const debugPath =
|
|
49275
|
+
const debugPath = path48.join(os45.homedir(), ".node9", "hook-debug.log");
|
|
49639
49276
|
try {
|
|
49640
|
-
|
|
49277
|
+
fs50.appendFileSync(debugPath, `[${(/* @__PURE__ */ new Date()).toISOString()}] LOG_ERROR: ${msg}
|
|
49641
49278
|
`);
|
|
49642
49279
|
} catch {
|
|
49643
49280
|
}
|
|
@@ -49664,16 +49301,16 @@ function registerLogCommand(program2) {
|
|
|
49664
49301
|
init_shields();
|
|
49665
49302
|
init_build();
|
|
49666
49303
|
import chalk10 from "chalk";
|
|
49667
|
-
import
|
|
49668
|
-
import
|
|
49669
|
-
import
|
|
49304
|
+
import fs52 from "fs";
|
|
49305
|
+
import path50 from "path";
|
|
49306
|
+
import os46 from "os";
|
|
49670
49307
|
|
|
49671
49308
|
// src/shields/create.ts
|
|
49672
49309
|
init_dist();
|
|
49673
49310
|
init_shields();
|
|
49674
49311
|
init_audit();
|
|
49675
|
-
import
|
|
49676
|
-
import
|
|
49312
|
+
import fs51 from "fs";
|
|
49313
|
+
import path49 from "path";
|
|
49677
49314
|
function builtinNames() {
|
|
49678
49315
|
const names = /* @__PURE__ */ new Set();
|
|
49679
49316
|
for (const def of Object.values(BUILTIN_SHIELDS)) {
|
|
@@ -49690,8 +49327,8 @@ function createShield(def, opts = {}) {
|
|
|
49690
49327
|
error: `"${name}" is a built-in shield \u2014 choose a different name (a user shield with this name would shadow the built-in).`
|
|
49691
49328
|
};
|
|
49692
49329
|
}
|
|
49693
|
-
const filePath =
|
|
49694
|
-
if (!opts.overwrite &&
|
|
49330
|
+
const filePath = path49.join(USER_SHIELDS_DIR_PATH, `${name}.json`);
|
|
49331
|
+
if (!opts.overwrite && fs51.existsSync(filePath)) {
|
|
49695
49332
|
return {
|
|
49696
49333
|
ok: false,
|
|
49697
49334
|
error: `Shield "${name}" already exists at ${filePath}. Pass --overwrite to replace it.`
|
|
@@ -49756,8 +49393,8 @@ var COMMUNITY_INDEX_URL = "https://raw.githubusercontent.com/node9ai/node9-proxy
|
|
|
49756
49393
|
function readCloudShields() {
|
|
49757
49394
|
const out = /* @__PURE__ */ new Set();
|
|
49758
49395
|
try {
|
|
49759
|
-
const file =
|
|
49760
|
-
const raw = JSON.parse(
|
|
49396
|
+
const file = path50.join(os46.homedir(), ".node9", "rules-cache.json");
|
|
49397
|
+
const raw = JSON.parse(fs52.readFileSync(file, "utf-8"));
|
|
49761
49398
|
for (const r of raw.rules ?? []) {
|
|
49762
49399
|
const rule = r;
|
|
49763
49400
|
const fromSource = rule.source?.startsWith("SHIELD:") ? rule.source.slice("SHIELD:".length).toLowerCase() : void 0;
|
|
@@ -50074,7 +49711,7 @@ function registerShieldCommand(program2) {
|
|
|
50074
49711
|
if (opts.fromFile) {
|
|
50075
49712
|
let raw;
|
|
50076
49713
|
try {
|
|
50077
|
-
raw = JSON.parse(
|
|
49714
|
+
raw = JSON.parse(fs52.readFileSync(opts.fromFile, "utf-8"));
|
|
50078
49715
|
} catch (err2) {
|
|
50079
49716
|
console.error(
|
|
50080
49717
|
chalk10.red(`
|
|
@@ -50200,9 +49837,9 @@ init_agent_wiring();
|
|
|
50200
49837
|
init_sync();
|
|
50201
49838
|
init_service();
|
|
50202
49839
|
import chalk11 from "chalk";
|
|
50203
|
-
import
|
|
50204
|
-
import
|
|
50205
|
-
import
|
|
49840
|
+
import fs54 from "fs";
|
|
49841
|
+
import path52 from "path";
|
|
49842
|
+
import os48 from "os";
|
|
50206
49843
|
import { execSync } from "child_process";
|
|
50207
49844
|
|
|
50208
49845
|
// src/lib/relative-time.ts
|
|
@@ -50222,22 +49859,22 @@ function agoLabel(iso, now = Date.now()) {
|
|
|
50222
49859
|
init_startup_log();
|
|
50223
49860
|
|
|
50224
49861
|
// src/utils/undo-leftovers.ts
|
|
50225
|
-
import
|
|
50226
|
-
import
|
|
50227
|
-
import
|
|
49862
|
+
import fs53 from "fs";
|
|
49863
|
+
import os47 from "os";
|
|
49864
|
+
import path51 from "path";
|
|
50228
49865
|
function candidates(homeDir2) {
|
|
50229
|
-
const node9Dir =
|
|
49866
|
+
const node9Dir = path51.join(homeDir2, ".node9");
|
|
50230
49867
|
return [
|
|
50231
|
-
|
|
50232
|
-
|
|
50233
|
-
|
|
49868
|
+
path51.join(node9Dir, "snapshots"),
|
|
49869
|
+
path51.join(node9Dir, "snapshots.json"),
|
|
49870
|
+
path51.join(node9Dir, "undo_latest.txt")
|
|
50234
49871
|
];
|
|
50235
49872
|
}
|
|
50236
|
-
function undoLeftoverPaths(homeDir2 =
|
|
49873
|
+
function undoLeftoverPaths(homeDir2 = os47.homedir()) {
|
|
50237
49874
|
const found = [];
|
|
50238
49875
|
for (const p of candidates(homeDir2)) {
|
|
50239
49876
|
try {
|
|
50240
|
-
|
|
49877
|
+
fs53.lstatSync(p);
|
|
50241
49878
|
found.push(p);
|
|
50242
49879
|
} catch (err2) {
|
|
50243
49880
|
if (err2.code !== "ENOENT") found.push(p);
|
|
@@ -50245,11 +49882,11 @@ function undoLeftoverPaths(homeDir2 = os48.homedir()) {
|
|
|
50245
49882
|
}
|
|
50246
49883
|
return found;
|
|
50247
49884
|
}
|
|
50248
|
-
function purgeUndoLeftovers(homeDir2 =
|
|
49885
|
+
function purgeUndoLeftovers(homeDir2 = os47.homedir()) {
|
|
50249
49886
|
const out = { deleted: [], skipped: [], failed: [] };
|
|
50250
49887
|
for (const p of undoLeftoverPaths(homeDir2)) {
|
|
50251
49888
|
try {
|
|
50252
|
-
if (
|
|
49889
|
+
if (fs53.lstatSync(p).isSymbolicLink()) {
|
|
50253
49890
|
out.skipped.push({
|
|
50254
49891
|
path: p,
|
|
50255
49892
|
reason: "is a symlink \u2014 remove it yourself so nothing else is followed"
|
|
@@ -50262,11 +49899,11 @@ function purgeUndoLeftovers(homeDir2 = os48.homedir()) {
|
|
|
50262
49899
|
}
|
|
50263
49900
|
let reason = null;
|
|
50264
49901
|
try {
|
|
50265
|
-
|
|
49902
|
+
fs53.rmSync(p, { recursive: true, force: true });
|
|
50266
49903
|
} catch (err2) {
|
|
50267
49904
|
reason = err2.message;
|
|
50268
49905
|
}
|
|
50269
|
-
if (
|
|
49906
|
+
if (fs53.existsSync(p)) {
|
|
50270
49907
|
out.failed.push({ path: p, reason: reason ?? "still present after removal" });
|
|
50271
49908
|
} else {
|
|
50272
49909
|
out.deleted.push(p);
|
|
@@ -50278,7 +49915,7 @@ function purgeUndoLeftovers(homeDir2 = os48.homedir()) {
|
|
|
50278
49915
|
// src/cli/commands/doctor.ts
|
|
50279
49916
|
function registerDoctorCommand(program2, version2) {
|
|
50280
49917
|
program2.command("doctor").description("Check that Node9 is installed and configured correctly").action(async () => {
|
|
50281
|
-
const homeDir2 =
|
|
49918
|
+
const homeDir2 = os48.homedir();
|
|
50282
49919
|
let failures = 0;
|
|
50283
49920
|
function pass(msg) {
|
|
50284
49921
|
console.log(chalk11.green(" \u2705 ") + msg);
|
|
@@ -50321,10 +49958,10 @@ function registerDoctorCommand(program2, version2) {
|
|
|
50321
49958
|
warn("git not found", "Install git \u2014 node9 reads repo state for scans and reports");
|
|
50322
49959
|
}
|
|
50323
49960
|
section("Configuration");
|
|
50324
|
-
const globalConfigPath =
|
|
50325
|
-
if (
|
|
49961
|
+
const globalConfigPath = path52.join(homeDir2, ".node9", "config.json");
|
|
49962
|
+
if (fs54.existsSync(globalConfigPath)) {
|
|
50326
49963
|
try {
|
|
50327
|
-
JSON.parse(
|
|
49964
|
+
JSON.parse(fs54.readFileSync(globalConfigPath, "utf-8"));
|
|
50328
49965
|
pass("~/.node9/config.json found and valid");
|
|
50329
49966
|
} catch {
|
|
50330
49967
|
fail("~/.node9/config.json is invalid JSON", "Run: node9 init --force");
|
|
@@ -50339,10 +49976,10 @@ function registerDoctorCommand(program2, version2) {
|
|
|
50339
49976
|
"Remove them when ready: node9 undo --purge"
|
|
50340
49977
|
);
|
|
50341
49978
|
}
|
|
50342
|
-
const projectConfigPath =
|
|
50343
|
-
if (
|
|
49979
|
+
const projectConfigPath = path52.join(process.cwd(), "node9.config.json");
|
|
49980
|
+
if (fs54.existsSync(projectConfigPath)) {
|
|
50344
49981
|
try {
|
|
50345
|
-
JSON.parse(
|
|
49982
|
+
JSON.parse(fs54.readFileSync(projectConfigPath, "utf-8"));
|
|
50346
49983
|
pass("node9.config.json found and valid (project)");
|
|
50347
49984
|
} catch {
|
|
50348
49985
|
fail(
|
|
@@ -50351,8 +49988,8 @@ function registerDoctorCommand(program2, version2) {
|
|
|
50351
49988
|
);
|
|
50352
49989
|
}
|
|
50353
49990
|
}
|
|
50354
|
-
const credsPath =
|
|
50355
|
-
if (
|
|
49991
|
+
const credsPath = path52.join(homeDir2, ".node9", "credentials.json");
|
|
49992
|
+
if (fs54.existsSync(credsPath)) {
|
|
50356
49993
|
pass("Cloud credentials found (~/.node9/credentials.json)");
|
|
50357
49994
|
} else {
|
|
50358
49995
|
warn(
|
|
@@ -50418,7 +50055,7 @@ function registerDoctorCommand(program2, version2) {
|
|
|
50418
50055
|
cloudEnabled: !!getConfig().settings.approvers?.cloud
|
|
50419
50056
|
});
|
|
50420
50057
|
if (autostart) warn(autostart.message, autostart.hint);
|
|
50421
|
-
if (
|
|
50058
|
+
if (fs54.existsSync(path52.join(os48.homedir(), ".node9", "credentials.json")) && getConfig().settings.approvers?.cloud) {
|
|
50422
50059
|
section("Policy sync");
|
|
50423
50060
|
const health = readSyncHealth();
|
|
50424
50061
|
if (isPolicyStale(Date.now(), health)) {
|
|
@@ -50436,7 +50073,7 @@ function registerDoctorCommand(program2, version2) {
|
|
|
50436
50073
|
try {
|
|
50437
50074
|
const { shipLagBytes: shipLagBytes2, readWatermark: readWatermark2, AUDIT_SHIP_WATERMARK: AUDIT_SHIP_WATERMARK2 } = await Promise.resolve().then(() => (init_audit_shipper(), audit_shipper_exports));
|
|
50438
50075
|
const cfg = getConfig();
|
|
50439
|
-
const creds =
|
|
50076
|
+
const creds = fs54.existsSync(path52.join(os48.homedir(), ".node9", "credentials.json"));
|
|
50440
50077
|
if (!creds) {
|
|
50441
50078
|
warn("Not logged in \u2014 audit rows stay local", "Run: node9 login <api-key>");
|
|
50442
50079
|
} else if (!cfg.settings.approvers.cloud) {
|
|
@@ -50487,9 +50124,9 @@ function registerDoctorCommand(program2, version2) {
|
|
|
50487
50124
|
// src/cli/commands/audit.ts
|
|
50488
50125
|
init_decision();
|
|
50489
50126
|
import chalk12 from "chalk";
|
|
50490
|
-
import
|
|
50491
|
-
import
|
|
50492
|
-
import
|
|
50127
|
+
import fs55 from "fs";
|
|
50128
|
+
import path53 from "path";
|
|
50129
|
+
import os49 from "os";
|
|
50493
50130
|
function formatRelativeTime(timestamp) {
|
|
50494
50131
|
const diff = Date.now() - new Date(timestamp).getTime();
|
|
50495
50132
|
const sec = Math.floor(diff / 1e3);
|
|
@@ -50502,14 +50139,14 @@ function formatRelativeTime(timestamp) {
|
|
|
50502
50139
|
}
|
|
50503
50140
|
function registerAuditCommand(program2) {
|
|
50504
50141
|
program2.command("audit").description("View local execution audit log").option("--tail <n>", "Number of entries to show", "20").option("--tool <pattern>", "Filter by tool name (substring match)").option("--deny", "Show only denied actions").option("--json", "Output raw JSON").action((options) => {
|
|
50505
|
-
const logPath =
|
|
50506
|
-
if (!
|
|
50142
|
+
const logPath = path53.join(os49.homedir(), ".node9", "audit.log");
|
|
50143
|
+
if (!fs55.existsSync(logPath)) {
|
|
50507
50144
|
console.log(
|
|
50508
50145
|
chalk12.yellow("No audit logs found. Run node9 with an agent to generate entries.")
|
|
50509
50146
|
);
|
|
50510
50147
|
return;
|
|
50511
50148
|
}
|
|
50512
|
-
const raw =
|
|
50149
|
+
const raw = fs55.readFileSync(logPath, "utf-8");
|
|
50513
50150
|
const lines = raw.split("\n").filter((l) => l.trim() !== "");
|
|
50514
50151
|
let entries = lines.flatMap((line) => {
|
|
50515
50152
|
try {
|
|
@@ -50575,9 +50212,9 @@ init_costSync();
|
|
|
50575
50212
|
init_litellm();
|
|
50576
50213
|
init_cost_codex();
|
|
50577
50214
|
init_decision();
|
|
50578
|
-
import
|
|
50579
|
-
import
|
|
50580
|
-
import
|
|
50215
|
+
import fs56 from "fs";
|
|
50216
|
+
import os50 from "os";
|
|
50217
|
+
import path54 from "path";
|
|
50581
50218
|
var TEST_COMMAND_RE3 = /(?:^|\s)(npm\s+(?:run\s+)?test|npx\s+(?:vitest|jest|mocha)|yarn\s+(?:run\s+)?test|pnpm\s+(?:run\s+)?test|vitest|jest|mocha|pytest|py\.test|cargo\s+test|go\s+test|bundle\s+exec\s+rspec|rspec|phpunit|dotnet\s+test)\b/i;
|
|
50582
50219
|
function buildTestTimestamps(allEntries) {
|
|
50583
50220
|
const testTs = /* @__PURE__ */ new Set();
|
|
@@ -50657,8 +50294,8 @@ function getDateRange(period, now) {
|
|
|
50657
50294
|
}
|
|
50658
50295
|
}
|
|
50659
50296
|
function parseAuditLog(logPath) {
|
|
50660
|
-
if (!
|
|
50661
|
-
const raw =
|
|
50297
|
+
if (!fs56.existsSync(logPath)) return [];
|
|
50298
|
+
const raw = fs56.readFileSync(logPath, "utf-8");
|
|
50662
50299
|
return raw.split("\n").flatMap((line) => {
|
|
50663
50300
|
if (!line.trim()) return [];
|
|
50664
50301
|
try {
|
|
@@ -50712,25 +50349,25 @@ function freezeClaudeCost(acc) {
|
|
|
50712
50349
|
};
|
|
50713
50350
|
}
|
|
50714
50351
|
function processClaudeCostProject(proj, projectsDir, start, end, acc) {
|
|
50715
|
-
const projPath =
|
|
50352
|
+
const projPath = path54.join(projectsDir, proj);
|
|
50716
50353
|
let files;
|
|
50717
50354
|
try {
|
|
50718
|
-
const stat =
|
|
50355
|
+
const stat = fs56.statSync(projPath);
|
|
50719
50356
|
if (!stat.isDirectory()) return;
|
|
50720
|
-
files =
|
|
50357
|
+
files = fs56.readdirSync(projPath).filter((f) => f.endsWith(".jsonl") && !f.startsWith("agent-"));
|
|
50721
50358
|
} catch {
|
|
50722
50359
|
return;
|
|
50723
50360
|
}
|
|
50724
50361
|
const startMs = start.getTime();
|
|
50725
50362
|
for (const file of files) {
|
|
50726
|
-
const filePath =
|
|
50363
|
+
const filePath = path54.join(projPath, file);
|
|
50727
50364
|
try {
|
|
50728
|
-
if (
|
|
50365
|
+
if (fs56.statSync(filePath).mtimeMs < startMs) continue;
|
|
50729
50366
|
} catch {
|
|
50730
50367
|
continue;
|
|
50731
50368
|
}
|
|
50732
50369
|
try {
|
|
50733
|
-
const raw =
|
|
50370
|
+
const raw = fs56.readFileSync(filePath, "utf-8");
|
|
50734
50371
|
for (const line of raw.split("\n")) {
|
|
50735
50372
|
if (!line.trim()) continue;
|
|
50736
50373
|
let entry;
|
|
@@ -50780,10 +50417,10 @@ function processClaudeCostProject(proj, projectsDir, start, end, acc) {
|
|
|
50780
50417
|
}
|
|
50781
50418
|
function loadClaudeCost(start, end, projectsDir) {
|
|
50782
50419
|
const acc = emptyClaudeCostAccumulator();
|
|
50783
|
-
if (!
|
|
50420
|
+
if (!fs56.existsSync(projectsDir)) return freezeClaudeCost(acc);
|
|
50784
50421
|
let dirs;
|
|
50785
50422
|
try {
|
|
50786
|
-
dirs =
|
|
50423
|
+
dirs = fs56.readdirSync(projectsDir);
|
|
50787
50424
|
} catch {
|
|
50788
50425
|
return freezeClaudeCost(acc);
|
|
50789
50426
|
}
|
|
@@ -50795,7 +50432,7 @@ function loadClaudeCost(start, end, projectsDir) {
|
|
|
50795
50432
|
function processCodexCostFile(filePath, start, end, acc) {
|
|
50796
50433
|
let lines;
|
|
50797
50434
|
try {
|
|
50798
|
-
lines =
|
|
50435
|
+
lines = fs56.readFileSync(filePath, "utf-8").split("\n");
|
|
50799
50436
|
} catch {
|
|
50800
50437
|
return;
|
|
50801
50438
|
}
|
|
@@ -50850,31 +50487,31 @@ function processCodexCostFile(filePath, start, end, acc) {
|
|
|
50850
50487
|
}
|
|
50851
50488
|
function listCodexSessionFiles2(sessionsBase) {
|
|
50852
50489
|
const jsonlFiles = [];
|
|
50853
|
-
if (!
|
|
50490
|
+
if (!fs56.existsSync(sessionsBase)) return jsonlFiles;
|
|
50854
50491
|
try {
|
|
50855
|
-
for (const year of
|
|
50856
|
-
const yearPath =
|
|
50492
|
+
for (const year of fs56.readdirSync(sessionsBase)) {
|
|
50493
|
+
const yearPath = path54.join(sessionsBase, year);
|
|
50857
50494
|
try {
|
|
50858
|
-
if (!
|
|
50495
|
+
if (!fs56.statSync(yearPath).isDirectory()) continue;
|
|
50859
50496
|
} catch {
|
|
50860
50497
|
continue;
|
|
50861
50498
|
}
|
|
50862
|
-
for (const month of
|
|
50863
|
-
const monthPath =
|
|
50499
|
+
for (const month of fs56.readdirSync(yearPath)) {
|
|
50500
|
+
const monthPath = path54.join(yearPath, month);
|
|
50864
50501
|
try {
|
|
50865
|
-
if (!
|
|
50502
|
+
if (!fs56.statSync(monthPath).isDirectory()) continue;
|
|
50866
50503
|
} catch {
|
|
50867
50504
|
continue;
|
|
50868
50505
|
}
|
|
50869
|
-
for (const day of
|
|
50870
|
-
const dayPath =
|
|
50506
|
+
for (const day of fs56.readdirSync(monthPath)) {
|
|
50507
|
+
const dayPath = path54.join(monthPath, day);
|
|
50871
50508
|
try {
|
|
50872
|
-
if (!
|
|
50509
|
+
if (!fs56.statSync(dayPath).isDirectory()) continue;
|
|
50873
50510
|
} catch {
|
|
50874
50511
|
continue;
|
|
50875
50512
|
}
|
|
50876
|
-
for (const file of
|
|
50877
|
-
if (file.endsWith(".jsonl")) jsonlFiles.push(
|
|
50513
|
+
for (const file of fs56.readdirSync(dayPath)) {
|
|
50514
|
+
if (file.endsWith(".jsonl")) jsonlFiles.push(path54.join(dayPath, file));
|
|
50878
50515
|
}
|
|
50879
50516
|
}
|
|
50880
50517
|
}
|
|
@@ -50939,13 +50576,13 @@ function freezeGeminiCost(acc) {
|
|
|
50939
50576
|
function processGeminiCostFile(filePath, projectKey, start, end, acc) {
|
|
50940
50577
|
const startMs = start.getTime();
|
|
50941
50578
|
try {
|
|
50942
|
-
if (
|
|
50579
|
+
if (fs56.statSync(filePath).mtimeMs < startMs) return;
|
|
50943
50580
|
} catch {
|
|
50944
50581
|
return;
|
|
50945
50582
|
}
|
|
50946
50583
|
let raw;
|
|
50947
50584
|
try {
|
|
50948
|
-
raw =
|
|
50585
|
+
raw = fs56.readFileSync(filePath, "utf-8");
|
|
50949
50586
|
} catch {
|
|
50950
50587
|
return;
|
|
50951
50588
|
}
|
|
@@ -50994,30 +50631,30 @@ function listGeminiSessionFiles2(geminiTmpDir2) {
|
|
|
50994
50631
|
const out = [];
|
|
50995
50632
|
let dirs;
|
|
50996
50633
|
try {
|
|
50997
|
-
if (!
|
|
50998
|
-
dirs =
|
|
50634
|
+
if (!fs56.statSync(geminiTmpDir2).isDirectory()) return out;
|
|
50635
|
+
dirs = fs56.readdirSync(geminiTmpDir2);
|
|
50999
50636
|
} catch {
|
|
51000
50637
|
return out;
|
|
51001
50638
|
}
|
|
51002
50639
|
for (const proj of dirs) {
|
|
51003
|
-
const chatsDir =
|
|
50640
|
+
const chatsDir = path54.join(geminiTmpDir2, proj, "chats");
|
|
51004
50641
|
let files;
|
|
51005
50642
|
try {
|
|
51006
|
-
if (!
|
|
51007
|
-
files =
|
|
50643
|
+
if (!fs56.statSync(chatsDir).isDirectory()) continue;
|
|
50644
|
+
files = fs56.readdirSync(chatsDir);
|
|
51008
50645
|
} catch {
|
|
51009
50646
|
continue;
|
|
51010
50647
|
}
|
|
51011
50648
|
for (const f of files) {
|
|
51012
50649
|
if (!f.endsWith(".jsonl")) continue;
|
|
51013
|
-
out.push({ projectKey: proj, file:
|
|
50650
|
+
out.push({ projectKey: proj, file: path54.join(chatsDir, f) });
|
|
51014
50651
|
}
|
|
51015
50652
|
}
|
|
51016
50653
|
return out;
|
|
51017
50654
|
}
|
|
51018
50655
|
function loadGeminiCost(start, end, geminiTmpDir2) {
|
|
51019
50656
|
const acc = emptyGeminiAccumulator();
|
|
51020
|
-
if (!
|
|
50657
|
+
if (!fs56.existsSync(geminiTmpDir2)) return freezeGeminiCost(acc);
|
|
51021
50658
|
for (const { projectKey, file } of listGeminiSessionFiles2(geminiTmpDir2)) {
|
|
51022
50659
|
processGeminiCostFile(file, projectKey, start, end, acc);
|
|
51023
50660
|
}
|
|
@@ -51035,11 +50672,11 @@ function dimensionOfBlock(checkedBy, ruleName) {
|
|
|
51035
50672
|
}
|
|
51036
50673
|
function aggregateReportFromAudit(period, opts = {}) {
|
|
51037
50674
|
const now = opts.now ?? /* @__PURE__ */ new Date();
|
|
51038
|
-
const auditLogPath = opts.auditLogPath ??
|
|
51039
|
-
const claudeProjectsDir = opts.claudeProjectsDir ??
|
|
51040
|
-
const codexSessionsDir2 = opts.codexSessionsDir ??
|
|
51041
|
-
const geminiTmpDir2 = opts.geminiTmpDir ??
|
|
51042
|
-
const hasAuditFile =
|
|
50675
|
+
const auditLogPath = opts.auditLogPath ?? path54.join(os50.homedir(), ".node9", "audit.log");
|
|
50676
|
+
const claudeProjectsDir = opts.claudeProjectsDir ?? path54.join(os50.homedir(), ".claude", "projects");
|
|
50677
|
+
const codexSessionsDir2 = opts.codexSessionsDir ?? path54.join(os50.homedir(), ".codex", "sessions");
|
|
50678
|
+
const geminiTmpDir2 = opts.geminiTmpDir ?? path54.join(os50.homedir(), ".gemini", "tmp");
|
|
50679
|
+
const hasAuditFile = fs56.existsSync(auditLogPath);
|
|
51043
50680
|
const allEntries = opts.preloadedAuditEntries ?? parseAuditLog(auditLogPath);
|
|
51044
50681
|
const unackedDlp = allEntries.filter((e) => e.source === "response-dlp");
|
|
51045
50682
|
const { start, end } = getDateRange(period, now);
|
|
@@ -51748,8 +51385,8 @@ init_daemon();
|
|
|
51748
51385
|
init_startup_log();
|
|
51749
51386
|
init_daemon2();
|
|
51750
51387
|
import chalk14 from "chalk";
|
|
51751
|
-
import { spawn as
|
|
51752
|
-
import
|
|
51388
|
+
import { spawn as spawn5 } from "child_process";
|
|
51389
|
+
import fs57 from "fs";
|
|
51753
51390
|
var VALID_ACTIONS = "start | stop | restart | status | install | uninstall";
|
|
51754
51391
|
function registerDaemonCommand(program2) {
|
|
51755
51392
|
program2.command("daemon").description("Manage the local approval daemon").argument("[action]", `${VALID_ACTIONS} (default: start)`).option("-b, --background", "Start the daemon in the background (detached)").option(
|
|
@@ -51792,7 +51429,7 @@ function registerDaemonCommand(program2) {
|
|
|
51792
51429
|
}
|
|
51793
51430
|
const restartFd = openStartupLogFd();
|
|
51794
51431
|
recordStartupState("starting");
|
|
51795
|
-
const child =
|
|
51432
|
+
const child = spawn5(process.execPath, [process.argv[1], "daemon"], {
|
|
51796
51433
|
detached: true,
|
|
51797
51434
|
stdio: ["ignore", "ignore", restartFd ?? "ignore"],
|
|
51798
51435
|
env: { ...process.env, NODE9_AUTO_STARTED: "1" }
|
|
@@ -51804,7 +51441,7 @@ function registerDaemonCommand(program2) {
|
|
|
51804
51441
|
child.unref();
|
|
51805
51442
|
if (restartFd !== void 0) {
|
|
51806
51443
|
try {
|
|
51807
|
-
|
|
51444
|
+
fs57.closeSync(restartFd);
|
|
51808
51445
|
} catch {
|
|
51809
51446
|
}
|
|
51810
51447
|
}
|
|
@@ -51836,7 +51473,7 @@ function registerDaemonCommand(program2) {
|
|
|
51836
51473
|
const startupFd = openStartupLogFd();
|
|
51837
51474
|
try {
|
|
51838
51475
|
recordStartupState("starting");
|
|
51839
|
-
const child =
|
|
51476
|
+
const child = spawn5(process.execPath, [process.argv[1], "daemon"], {
|
|
51840
51477
|
detached: true,
|
|
51841
51478
|
// Capture the child's stderr: a module-load crash prints its stack there
|
|
51842
51479
|
// and dies before it can record anything itself.
|
|
@@ -51855,7 +51492,7 @@ function registerDaemonCommand(program2) {
|
|
|
51855
51492
|
} finally {
|
|
51856
51493
|
if (startupFd !== void 0) {
|
|
51857
51494
|
try {
|
|
51858
|
-
|
|
51495
|
+
fs57.closeSync(startupFd);
|
|
51859
51496
|
} catch {
|
|
51860
51497
|
}
|
|
51861
51498
|
}
|
|
@@ -51875,9 +51512,9 @@ init_agent_wiring();
|
|
|
51875
51512
|
init_sync();
|
|
51876
51513
|
init_service();
|
|
51877
51514
|
import chalk15 from "chalk";
|
|
51878
|
-
import
|
|
51879
|
-
import
|
|
51880
|
-
import
|
|
51515
|
+
import fs58 from "fs";
|
|
51516
|
+
import path55 from "path";
|
|
51517
|
+
import os51 from "os";
|
|
51881
51518
|
function printAgentSection(label2, hookPairs, wrapped) {
|
|
51882
51519
|
console.log(chalk15.bold(` ${label2}`));
|
|
51883
51520
|
for (const { name, present } of hookPairs) {
|
|
@@ -51958,20 +51595,20 @@ function registerStatusCommand(program2) {
|
|
|
51958
51595
|
console.log("");
|
|
51959
51596
|
const modeLabel = settings.mode === "audit" ? chalk15.blue("audit") : settings.mode === "strict" ? chalk15.red("strict") : chalk15.white("standard");
|
|
51960
51597
|
console.log(` Mode: ${modeLabel}`);
|
|
51961
|
-
const projectConfig =
|
|
51962
|
-
const globalConfig =
|
|
51598
|
+
const projectConfig = path55.join(process.cwd(), "node9.config.json");
|
|
51599
|
+
const globalConfig = path55.join(os51.homedir(), ".node9", "config.json");
|
|
51963
51600
|
console.log(
|
|
51964
|
-
` Local: ${
|
|
51601
|
+
` Local: ${fs58.existsSync(projectConfig) ? chalk15.green("Active (node9.config.json)") : chalk15.gray("Not present")}`
|
|
51965
51602
|
);
|
|
51966
51603
|
console.log(
|
|
51967
|
-
` Global: ${
|
|
51604
|
+
` Global: ${fs58.existsSync(globalConfig) ? chalk15.green("Active (~/.node9/config.json)") : chalk15.gray("Not present")}`
|
|
51968
51605
|
);
|
|
51969
51606
|
if (mergedConfig.policy.sandboxPaths.length > 0) {
|
|
51970
51607
|
console.log(
|
|
51971
51608
|
` Sandbox: ${chalk15.green(`${mergedConfig.policy.sandboxPaths.length} safe zones active`)}`
|
|
51972
51609
|
);
|
|
51973
51610
|
}
|
|
51974
|
-
const wiring = getAgentWiring(
|
|
51611
|
+
const wiring = getAgentWiring(os51.homedir()).filter((a) => a.present);
|
|
51975
51612
|
if (wiring.length > 0) {
|
|
51976
51613
|
console.log("");
|
|
51977
51614
|
console.log(chalk15.bold(" Agent Wiring:"));
|
|
@@ -52011,9 +51648,9 @@ init_shields();
|
|
|
52011
51648
|
init_service();
|
|
52012
51649
|
init_core();
|
|
52013
51650
|
import chalk16 from "chalk";
|
|
52014
|
-
import
|
|
52015
|
-
import
|
|
52016
|
-
import
|
|
51651
|
+
import fs59 from "fs";
|
|
51652
|
+
import path56 from "path";
|
|
51653
|
+
import os52 from "os";
|
|
52017
51654
|
import https6 from "https";
|
|
52018
51655
|
var DEFAULT_SHIELDS = ["bash-safe", "filesystem", "project-jail"];
|
|
52019
51656
|
function buildTelemetryPayload(agents, firstInstall) {
|
|
@@ -52099,16 +51736,16 @@ function registerInitCommand(program2) {
|
|
|
52099
51736
|
}
|
|
52100
51737
|
console.log("");
|
|
52101
51738
|
}
|
|
52102
|
-
const configPath =
|
|
52103
|
-
const isFirstInstall = !
|
|
52104
|
-
if (
|
|
51739
|
+
const configPath = path56.join(os52.homedir(), ".node9", "config.json");
|
|
51740
|
+
const isFirstInstall = !fs59.existsSync(configPath);
|
|
51741
|
+
if (fs59.existsSync(configPath) && !options.force) {
|
|
52105
51742
|
try {
|
|
52106
|
-
const existing = JSON.parse(
|
|
51743
|
+
const existing = JSON.parse(fs59.readFileSync(configPath, "utf-8"));
|
|
52107
51744
|
const settings = existing.settings ?? {};
|
|
52108
51745
|
if (settings.mode !== chosenMode) {
|
|
52109
51746
|
settings.mode = chosenMode;
|
|
52110
51747
|
existing.settings = settings;
|
|
52111
|
-
|
|
51748
|
+
fs59.writeFileSync(configPath, JSON.stringify(existing, null, 2) + "\n");
|
|
52112
51749
|
console.log(chalk16.green(`\u2705 Mode updated: ${chosenMode}`));
|
|
52113
51750
|
} else {
|
|
52114
51751
|
console.log(chalk16.blue(`\u2139\uFE0F Config already exists: ${configPath}`));
|
|
@@ -52121,9 +51758,9 @@ function registerInitCommand(program2) {
|
|
|
52121
51758
|
...DEFAULT_CONFIG,
|
|
52122
51759
|
settings: { ...DEFAULT_CONFIG.settings, mode: chosenMode }
|
|
52123
51760
|
};
|
|
52124
|
-
const dir =
|
|
52125
|
-
if (!
|
|
52126
|
-
|
|
51761
|
+
const dir = path56.dirname(configPath);
|
|
51762
|
+
if (!fs59.existsSync(dir)) fs59.mkdirSync(dir, { recursive: true });
|
|
51763
|
+
fs59.writeFileSync(configPath, JSON.stringify(configToSave, null, 2) + "\n");
|
|
52127
51764
|
console.log(chalk16.green(`\u2705 Config created: ${configPath}`));
|
|
52128
51765
|
console.log(chalk16.gray(` Mode: ${chosenMode}`));
|
|
52129
51766
|
}
|
|
@@ -52226,11 +51863,11 @@ init_agent_wiring();
|
|
|
52226
51863
|
init_setup();
|
|
52227
51864
|
init_hook_baseline();
|
|
52228
51865
|
import chalk17 from "chalk";
|
|
52229
|
-
import
|
|
51866
|
+
import fs60 from "fs";
|
|
52230
51867
|
var hasHookSurface = (a) => a.hooks.length > 0;
|
|
52231
51868
|
function backupForHeal(file) {
|
|
52232
51869
|
try {
|
|
52233
|
-
if (file &&
|
|
51870
|
+
if (file && fs60.existsSync(file)) fs60.copyFileSync(file, `${file}.node9-heal-bak`);
|
|
52234
51871
|
} catch {
|
|
52235
51872
|
}
|
|
52236
51873
|
}
|
|
@@ -52465,7 +52102,7 @@ init_cloud();
|
|
|
52465
52102
|
init_config();
|
|
52466
52103
|
import readline3 from "readline";
|
|
52467
52104
|
import chalk20 from "chalk";
|
|
52468
|
-
import { spawn as
|
|
52105
|
+
import { spawn as spawn6 } from "child_process";
|
|
52469
52106
|
import { execa as execa2 } from "execa";
|
|
52470
52107
|
init_provenance();
|
|
52471
52108
|
init_mcp_pin();
|
|
@@ -52594,7 +52231,7 @@ async function runMcpGateway(upstreamCommand, configName) {
|
|
|
52594
52231
|
const safeEnv = Object.fromEntries(
|
|
52595
52232
|
Object.entries(process.env).filter(([k]) => !UPSTREAM_INJECTOR_VARS.has(k))
|
|
52596
52233
|
);
|
|
52597
|
-
const child =
|
|
52234
|
+
const child = spawn6(executable, cmdArgs, {
|
|
52598
52235
|
stdio: ["pipe", "pipe", "inherit"],
|
|
52599
52236
|
// control stdin/stdout; inherit stderr
|
|
52600
52237
|
shell: false,
|
|
@@ -52971,15 +52608,15 @@ init_core();
|
|
|
52971
52608
|
init_daemon();
|
|
52972
52609
|
init_shields();
|
|
52973
52610
|
import readline4 from "readline";
|
|
52974
|
-
import fs63 from "fs";
|
|
52975
|
-
import os55 from "os";
|
|
52976
|
-
import path59 from "path";
|
|
52977
|
-
import { spawnSync as spawnSync4 } from "child_process";
|
|
52978
|
-
|
|
52979
|
-
// src/auth/egress-config.ts
|
|
52980
52611
|
import fs62 from "fs";
|
|
52981
52612
|
import os54 from "os";
|
|
52982
52613
|
import path58 from "path";
|
|
52614
|
+
import { spawnSync as spawnSync3 } from "child_process";
|
|
52615
|
+
|
|
52616
|
+
// src/auth/egress-config.ts
|
|
52617
|
+
import fs61 from "fs";
|
|
52618
|
+
import os53 from "os";
|
|
52619
|
+
import path57 from "path";
|
|
52983
52620
|
var DEFAULT_EGRESS = {
|
|
52984
52621
|
enabled: false,
|
|
52985
52622
|
mode: "review",
|
|
@@ -52988,12 +52625,12 @@ var DEFAULT_EGRESS = {
|
|
|
52988
52625
|
allowPrivate: true
|
|
52989
52626
|
};
|
|
52990
52627
|
function egressConfigPath() {
|
|
52991
|
-
return
|
|
52628
|
+
return path57.join(os53.homedir(), ".node9", "config.json");
|
|
52992
52629
|
}
|
|
52993
52630
|
function readEgressRawConfig() {
|
|
52994
52631
|
let text;
|
|
52995
52632
|
try {
|
|
52996
|
-
text =
|
|
52633
|
+
text = fs61.readFileSync(egressConfigPath(), "utf8");
|
|
52997
52634
|
} catch (err2) {
|
|
52998
52635
|
if (err2.code === "ENOENT") return {};
|
|
52999
52636
|
throw err2;
|
|
@@ -53008,8 +52645,8 @@ function readEgressRawConfig() {
|
|
|
53008
52645
|
}
|
|
53009
52646
|
function writeEgressRawConfig(config) {
|
|
53010
52647
|
const p = egressConfigPath();
|
|
53011
|
-
|
|
53012
|
-
|
|
52648
|
+
fs61.mkdirSync(path57.dirname(p), { recursive: true });
|
|
52649
|
+
fs61.writeFileSync(p, JSON.stringify(config, null, 2) + "\n", { mode: 384 });
|
|
53013
52650
|
}
|
|
53014
52651
|
function applyEgress(config, change) {
|
|
53015
52652
|
const policy = config.policy = config.policy ?? {};
|
|
@@ -53343,13 +52980,13 @@ function handleStatus() {
|
|
|
53343
52980
|
lines.push(`Active shields: ${activeShields.length > 0 ? activeShields.join(", ") : "none"}`);
|
|
53344
52981
|
lines.push(`Smart rules: ${config.policy.smartRules.length} loaded`);
|
|
53345
52982
|
lines.push(`DLP: ${config.policy.dlp?.enabled !== false ? "enabled" : "disabled"}`);
|
|
53346
|
-
const projectConfig =
|
|
53347
|
-
const globalConfig =
|
|
52983
|
+
const projectConfig = path58.join(process.cwd(), "node9.config.json");
|
|
52984
|
+
const globalConfig = path58.join(os54.homedir(), ".node9", "config.json");
|
|
53348
52985
|
lines.push(
|
|
53349
|
-
`Project config (node9.config.json): ${
|
|
52986
|
+
`Project config (node9.config.json): ${fs62.existsSync(projectConfig) ? "present" : "not found"}`
|
|
53350
52987
|
);
|
|
53351
52988
|
lines.push(
|
|
53352
|
-
`Global config (~/.node9/config.json): ${
|
|
52989
|
+
`Global config (~/.node9/config.json): ${fs62.existsSync(globalConfig) ? "present" : "not found"}`
|
|
53353
52990
|
);
|
|
53354
52991
|
return lines.join("\n");
|
|
53355
52992
|
}
|
|
@@ -53454,21 +53091,21 @@ function handleEgressDeny(args) {
|
|
|
53454
53091
|
addEgressHost("deny", host);
|
|
53455
53092
|
return `Denied egress to ${host} (deny always wins over allow).`;
|
|
53456
53093
|
}
|
|
53457
|
-
var GLOBAL_CONFIG_PATH =
|
|
53094
|
+
var GLOBAL_CONFIG_PATH = path58.join(os54.homedir(), ".node9", "config.json");
|
|
53458
53095
|
var APPROVER_CHANNELS = ["native", "browser", "cloud", "terminal"];
|
|
53459
53096
|
function readGlobalConfigRaw() {
|
|
53460
53097
|
try {
|
|
53461
|
-
if (
|
|
53462
|
-
return JSON.parse(
|
|
53098
|
+
if (fs62.existsSync(GLOBAL_CONFIG_PATH)) {
|
|
53099
|
+
return JSON.parse(fs62.readFileSync(GLOBAL_CONFIG_PATH, "utf-8"));
|
|
53463
53100
|
}
|
|
53464
53101
|
} catch {
|
|
53465
53102
|
}
|
|
53466
53103
|
return {};
|
|
53467
53104
|
}
|
|
53468
53105
|
function writeGlobalConfigRaw(data) {
|
|
53469
|
-
const dir =
|
|
53470
|
-
if (!
|
|
53471
|
-
|
|
53106
|
+
const dir = path58.dirname(GLOBAL_CONFIG_PATH);
|
|
53107
|
+
if (!fs62.existsSync(dir)) fs62.mkdirSync(dir, { recursive: true });
|
|
53108
|
+
fs62.writeFileSync(GLOBAL_CONFIG_PATH, JSON.stringify(data, null, 2) + "\n");
|
|
53472
53109
|
}
|
|
53473
53110
|
function handleApproverList() {
|
|
53474
53111
|
const config = getConfig();
|
|
@@ -53512,9 +53149,9 @@ function handleApproverSet(args) {
|
|
|
53512
53149
|
function handleAuditGet(args) {
|
|
53513
53150
|
const limit = Math.min(typeof args.limit === "number" ? args.limit : 20, 100);
|
|
53514
53151
|
const filter = typeof args.filter === "string" && args.filter !== "all" ? args.filter : null;
|
|
53515
|
-
const auditPath =
|
|
53516
|
-
if (!
|
|
53517
|
-
const rawLines =
|
|
53152
|
+
const auditPath = path58.join(os54.homedir(), ".node9", "audit.log");
|
|
53153
|
+
if (!fs62.existsSync(auditPath)) return "No audit log found.";
|
|
53154
|
+
const rawLines = fs62.readFileSync(auditPath, "utf-8").trim().split("\n").filter(Boolean);
|
|
53518
53155
|
const wanted = filter === "block" ? "deny" : filter;
|
|
53519
53156
|
const parsed = [];
|
|
53520
53157
|
for (const line of rawLines) {
|
|
@@ -53600,7 +53237,7 @@ function handleRuleAdd(args) {
|
|
|
53600
53237
|
return `Rule "${name}" added to ~/.node9/config.json \u2014 verdict: ${verdict} when ${field} matches "${pattern}"`;
|
|
53601
53238
|
}
|
|
53602
53239
|
function runCliCommand(subArgs) {
|
|
53603
|
-
const result =
|
|
53240
|
+
const result = spawnSync3(process.execPath, [process.argv[1], ...subArgs], {
|
|
53604
53241
|
encoding: "utf-8",
|
|
53605
53242
|
timeout: 6e4,
|
|
53606
53243
|
// Disable colors — stdout is piped (not a TTY), chalk auto-detects, but be explicit
|
|
@@ -53816,7 +53453,7 @@ function registerTrustCommand(program2) {
|
|
|
53816
53453
|
// src/cli/commands/mcp-pin.ts
|
|
53817
53454
|
init_mcp_pin();
|
|
53818
53455
|
import chalk23 from "chalk";
|
|
53819
|
-
import
|
|
53456
|
+
import fs63 from "fs";
|
|
53820
53457
|
|
|
53821
53458
|
// src/cli/commands/mcp-gateway-cmd.ts
|
|
53822
53459
|
init_mcp_wrap();
|
|
@@ -54024,7 +53661,7 @@ function registerMcpPinCommand(program2) {
|
|
|
54024
53661
|
let repoCorrupt = false;
|
|
54025
53662
|
if (found.source === "repo") {
|
|
54026
53663
|
try {
|
|
54027
|
-
const raw =
|
|
53664
|
+
const raw = fs63.readFileSync(found.path, "utf-8");
|
|
54028
53665
|
const parsed = JSON.parse(raw);
|
|
54029
53666
|
repoEntries = parsed.servers ?? {};
|
|
54030
53667
|
} catch {
|
|
@@ -54618,8 +54255,8 @@ import chalk29 from "chalk";
|
|
|
54618
54255
|
|
|
54619
54256
|
// src/ci-check/fetch.ts
|
|
54620
54257
|
var import_undici = __toESM(require_undici());
|
|
54621
|
-
import
|
|
54622
|
-
import
|
|
54258
|
+
import fs64 from "fs";
|
|
54259
|
+
import path59 from "path";
|
|
54623
54260
|
import { execFileSync as execFileSync2 } from "child_process";
|
|
54624
54261
|
var cachedGhToken;
|
|
54625
54262
|
function resolveGitHubToken() {
|
|
@@ -54702,7 +54339,7 @@ function parseRepoUrl(input) {
|
|
|
54702
54339
|
function isLocalPath(input) {
|
|
54703
54340
|
if (input.startsWith(".") || input.startsWith("/") || input.startsWith("~")) return true;
|
|
54704
54341
|
try {
|
|
54705
|
-
return
|
|
54342
|
+
return fs64.existsSync(input) && fs64.statSync(input).isDirectory();
|
|
54706
54343
|
} catch {
|
|
54707
54344
|
return false;
|
|
54708
54345
|
}
|
|
@@ -54817,10 +54454,10 @@ function readLocalTree(dir) {
|
|
|
54817
54454
|
const files = [];
|
|
54818
54455
|
const notes = [];
|
|
54819
54456
|
const add = (rel) => {
|
|
54820
|
-
const abs =
|
|
54457
|
+
const abs = path59.join(root, rel);
|
|
54821
54458
|
try {
|
|
54822
|
-
if (
|
|
54823
|
-
files.push({ path: rel, content:
|
|
54459
|
+
if (fs64.existsSync(abs) && fs64.statSync(abs).isFile()) {
|
|
54460
|
+
files.push({ path: rel, content: fs64.readFileSync(abs, "utf8") });
|
|
54824
54461
|
}
|
|
54825
54462
|
} catch {
|
|
54826
54463
|
}
|
|
@@ -54840,7 +54477,7 @@ function readLocalTree(dir) {
|
|
|
54840
54477
|
dirsVisited++;
|
|
54841
54478
|
let entries;
|
|
54842
54479
|
try {
|
|
54843
|
-
entries =
|
|
54480
|
+
entries = fs64.readdirSync(path59.join(root, relDir), { withFileTypes: true });
|
|
54844
54481
|
} catch {
|
|
54845
54482
|
return;
|
|
54846
54483
|
}
|
|
@@ -54861,11 +54498,11 @@ function readLocalTree(dir) {
|
|
|
54861
54498
|
`repo is large \u2014 some agent-surface files may be INCOMPLETE (capped at ${MAX_SURFACE_FILES} files / ${MAX_DIRS} dirs).`
|
|
54862
54499
|
);
|
|
54863
54500
|
for (const rel of matches) collect(rel);
|
|
54864
|
-
const wfDir =
|
|
54501
|
+
const wfDir = path59.join(root, WORKFLOW_DIR);
|
|
54865
54502
|
try {
|
|
54866
|
-
if (
|
|
54867
|
-
for (const name of
|
|
54868
|
-
if (/\.ya?ml$/.test(name)) add(
|
|
54503
|
+
if (fs64.existsSync(wfDir)) {
|
|
54504
|
+
for (const name of fs64.readdirSync(wfDir)) {
|
|
54505
|
+
if (/\.ya?ml$/.test(name)) add(path59.join(WORKFLOW_DIR, name));
|
|
54869
54506
|
}
|
|
54870
54507
|
}
|
|
54871
54508
|
} catch {
|
|
@@ -55170,7 +54807,7 @@ function severityFromScore(score) {
|
|
|
55170
54807
|
if (score >= 1) return "advisory";
|
|
55171
54808
|
return null;
|
|
55172
54809
|
}
|
|
55173
|
-
function analyzeWorkflow(
|
|
54810
|
+
function analyzeWorkflow(path71, content) {
|
|
55174
54811
|
let raw;
|
|
55175
54812
|
try {
|
|
55176
54813
|
raw = parseYaml(content) ?? {};
|
|
@@ -55296,7 +54933,7 @@ function analyzeWorkflow(path72, content) {
|
|
|
55296
54933
|
dimension: "workflows",
|
|
55297
54934
|
severity,
|
|
55298
54935
|
title,
|
|
55299
|
-
file:
|
|
54936
|
+
file: path71,
|
|
55300
54937
|
signals,
|
|
55301
54938
|
mitigations: mitigations.length ? mitigations : void 0,
|
|
55302
54939
|
fix: head === "root" && privileged ? "Do not check out the untrusted PR head into the workspace root under a privileged trigger (pull_request_target/workflow_run) \u2014 check out the base ref, or isolate the head in a subdir (--add-dir). Add an actor gate and scope the agent tools." : head === "root" ? "This runs under `pull_request` (fork PRs get a read-only token), so the head checkout is low-risk today \u2014 keep it on `pull_request` (not `pull_request_target`) and keep the actor gate + scoped tools." : "Add/verify an actor gate, scope the agent tools to read-only, and env-deny secrets. See Anthropic\u2019s claude-code-action security doc."
|
|
@@ -55372,7 +55009,7 @@ function evalAgentJob(job, wf, raw, untrustedTrigger, reusable) {
|
|
|
55372
55009
|
if (reusable && !loadedGun && SEVERITY_RANK2[severity] > SEVERITY_RANK2.medium) severity = "medium";
|
|
55373
55010
|
return { severity, secrets, injectable, canReadEnv };
|
|
55374
55011
|
}
|
|
55375
|
-
function analyzeWorkflowSecrets(
|
|
55012
|
+
function analyzeWorkflowSecrets(path71, content) {
|
|
55376
55013
|
let raw;
|
|
55377
55014
|
try {
|
|
55378
55015
|
raw = parseYaml(content) ?? {};
|
|
@@ -55392,7 +55029,7 @@ function analyzeWorkflowSecrets(path72, content) {
|
|
|
55392
55029
|
dimension: "data",
|
|
55393
55030
|
severity: worst.severity,
|
|
55394
55031
|
title: worst.severity === "advisory" ? "Secrets reachable by the agent \u2014 hardening" : "Exfiltratable secrets reachable by an injectable agent",
|
|
55395
|
-
file:
|
|
55032
|
+
file: path71,
|
|
55396
55033
|
signals: [
|
|
55397
55034
|
`agent can reach: ${worst.secrets.map((s) => s.name).join(", ")}`,
|
|
55398
55035
|
worst.injectable ? "the agent is externally triggerable (untrusted trigger, no gate)" : "gated / not externally triggerable \u2014 latent risk only",
|
|
@@ -55419,7 +55056,7 @@ function hookCommands(hooks) {
|
|
|
55419
55056
|
}
|
|
55420
55057
|
return out;
|
|
55421
55058
|
}
|
|
55422
|
-
function analyzeAgentConfig(
|
|
55059
|
+
function analyzeAgentConfig(path71, content) {
|
|
55423
55060
|
let cfg;
|
|
55424
55061
|
try {
|
|
55425
55062
|
cfg = JSON.parse(content);
|
|
@@ -55438,7 +55075,7 @@ function analyzeAgentConfig(path72, content) {
|
|
|
55438
55075
|
dimension: "toolRules",
|
|
55439
55076
|
severity: high ? "high" : "medium",
|
|
55440
55077
|
title: high ? "Agent hook runs UNPINNED/remote third-party code on every action" : "Agent hook runs third-party code in the agent hot path",
|
|
55441
|
-
file:
|
|
55078
|
+
file: path71,
|
|
55442
55079
|
signals: [
|
|
55443
55080
|
`hook command: \`${cmd.slice(0, 120)}\``,
|
|
55444
55081
|
remoteExec ? "fetch-and-run (curl|wget / pipe-to-shell) \u2014 unpinnable remote code execution on every contributor" : unpinned ? "unpinned \u2014 a compromised/yanked package = code execution on every contributor" : "pinned, but still a standing supply-chain dependency in the agent hot path"
|
|
@@ -55458,7 +55095,7 @@ function analyzeAgentConfig(path72, content) {
|
|
|
55458
55095
|
dimension: "toolRules",
|
|
55459
55096
|
severity: hasBackstop ? "medium" : "high",
|
|
55460
55097
|
title: hasBackstop ? "Committed agent config pre-authorizes broad tools" : "Committed agent config pre-authorizes broad tools with no deny backstop",
|
|
55461
|
-
file:
|
|
55098
|
+
file: path71,
|
|
55462
55099
|
signals: [
|
|
55463
55100
|
`broad allow(s): ${broad.slice(0, 5).join(", ")}`,
|
|
55464
55101
|
hasBackstop ? "a `deny` list backstops the broad allow" : "no `deny` entry covers Bash/Write/Edit \u2014 every contributor is pre-authorized for catastrophic tools"
|
|
@@ -55471,16 +55108,16 @@ function analyzeAgentConfig(path72, content) {
|
|
|
55471
55108
|
|
|
55472
55109
|
// src/ci-check/mcp.ts
|
|
55473
55110
|
init_dist();
|
|
55474
|
-
function analyzeMcp(
|
|
55111
|
+
function analyzeMcp(path71, content) {
|
|
55475
55112
|
let cfg;
|
|
55476
55113
|
try {
|
|
55477
55114
|
cfg = JSON.parse(content);
|
|
55478
55115
|
} catch {
|
|
55479
55116
|
return [];
|
|
55480
55117
|
}
|
|
55481
|
-
return analyzeMcpServers(cfg.mcpServers ?? {},
|
|
55118
|
+
return analyzeMcpServers(cfg.mcpServers ?? {}, path71);
|
|
55482
55119
|
}
|
|
55483
|
-
function analyzeMcpServers(servers,
|
|
55120
|
+
function analyzeMcpServers(servers, path71) {
|
|
55484
55121
|
const findings = [];
|
|
55485
55122
|
for (const [name, srv] of Object.entries(servers ?? {})) {
|
|
55486
55123
|
if (!srv || srv.disabled) continue;
|
|
@@ -55491,7 +55128,7 @@ function analyzeMcpServers(servers, path72) {
|
|
|
55491
55128
|
dimension: "mcp",
|
|
55492
55129
|
severity: "medium",
|
|
55493
55130
|
title: `MCP server "${name}" runs an unpinned executable`,
|
|
55494
|
-
file:
|
|
55131
|
+
file: path71,
|
|
55495
55132
|
signals: [`\`${argv.slice(0, 120)}\` \u2014 unversioned/@latest npx`],
|
|
55496
55133
|
fix: "Pin the MCP server package to an exact version so a PR (or a registry compromise) can\u2019t swap the toolchain."
|
|
55497
55134
|
});
|
|
@@ -55505,7 +55142,7 @@ function analyzeMcpServers(servers, path72) {
|
|
|
55505
55142
|
dimension: "mcp",
|
|
55506
55143
|
severity: "high",
|
|
55507
55144
|
title: `MCP server "${name}" has an inline credential`,
|
|
55508
|
-
file:
|
|
55145
|
+
file: path71,
|
|
55509
55146
|
signals: [
|
|
55510
55147
|
`env.${k} matches ${hit.patternName} \u2014 agent-reachable secret committed to the repo`
|
|
55511
55148
|
],
|
|
@@ -55519,7 +55156,7 @@ function analyzeMcpServers(servers, path72) {
|
|
|
55519
55156
|
|
|
55520
55157
|
// src/ci-check/codex.ts
|
|
55521
55158
|
import { parse as parseToml5 } from "smol-toml";
|
|
55522
|
-
function analyzeCodexConfig(
|
|
55159
|
+
function analyzeCodexConfig(path71, content) {
|
|
55523
55160
|
let cfg;
|
|
55524
55161
|
try {
|
|
55525
55162
|
cfg = parseToml5(content);
|
|
@@ -55527,7 +55164,7 @@ function analyzeCodexConfig(path72, content) {
|
|
|
55527
55164
|
return [];
|
|
55528
55165
|
}
|
|
55529
55166
|
const findings = [];
|
|
55530
|
-
findings.push(...analyzeMcpServers(cfg.mcp_servers ?? {},
|
|
55167
|
+
findings.push(...analyzeMcpServers(cfg.mcp_servers ?? {}, path71));
|
|
55531
55168
|
const sandbox = typeof cfg.sandbox_mode === "string" ? cfg.sandbox_mode : "";
|
|
55532
55169
|
const approval = typeof cfg.approval_policy === "string" ? cfg.approval_policy : "";
|
|
55533
55170
|
const fullAccess = /danger-full-access/i.test(sandbox);
|
|
@@ -55542,7 +55179,7 @@ function analyzeCodexConfig(path72, content) {
|
|
|
55542
55179
|
dimension: "toolRules",
|
|
55543
55180
|
severity: fullAccess ? "high" : "medium",
|
|
55544
55181
|
title: fullAccess ? "Codex config grants a full-access sandbox" : "Codex config never requires approval",
|
|
55545
|
-
file:
|
|
55182
|
+
file: path71,
|
|
55546
55183
|
signals,
|
|
55547
55184
|
fix: 'Commit a least-privilege Codex config: prefer `sandbox_mode = "read-only"` (or `"workspace-write"`) and `approval_policy = "on-request"`/`"on-failure"`. A repo-committed config applies to every contributor who runs Codex here.'
|
|
55548
55185
|
});
|
|
@@ -55598,10 +55235,10 @@ function decodeSuspiciousBase64(text) {
|
|
|
55598
55235
|
}
|
|
55599
55236
|
return out;
|
|
55600
55237
|
}
|
|
55601
|
-
function mk(severity, title, signals, fix,
|
|
55602
|
-
return { check: "CI-6", dimension: "instructions", severity, title, file:
|
|
55238
|
+
function mk(severity, title, signals, fix, path71) {
|
|
55239
|
+
return { check: "CI-6", dimension: "instructions", severity, title, file: path71, signals, fix };
|
|
55603
55240
|
}
|
|
55604
|
-
function analyzeInstructionFile(
|
|
55241
|
+
function analyzeInstructionFile(path71, content) {
|
|
55605
55242
|
const findings = [];
|
|
55606
55243
|
const decoded = decodeSuspiciousBase64(content);
|
|
55607
55244
|
if (TAG_CHARS.test(content))
|
|
@@ -55613,7 +55250,7 @@ function analyzeInstructionFile(path72, content) {
|
|
|
55613
55250
|
"contains Unicode tag characters (U+E0000\u2013E007F) \u2014 an invisible instruction-smuggling channel with no legitimate use in text"
|
|
55614
55251
|
],
|
|
55615
55252
|
"Remove the tag characters. Instruction files must be plain, reviewable text.",
|
|
55616
|
-
|
|
55253
|
+
path71
|
|
55617
55254
|
)
|
|
55618
55255
|
);
|
|
55619
55256
|
if (BIDI_OVERRIDE.test(content))
|
|
@@ -55625,7 +55262,7 @@ function analyzeInstructionFile(path72, content) {
|
|
|
55625
55262
|
"contains a bidi override (U+202D/U+202E) \u2014 a Trojan-Source technique that visually reorders text so a human reads something different from what the agent parses"
|
|
55626
55263
|
],
|
|
55627
55264
|
"Remove the bidi override characters.",
|
|
55628
|
-
|
|
55265
|
+
path71
|
|
55629
55266
|
)
|
|
55630
55267
|
);
|
|
55631
55268
|
else if (BIDI_EMBED_ISOLATE.test(content))
|
|
@@ -55637,7 +55274,7 @@ function analyzeInstructionFile(path72, content) {
|
|
|
55637
55274
|
"contains bidi embed/isolate characters (U+202A\u2013202C / U+2066\u20132069) \u2014 legitimate in right-to-left text, but confirm they are not being used to hide or reorder instructions"
|
|
55638
55275
|
],
|
|
55639
55276
|
"Confirm the bidi marks are legitimate RTL formatting; remove otherwise.",
|
|
55640
|
-
|
|
55277
|
+
path71
|
|
55641
55278
|
)
|
|
55642
55279
|
);
|
|
55643
55280
|
const zw = suspiciousZeroWidth(content);
|
|
@@ -55651,7 +55288,7 @@ function analyzeInstructionFile(path72, content) {
|
|
|
55651
55288
|
revealed ? "a zero-width character conceals a prompt-override directive that only appears once the hidden characters are stripped" : "a zero-width character splits a visible Latin word \u2014 a concealment technique (hides text from human review while the agent reads it as contiguous)"
|
|
55652
55289
|
],
|
|
55653
55290
|
"Remove the zero-width characters. Instruction files must be plain, reviewable text.",
|
|
55654
|
-
|
|
55291
|
+
path71
|
|
55655
55292
|
)
|
|
55656
55293
|
);
|
|
55657
55294
|
}
|
|
@@ -55667,7 +55304,7 @@ function analyzeInstructionFile(path72, content) {
|
|
|
55667
55304
|
`contains a prompt-override / role-impersonation directive (\`${m[0].slice(0, 60).trim()}\`)${ovEnc ? " \u2014 concealed in a base64 blob" : ""}`
|
|
55668
55305
|
],
|
|
55669
55306
|
"Remove the override text. An instruction file should not tell the agent to ignore its own rules.",
|
|
55670
|
-
|
|
55307
|
+
path71
|
|
55671
55308
|
)
|
|
55672
55309
|
);
|
|
55673
55310
|
}
|
|
@@ -55679,7 +55316,7 @@ function analyzeInstructionFile(path72, content) {
|
|
|
55679
55316
|
"Instruction directs the agent to fetch and run remote code",
|
|
55680
55317
|
[`\`${fo[0].slice(0, 70).trim()}\` \u2014 fetch-and-obey, outside an install/setup section`],
|
|
55681
55318
|
"Do not instruct the agent to pipe remote content into a shell; pin and vendor scripts instead.",
|
|
55682
|
-
|
|
55319
|
+
path71
|
|
55683
55320
|
)
|
|
55684
55321
|
);
|
|
55685
55322
|
}
|
|
@@ -55691,7 +55328,7 @@ function analyzeInstructionFile(path72, content) {
|
|
|
55691
55328
|
"Instruction points the agent at credential material",
|
|
55692
55329
|
[`references \`${sp[0].slice(0, 50).trim()}\` \u2014 directs the agent toward secrets`],
|
|
55693
55330
|
"Do not reference credential files or paths in agent instructions.",
|
|
55694
|
-
|
|
55331
|
+
path71
|
|
55695
55332
|
)
|
|
55696
55333
|
);
|
|
55697
55334
|
}
|
|
@@ -55703,7 +55340,7 @@ function analyzeInstructionFile(path72, content) {
|
|
|
55703
55340
|
"Instruction directs the agent to send data to an external endpoint",
|
|
55704
55341
|
[`\`${ex[0].slice(0, 70).trim()}\` \u2014 possible exfiltration directive`],
|
|
55705
55342
|
"Remove external post/upload directives from agent instructions.",
|
|
55706
|
-
|
|
55343
|
+
path71
|
|
55707
55344
|
)
|
|
55708
55345
|
);
|
|
55709
55346
|
}
|
|
@@ -56100,13 +55737,13 @@ function registerJailCommand(program2) {
|
|
|
56100
55737
|
// src/cli/commands/sandbox.ts
|
|
56101
55738
|
init_config();
|
|
56102
55739
|
import chalk32 from "chalk";
|
|
56103
|
-
import
|
|
56104
|
-
import
|
|
56105
|
-
import { spawnSync as
|
|
55740
|
+
import fs67 from "fs";
|
|
55741
|
+
import path62 from "path";
|
|
55742
|
+
import { spawnSync as spawnSync5 } from "child_process";
|
|
56106
55743
|
|
|
56107
55744
|
// src/sandbox/config.ts
|
|
56108
|
-
import
|
|
56109
|
-
import
|
|
55745
|
+
import fs65 from "fs";
|
|
55746
|
+
import path60 from "path";
|
|
56110
55747
|
import { parse as parseYaml2, stringify as stringifyYaml } from "yaml";
|
|
56111
55748
|
var SANDBOX_CONFIG_FILE = "node9.sandbox.yaml";
|
|
56112
55749
|
var FORBIDDEN_ENV = /* @__PURE__ */ new Set(["NODE9_API_KEY", "NODE9_API_URL"]);
|
|
@@ -56179,16 +55816,16 @@ function scaffoldSandboxYaml(agent) {
|
|
|
56179
55816
|
return header + stringifyYaml(defaultSandboxConfig(agent));
|
|
56180
55817
|
}
|
|
56181
55818
|
function sandboxConfigPath(cwd = process.cwd()) {
|
|
56182
|
-
return
|
|
55819
|
+
return path60.join(cwd, SANDBOX_CONFIG_FILE);
|
|
56183
55820
|
}
|
|
56184
55821
|
function loadSandboxConfig(cwd = process.cwd(), fallbackAgent = "claude") {
|
|
56185
55822
|
const p = sandboxConfigPath(cwd);
|
|
56186
|
-
if (!
|
|
55823
|
+
if (!fs65.existsSync(p)) {
|
|
56187
55824
|
throw new Error(`sandbox: ${SANDBOX_CONFIG_FILE} not found \u2014 run \`node9 sandbox new\` first.`);
|
|
56188
55825
|
}
|
|
56189
55826
|
let raw;
|
|
56190
55827
|
try {
|
|
56191
|
-
raw = parseYaml2(
|
|
55828
|
+
raw = parseYaml2(fs65.readFileSync(p, "utf-8"));
|
|
56192
55829
|
} catch (err2) {
|
|
56193
55830
|
throw new Error(
|
|
56194
55831
|
`sandbox: ${SANDBOX_CONFIG_FILE} is not valid YAML \u2014 ${err2.message}`
|
|
@@ -56247,16 +55884,16 @@ init_templates();
|
|
|
56247
55884
|
|
|
56248
55885
|
// src/sandbox/runtime.ts
|
|
56249
55886
|
init_templates();
|
|
56250
|
-
import
|
|
56251
|
-
import
|
|
56252
|
-
import
|
|
56253
|
-
import
|
|
56254
|
-
import { spawnSync as
|
|
55887
|
+
import fs66 from "fs";
|
|
55888
|
+
import os55 from "os";
|
|
55889
|
+
import path61 from "path";
|
|
55890
|
+
import crypto8 from "crypto";
|
|
55891
|
+
import { spawnSync as spawnSync4 } from "child_process";
|
|
56255
55892
|
function sandboxDataDir(cwd = process.cwd()) {
|
|
56256
|
-
return
|
|
55893
|
+
return path61.join(cwd, ".node9", "sandbox", "data");
|
|
56257
55894
|
}
|
|
56258
55895
|
function detectEngine(engine) {
|
|
56259
|
-
const r =
|
|
55896
|
+
const r = spawnSync4(engine, ["--version"], { encoding: "utf-8" });
|
|
56260
55897
|
if (r.status === 0 && typeof r.stdout === "string") {
|
|
56261
55898
|
return { available: true, version: r.stdout.trim() };
|
|
56262
55899
|
}
|
|
@@ -56264,7 +55901,7 @@ function detectEngine(engine) {
|
|
|
56264
55901
|
}
|
|
56265
55902
|
function agentCredentialsMount(agent) {
|
|
56266
55903
|
const rel = agent === "codex" ? ".codex/auth.json" : ".claude/.credentials.json";
|
|
56267
|
-
return { hostPath:
|
|
55904
|
+
return { hostPath: path61.join(os55.homedir(), rel), target: `/home/${RUN_AS_USER}/${rel}` };
|
|
56268
55905
|
}
|
|
56269
55906
|
function buildRunArgs(opts) {
|
|
56270
55907
|
const { config, workspaceHostPath, dataHostPath, allowlistHostPath, agentArgs } = opts;
|
|
@@ -56274,7 +55911,7 @@ function buildRunArgs(opts) {
|
|
|
56274
55911
|
args.push("-v", `${allowlistHostPath}:${ALLOWED_DOMAINS_PATH}:ro`);
|
|
56275
55912
|
if (config.node9.mountAgentCredentials) {
|
|
56276
55913
|
const creds = agentCredentialsMount(config.agent);
|
|
56277
|
-
if (
|
|
55914
|
+
if (fs66.existsSync(creds.hostPath)) {
|
|
56278
55915
|
args.push("-v", `${creds.hostPath}:${creds.target}`);
|
|
56279
55916
|
}
|
|
56280
55917
|
}
|
|
@@ -56289,33 +55926,33 @@ function buildRunArgs(opts) {
|
|
|
56289
55926
|
return args;
|
|
56290
55927
|
}
|
|
56291
55928
|
function imageContentHash(dockerfile, entrypoint) {
|
|
56292
|
-
return
|
|
55929
|
+
return crypto8.createHash("sha256").update(dockerfile).update("\0").update(entrypoint).digest("hex").slice(0, 16);
|
|
56293
55930
|
}
|
|
56294
55931
|
function sandboxBuildDir(cwd = process.cwd()) {
|
|
56295
|
-
return
|
|
55932
|
+
return path61.join(cwd, ".node9", "sandbox", "build");
|
|
56296
55933
|
}
|
|
56297
55934
|
function writeBuildContext(cwd, dockerfile, entrypoint) {
|
|
56298
55935
|
const dir = sandboxBuildDir(cwd);
|
|
56299
|
-
|
|
56300
|
-
|
|
56301
|
-
|
|
55936
|
+
fs66.mkdirSync(dir, { recursive: true });
|
|
55937
|
+
fs66.writeFileSync(path61.join(dir, "Dockerfile"), dockerfile);
|
|
55938
|
+
fs66.writeFileSync(path61.join(dir, "entrypoint.sh"), entrypoint);
|
|
56302
55939
|
return dir;
|
|
56303
55940
|
}
|
|
56304
55941
|
function writeAllowlist(cwd, hosts) {
|
|
56305
|
-
const dir =
|
|
56306
|
-
|
|
56307
|
-
const p =
|
|
56308
|
-
|
|
55942
|
+
const dir = path61.join(cwd, ".node9", "sandbox");
|
|
55943
|
+
fs66.mkdirSync(dir, { recursive: true });
|
|
55944
|
+
const p = path61.join(dir, "allowed-domains.txt");
|
|
55945
|
+
fs66.writeFileSync(p, hosts.join("\n") + "\n");
|
|
56309
55946
|
return p;
|
|
56310
55947
|
}
|
|
56311
55948
|
function resolveHomePath(p) {
|
|
56312
|
-
return p.startsWith("~") ?
|
|
55949
|
+
return p.startsWith("~") ? path61.join(os55.homedir(), p.slice(1)) : path61.resolve(p);
|
|
56313
55950
|
}
|
|
56314
55951
|
|
|
56315
55952
|
// src/cli/commands/sandbox.ts
|
|
56316
55953
|
function seedDataDirConfig(dataDir, sandbox) {
|
|
56317
|
-
|
|
56318
|
-
const configPath =
|
|
55954
|
+
fs67.mkdirSync(dataDir, { recursive: true });
|
|
55955
|
+
const configPath = path62.join(dataDir, "config.json");
|
|
56319
55956
|
const seed = {
|
|
56320
55957
|
settings: {
|
|
56321
55958
|
approvers: {
|
|
@@ -56326,7 +55963,7 @@ function seedDataDirConfig(dataDir, sandbox) {
|
|
|
56326
55963
|
}
|
|
56327
55964
|
}
|
|
56328
55965
|
};
|
|
56329
|
-
|
|
55966
|
+
fs67.writeFileSync(configPath, JSON.stringify(seed, null, 2), { mode: 384 });
|
|
56330
55967
|
}
|
|
56331
55968
|
function registerSandboxCommand(program2, version2) {
|
|
56332
55969
|
const node9Version2 = pinnedNode9Version(version2);
|
|
@@ -56334,13 +55971,13 @@ function registerSandboxCommand(program2, version2) {
|
|
|
56334
55971
|
cmd.command("new").description(`Scaffold ${SANDBOX_CONFIG_FILE} in this project`).option("--agent <agent>", "claude (default) or codex", "claude").action((opts) => {
|
|
56335
55972
|
const agent = opts.agent === "codex" ? "codex" : "claude";
|
|
56336
55973
|
const p = sandboxConfigPath();
|
|
56337
|
-
if (
|
|
55974
|
+
if (fs67.existsSync(p)) {
|
|
56338
55975
|
console.log(
|
|
56339
55976
|
chalk32.yellow(` ${SANDBOX_CONFIG_FILE} already exists \u2014 leaving it untouched.`)
|
|
56340
55977
|
);
|
|
56341
55978
|
return;
|
|
56342
55979
|
}
|
|
56343
|
-
|
|
55980
|
+
fs67.writeFileSync(p, scaffoldSandboxYaml(agent));
|
|
56344
55981
|
console.log(
|
|
56345
55982
|
chalk32.green(` \u2713 wrote ${SANDBOX_CONFIG_FILE}`) + chalk32.dim(` (agent: ${agent})`)
|
|
56346
55983
|
);
|
|
@@ -56380,20 +56017,20 @@ function registerSandboxCommand(program2, version2) {
|
|
|
56380
56017
|
const buildDir = writeBuildContext(cwd, dockerfile, entrypoint);
|
|
56381
56018
|
const hash = imageContentHash(dockerfile, entrypoint);
|
|
56382
56019
|
const image = sandbox.runtime.image;
|
|
56383
|
-
const hashFile =
|
|
56384
|
-
const lastHash =
|
|
56385
|
-
const imageExists =
|
|
56020
|
+
const hashFile = path62.join(sandboxBuildDir(cwd), ".image-hash");
|
|
56021
|
+
const lastHash = fs67.existsSync(hashFile) ? fs67.readFileSync(hashFile, "utf-8").trim() : "";
|
|
56022
|
+
const imageExists = spawnSync5(sandbox.runtime.engine, ["image", "inspect", image], { stdio: "ignore" }).status === 0;
|
|
56386
56023
|
const needBuild = sandbox.runtime.rebuild === "always" || !imageExists || sandbox.runtime.rebuild !== "never" && lastHash !== hash;
|
|
56387
56024
|
if (needBuild) {
|
|
56388
56025
|
console.log(chalk32.dim(` building ${image} \u2026`));
|
|
56389
|
-
const b =
|
|
56026
|
+
const b = spawnSync5(sandbox.runtime.engine, ["build", "-t", image, buildDir], {
|
|
56390
56027
|
stdio: "inherit"
|
|
56391
56028
|
});
|
|
56392
56029
|
if (b.status !== 0) {
|
|
56393
56030
|
console.error(chalk32.red(" build failed."));
|
|
56394
56031
|
process.exit(b.status ?? 1);
|
|
56395
56032
|
}
|
|
56396
|
-
|
|
56033
|
+
fs67.writeFileSync(hashFile, hash);
|
|
56397
56034
|
}
|
|
56398
56035
|
const dataDir = sandboxDataDir(cwd);
|
|
56399
56036
|
seedDataDirConfig(dataDir, sandbox);
|
|
@@ -56407,7 +56044,7 @@ function registerSandboxCommand(program2, version2) {
|
|
|
56407
56044
|
});
|
|
56408
56045
|
if (sandbox.node9.mountAgentCredentials) {
|
|
56409
56046
|
const creds = agentCredentialsMount(sandbox.agent);
|
|
56410
|
-
if (
|
|
56047
|
+
if (fs67.existsSync(creds.hostPath)) {
|
|
56411
56048
|
console.log(chalk32.dim(` mounting ${creds.hostPath} (agent credentials, rw)`));
|
|
56412
56049
|
} else {
|
|
56413
56050
|
console.log(
|
|
@@ -56419,24 +56056,24 @@ function registerSandboxCommand(program2, version2) {
|
|
|
56419
56056
|
chalk32.green(` \u{1F6E1}\uFE0F ${sandbox.agent} jailed \u2014 ${compiled.allow.length} hosts allowed
|
|
56420
56057
|
`)
|
|
56421
56058
|
);
|
|
56422
|
-
const r =
|
|
56059
|
+
const r = spawnSync5(sandbox.runtime.engine, runArgs, { stdio: "inherit" });
|
|
56423
56060
|
process.exit(r.status ?? 0);
|
|
56424
56061
|
});
|
|
56425
56062
|
cmd.command("tail").description("Stream the sandbox's audit log (host-side)").action(() => {
|
|
56426
|
-
const auditPath =
|
|
56427
|
-
if (!
|
|
56063
|
+
const auditPath = path62.join(sandboxDataDir(), "audit.log");
|
|
56064
|
+
if (!fs67.existsSync(auditPath)) {
|
|
56428
56065
|
console.log(chalk32.dim(" no sandbox audit yet."));
|
|
56429
56066
|
return;
|
|
56430
56067
|
}
|
|
56431
|
-
|
|
56068
|
+
spawnSync5("tail", ["-f", auditPath], { stdio: "inherit" });
|
|
56432
56069
|
});
|
|
56433
56070
|
cmd.command("logs").description("Dump the sandbox's audit log").action(() => {
|
|
56434
|
-
const auditPath =
|
|
56435
|
-
if (!
|
|
56071
|
+
const auditPath = path62.join(sandboxDataDir(), "audit.log");
|
|
56072
|
+
if (!fs67.existsSync(auditPath)) {
|
|
56436
56073
|
console.log(chalk32.dim(" no sandbox audit yet."));
|
|
56437
56074
|
return;
|
|
56438
56075
|
}
|
|
56439
|
-
process.stdout.write(
|
|
56076
|
+
process.stdout.write(fs67.readFileSync(auditPath, "utf-8"));
|
|
56440
56077
|
});
|
|
56441
56078
|
cmd.command("clean").description("Remove the sandbox image, build context, and data").action(() => {
|
|
56442
56079
|
const cwd = process.cwd();
|
|
@@ -56446,11 +56083,11 @@ function registerSandboxCommand(program2, version2) {
|
|
|
56446
56083
|
} catch {
|
|
56447
56084
|
}
|
|
56448
56085
|
if (sandbox) {
|
|
56449
|
-
|
|
56086
|
+
spawnSync5(sandbox.runtime.engine, ["image", "rm", "-f", sandbox.runtime.image], {
|
|
56450
56087
|
stdio: "ignore"
|
|
56451
56088
|
});
|
|
56452
56089
|
}
|
|
56453
|
-
|
|
56090
|
+
fs67.rmSync(path62.join(cwd, ".node9", "sandbox"), { recursive: true, force: true });
|
|
56454
56091
|
console.log(chalk32.green(" \u2713 sandbox image + build + data removed."));
|
|
56455
56092
|
});
|
|
56456
56093
|
}
|
|
@@ -56462,9 +56099,9 @@ init_litellm();
|
|
|
56462
56099
|
init_cost_gemini();
|
|
56463
56100
|
init_cost_codex();
|
|
56464
56101
|
import chalk33 from "chalk";
|
|
56465
|
-
import
|
|
56466
|
-
import
|
|
56467
|
-
import
|
|
56102
|
+
import fs68 from "fs";
|
|
56103
|
+
import path63 from "path";
|
|
56104
|
+
import os56 from "os";
|
|
56468
56105
|
function modelPrice(model) {
|
|
56469
56106
|
const t = pricingFor(model);
|
|
56470
56107
|
if (!t) return null;
|
|
@@ -56481,10 +56118,10 @@ function encodeProjectPath(projectPath) {
|
|
|
56481
56118
|
}
|
|
56482
56119
|
function sessionJsonlPath(projectPath, sessionId) {
|
|
56483
56120
|
const encoded = encodeProjectPath(projectPath);
|
|
56484
|
-
return
|
|
56121
|
+
return path63.join(os56.homedir(), ".claude", "projects", encoded, `${sessionId}.jsonl`);
|
|
56485
56122
|
}
|
|
56486
56123
|
function projectLabel(projectPath) {
|
|
56487
|
-
return projectPath.replace(
|
|
56124
|
+
return projectPath.replace(os56.homedir(), "~");
|
|
56488
56125
|
}
|
|
56489
56126
|
function parseHistoryLines(lines) {
|
|
56490
56127
|
const entries = [];
|
|
@@ -56553,10 +56190,10 @@ function parseSessionLines(lines) {
|
|
|
56553
56190
|
return { toolCalls, costUSD, hasSnapshot, modifiedFiles };
|
|
56554
56191
|
}
|
|
56555
56192
|
function loadAuditEntries(auditPath) {
|
|
56556
|
-
const aPath = auditPath ??
|
|
56193
|
+
const aPath = auditPath ?? path63.join(os56.homedir(), ".node9", "audit.log");
|
|
56557
56194
|
let raw;
|
|
56558
56195
|
try {
|
|
56559
|
-
raw =
|
|
56196
|
+
raw = fs68.readFileSync(aPath, "utf-8");
|
|
56560
56197
|
} catch {
|
|
56561
56198
|
return [];
|
|
56562
56199
|
}
|
|
@@ -56592,8 +56229,8 @@ function auditEntriesInWindow(entries, windowStart, windowEnd) {
|
|
|
56592
56229
|
return result;
|
|
56593
56230
|
}
|
|
56594
56231
|
function buildGeminiSessions(days, allAuditEntries) {
|
|
56595
|
-
const tmpDir =
|
|
56596
|
-
if (!
|
|
56232
|
+
const tmpDir = path63.join(os56.homedir(), ".gemini", "tmp");
|
|
56233
|
+
if (!fs68.existsSync(tmpDir)) return [];
|
|
56597
56234
|
const cutoff = days !== null ? (() => {
|
|
56598
56235
|
const d = /* @__PURE__ */ new Date();
|
|
56599
56236
|
d.setDate(d.getDate() - days);
|
|
@@ -56602,35 +56239,35 @@ function buildGeminiSessions(days, allAuditEntries) {
|
|
|
56602
56239
|
})() : null;
|
|
56603
56240
|
let slugDirs;
|
|
56604
56241
|
try {
|
|
56605
|
-
slugDirs =
|
|
56242
|
+
slugDirs = fs68.readdirSync(tmpDir);
|
|
56606
56243
|
} catch {
|
|
56607
56244
|
return [];
|
|
56608
56245
|
}
|
|
56609
56246
|
const summaries = [];
|
|
56610
56247
|
for (const slug2 of slugDirs) {
|
|
56611
|
-
const slugPath =
|
|
56248
|
+
const slugPath = path63.join(tmpDir, slug2);
|
|
56612
56249
|
try {
|
|
56613
|
-
if (!
|
|
56250
|
+
if (!fs68.statSync(slugPath).isDirectory()) continue;
|
|
56614
56251
|
} catch {
|
|
56615
56252
|
continue;
|
|
56616
56253
|
}
|
|
56617
|
-
let projectRoot =
|
|
56254
|
+
let projectRoot = path63.join(os56.homedir(), slug2);
|
|
56618
56255
|
try {
|
|
56619
|
-
projectRoot =
|
|
56256
|
+
projectRoot = fs68.readFileSync(path63.join(slugPath, ".project_root"), "utf-8").trim();
|
|
56620
56257
|
} catch {
|
|
56621
56258
|
}
|
|
56622
|
-
const chatsDir =
|
|
56623
|
-
if (!
|
|
56259
|
+
const chatsDir = path63.join(slugPath, "chats");
|
|
56260
|
+
if (!fs68.existsSync(chatsDir)) continue;
|
|
56624
56261
|
let chatFiles;
|
|
56625
56262
|
try {
|
|
56626
|
-
chatFiles =
|
|
56263
|
+
chatFiles = fs68.readdirSync(chatsDir).filter((f) => f.endsWith(".json"));
|
|
56627
56264
|
} catch {
|
|
56628
56265
|
continue;
|
|
56629
56266
|
}
|
|
56630
56267
|
for (const chatFile of chatFiles) {
|
|
56631
56268
|
let raw;
|
|
56632
56269
|
try {
|
|
56633
|
-
raw =
|
|
56270
|
+
raw = fs68.readFileSync(path63.join(chatsDir, chatFile), "utf-8");
|
|
56634
56271
|
} catch {
|
|
56635
56272
|
continue;
|
|
56636
56273
|
}
|
|
@@ -56710,8 +56347,8 @@ function buildGeminiSessions(days, allAuditEntries) {
|
|
|
56710
56347
|
return summaries;
|
|
56711
56348
|
}
|
|
56712
56349
|
function buildCodexSessions(days, allAuditEntries) {
|
|
56713
|
-
const sessionsBase =
|
|
56714
|
-
if (!
|
|
56350
|
+
const sessionsBase = path63.join(os56.homedir(), ".codex", "sessions");
|
|
56351
|
+
if (!fs68.existsSync(sessionsBase)) return [];
|
|
56715
56352
|
const cutoff = days !== null ? (() => {
|
|
56716
56353
|
const d = /* @__PURE__ */ new Date();
|
|
56717
56354
|
d.setDate(d.getDate() - days);
|
|
@@ -56720,29 +56357,29 @@ function buildCodexSessions(days, allAuditEntries) {
|
|
|
56720
56357
|
})() : null;
|
|
56721
56358
|
const jsonlFiles = [];
|
|
56722
56359
|
try {
|
|
56723
|
-
for (const year of
|
|
56724
|
-
const yearPath =
|
|
56360
|
+
for (const year of fs68.readdirSync(sessionsBase)) {
|
|
56361
|
+
const yearPath = path63.join(sessionsBase, year);
|
|
56725
56362
|
try {
|
|
56726
|
-
if (!
|
|
56363
|
+
if (!fs68.statSync(yearPath).isDirectory()) continue;
|
|
56727
56364
|
} catch {
|
|
56728
56365
|
continue;
|
|
56729
56366
|
}
|
|
56730
|
-
for (const month of
|
|
56731
|
-
const monthPath =
|
|
56367
|
+
for (const month of fs68.readdirSync(yearPath)) {
|
|
56368
|
+
const monthPath = path63.join(yearPath, month);
|
|
56732
56369
|
try {
|
|
56733
|
-
if (!
|
|
56370
|
+
if (!fs68.statSync(monthPath).isDirectory()) continue;
|
|
56734
56371
|
} catch {
|
|
56735
56372
|
continue;
|
|
56736
56373
|
}
|
|
56737
|
-
for (const day of
|
|
56738
|
-
const dayPath =
|
|
56374
|
+
for (const day of fs68.readdirSync(monthPath)) {
|
|
56375
|
+
const dayPath = path63.join(monthPath, day);
|
|
56739
56376
|
try {
|
|
56740
|
-
if (!
|
|
56377
|
+
if (!fs68.statSync(dayPath).isDirectory()) continue;
|
|
56741
56378
|
} catch {
|
|
56742
56379
|
continue;
|
|
56743
56380
|
}
|
|
56744
|
-
for (const file of
|
|
56745
|
-
if (file.endsWith(".jsonl")) jsonlFiles.push(
|
|
56381
|
+
for (const file of fs68.readdirSync(dayPath)) {
|
|
56382
|
+
if (file.endsWith(".jsonl")) jsonlFiles.push(path63.join(dayPath, file));
|
|
56746
56383
|
}
|
|
56747
56384
|
}
|
|
56748
56385
|
}
|
|
@@ -56754,7 +56391,7 @@ function buildCodexSessions(days, allAuditEntries) {
|
|
|
56754
56391
|
for (const filePath of jsonlFiles) {
|
|
56755
56392
|
let lines;
|
|
56756
56393
|
try {
|
|
56757
|
-
lines =
|
|
56394
|
+
lines = fs68.readFileSync(filePath, "utf-8").split("\n");
|
|
56758
56395
|
} catch {
|
|
56759
56396
|
continue;
|
|
56760
56397
|
}
|
|
@@ -56840,10 +56477,10 @@ function buildCodexSessions(days, allAuditEntries) {
|
|
|
56840
56477
|
return summaries;
|
|
56841
56478
|
}
|
|
56842
56479
|
function buildSessions(days, historyPath) {
|
|
56843
|
-
const hPath = historyPath ??
|
|
56480
|
+
const hPath = historyPath ?? path63.join(os56.homedir(), ".claude", "history.jsonl");
|
|
56844
56481
|
let historyRaw = "";
|
|
56845
56482
|
try {
|
|
56846
|
-
historyRaw =
|
|
56483
|
+
historyRaw = fs68.readFileSync(hPath, "utf-8");
|
|
56847
56484
|
} catch {
|
|
56848
56485
|
}
|
|
56849
56486
|
const cutoff = days !== null ? (() => {
|
|
@@ -56867,7 +56504,7 @@ function buildSessions(days, historyPath) {
|
|
|
56867
56504
|
const jsonlFile = sessionJsonlPath(entry.project, entry.sessionId);
|
|
56868
56505
|
let sessionLines = [];
|
|
56869
56506
|
try {
|
|
56870
|
-
sessionLines =
|
|
56507
|
+
sessionLines = fs68.readFileSync(jsonlFile, "utf-8").split("\n");
|
|
56871
56508
|
} catch {
|
|
56872
56509
|
}
|
|
56873
56510
|
const { toolCalls, costUSD, hasSnapshot, modifiedFiles } = parseSessionLines(sessionLines);
|
|
@@ -57261,12 +56898,12 @@ function registerSessionTaintCommand(program2) {
|
|
|
57261
56898
|
|
|
57262
56899
|
// src/cli/commands/skill-pin.ts
|
|
57263
56900
|
import chalk35 from "chalk";
|
|
57264
|
-
import
|
|
57265
|
-
import
|
|
57266
|
-
import
|
|
56901
|
+
import fs69 from "fs";
|
|
56902
|
+
import os57 from "os";
|
|
56903
|
+
import path64 from "path";
|
|
57267
56904
|
function wipeSkillSessions() {
|
|
57268
56905
|
try {
|
|
57269
|
-
|
|
56906
|
+
fs69.rmSync(path64.join(os57.homedir(), ".node9", "skill-sessions"), {
|
|
57270
56907
|
recursive: true,
|
|
57271
56908
|
force: true
|
|
57272
56909
|
});
|
|
@@ -57348,15 +56985,15 @@ function registerSkillPinCommand(program2) {
|
|
|
57348
56985
|
}
|
|
57349
56986
|
|
|
57350
56987
|
// src/cli/commands/decisions.ts
|
|
57351
|
-
import
|
|
57352
|
-
import
|
|
57353
|
-
import
|
|
56988
|
+
import fs70 from "fs";
|
|
56989
|
+
import os58 from "os";
|
|
56990
|
+
import path65 from "path";
|
|
57354
56991
|
import chalk36 from "chalk";
|
|
57355
|
-
var DECISIONS_FILE2 =
|
|
56992
|
+
var DECISIONS_FILE2 = path65.join(os58.homedir(), ".node9", "decisions.json");
|
|
57356
56993
|
function readDecisions() {
|
|
57357
56994
|
try {
|
|
57358
|
-
if (!
|
|
57359
|
-
const raw =
|
|
56995
|
+
if (!fs70.existsSync(DECISIONS_FILE2)) return {};
|
|
56996
|
+
const raw = fs70.readFileSync(DECISIONS_FILE2, "utf-8");
|
|
57360
56997
|
const parsed = JSON.parse(raw);
|
|
57361
56998
|
const out = {};
|
|
57362
56999
|
for (const [k, v] of Object.entries(parsed)) {
|
|
@@ -57368,11 +57005,11 @@ function readDecisions() {
|
|
|
57368
57005
|
}
|
|
57369
57006
|
}
|
|
57370
57007
|
function writeDecisions(d) {
|
|
57371
|
-
const dir =
|
|
57372
|
-
if (!
|
|
57008
|
+
const dir = path65.dirname(DECISIONS_FILE2);
|
|
57009
|
+
if (!fs70.existsSync(dir)) fs70.mkdirSync(dir, { recursive: true });
|
|
57373
57010
|
const tmp = `${DECISIONS_FILE2}.${process.pid}.tmp`;
|
|
57374
|
-
|
|
57375
|
-
|
|
57011
|
+
fs70.writeFileSync(tmp, JSON.stringify(d, null, 2));
|
|
57012
|
+
fs70.renameSync(tmp, DECISIONS_FILE2);
|
|
57376
57013
|
}
|
|
57377
57014
|
function registerDecisionsCommand(program2) {
|
|
57378
57015
|
const cmd = program2.command("decisions").description('Manage persistent "Always Allow" / "Always Deny" tool decisions');
|
|
@@ -57429,18 +57066,18 @@ Persistent decisions (${entries.length})
|
|
|
57429
57066
|
|
|
57430
57067
|
// src/cli/commands/dlp.ts
|
|
57431
57068
|
import chalk37 from "chalk";
|
|
57432
|
-
import
|
|
57433
|
-
import
|
|
57434
|
-
import
|
|
57435
|
-
var AUDIT_LOG =
|
|
57436
|
-
var RESOLVED_FILE =
|
|
57069
|
+
import fs71 from "fs";
|
|
57070
|
+
import path66 from "path";
|
|
57071
|
+
import os59 from "os";
|
|
57072
|
+
var AUDIT_LOG = path66.join(os59.homedir(), ".node9", "audit.log");
|
|
57073
|
+
var RESOLVED_FILE = path66.join(os59.homedir(), ".node9", "dlp-resolved.json");
|
|
57437
57074
|
var ANSI_RE = /\x1b(?:\[[0-9;?]*[a-zA-Z]|\][^\x07\x1b]*(?:\x07|\x1b\\)|[@-_])/g;
|
|
57438
57075
|
function stripAnsi(s) {
|
|
57439
57076
|
return s.replace(ANSI_RE, "");
|
|
57440
57077
|
}
|
|
57441
57078
|
function loadResolved() {
|
|
57442
57079
|
try {
|
|
57443
|
-
const raw = JSON.parse(
|
|
57080
|
+
const raw = JSON.parse(fs71.readFileSync(RESOLVED_FILE, "utf-8"));
|
|
57444
57081
|
return new Set(raw);
|
|
57445
57082
|
} catch {
|
|
57446
57083
|
return /* @__PURE__ */ new Set();
|
|
@@ -57448,13 +57085,13 @@ function loadResolved() {
|
|
|
57448
57085
|
}
|
|
57449
57086
|
function saveResolved(resolved) {
|
|
57450
57087
|
try {
|
|
57451
|
-
|
|
57088
|
+
fs71.writeFileSync(RESOLVED_FILE, JSON.stringify([...resolved], null, 2), { mode: 384 });
|
|
57452
57089
|
} catch {
|
|
57453
57090
|
}
|
|
57454
57091
|
}
|
|
57455
57092
|
function loadDlpFindings() {
|
|
57456
|
-
if (!
|
|
57457
|
-
return
|
|
57093
|
+
if (!fs71.existsSync(AUDIT_LOG)) return [];
|
|
57094
|
+
return fs71.readFileSync(AUDIT_LOG, "utf-8").split("\n").flatMap((line) => {
|
|
57458
57095
|
if (!line.trim()) return [];
|
|
57459
57096
|
try {
|
|
57460
57097
|
const e = JSON.parse(line);
|
|
@@ -57553,14 +57190,14 @@ function registerDlpCommand(program2) {
|
|
|
57553
57190
|
// src/cli/commands/mask.ts
|
|
57554
57191
|
init_dlp();
|
|
57555
57192
|
import chalk38 from "chalk";
|
|
57556
|
-
import
|
|
57557
|
-
import
|
|
57558
|
-
import
|
|
57193
|
+
import fs72 from "fs";
|
|
57194
|
+
import path67 from "path";
|
|
57195
|
+
import os60 from "os";
|
|
57559
57196
|
function findJsonlFiles(dir) {
|
|
57560
57197
|
const results = [];
|
|
57561
|
-
if (!
|
|
57562
|
-
for (const entry of
|
|
57563
|
-
const full =
|
|
57198
|
+
if (!fs72.existsSync(dir)) return results;
|
|
57199
|
+
for (const entry of fs72.readdirSync(dir, { withFileTypes: true })) {
|
|
57200
|
+
const full = path67.join(dir, entry.name);
|
|
57564
57201
|
if (entry.isDirectory()) results.push(...findJsonlFiles(full));
|
|
57565
57202
|
else if (entry.isFile() && entry.name.endsWith(".jsonl")) results.push(full);
|
|
57566
57203
|
}
|
|
@@ -57603,7 +57240,7 @@ function redactJson(obj) {
|
|
|
57603
57240
|
function processFile(filePath, dryRun) {
|
|
57604
57241
|
let raw;
|
|
57605
57242
|
try {
|
|
57606
|
-
raw =
|
|
57243
|
+
raw = fs72.readFileSync(filePath, "utf-8");
|
|
57607
57244
|
} catch {
|
|
57608
57245
|
return { redactedLines: 0, patterns: [] };
|
|
57609
57246
|
}
|
|
@@ -57635,14 +57272,14 @@ function processFile(filePath, dryRun) {
|
|
|
57635
57272
|
}
|
|
57636
57273
|
}
|
|
57637
57274
|
if (!dryRun && redactedLines > 0) {
|
|
57638
|
-
|
|
57275
|
+
fs72.writeFileSync(filePath, newLines.join("\n"), "utf-8");
|
|
57639
57276
|
}
|
|
57640
57277
|
return { redactedLines, patterns };
|
|
57641
57278
|
}
|
|
57642
57279
|
function processJsonFile(filePath, dryRun) {
|
|
57643
57280
|
let raw;
|
|
57644
57281
|
try {
|
|
57645
|
-
raw =
|
|
57282
|
+
raw = fs72.readFileSync(filePath, "utf-8");
|
|
57646
57283
|
} catch {
|
|
57647
57284
|
return { redactedLines: 0, patterns: [] };
|
|
57648
57285
|
}
|
|
@@ -57655,15 +57292,15 @@ function processJsonFile(filePath, dryRun) {
|
|
|
57655
57292
|
const { value, modified, found } = redactJson(parsed);
|
|
57656
57293
|
if (!modified) return { redactedLines: 0, patterns: [] };
|
|
57657
57294
|
if (!dryRun) {
|
|
57658
|
-
|
|
57295
|
+
fs72.writeFileSync(filePath, JSON.stringify(value, null, 2), "utf-8");
|
|
57659
57296
|
}
|
|
57660
57297
|
return { redactedLines: 1, patterns: found };
|
|
57661
57298
|
}
|
|
57662
57299
|
function findJsonFiles(dir) {
|
|
57663
57300
|
const results = [];
|
|
57664
|
-
if (!
|
|
57665
|
-
for (const entry of
|
|
57666
|
-
const full =
|
|
57301
|
+
if (!fs72.existsSync(dir)) return results;
|
|
57302
|
+
for (const entry of fs72.readdirSync(dir, { withFileTypes: true })) {
|
|
57303
|
+
const full = path67.join(dir, entry.name);
|
|
57667
57304
|
if (entry.isDirectory()) results.push(...findJsonFiles(full));
|
|
57668
57305
|
else if (entry.isFile() && entry.name.endsWith(".json")) results.push(full);
|
|
57669
57306
|
}
|
|
@@ -57672,9 +57309,9 @@ function findJsonFiles(dir) {
|
|
|
57672
57309
|
function registerMaskCommand(program2) {
|
|
57673
57310
|
program2.command("mask").description("Redact plaintext secrets from local AI session history files").option("--dry-run", "show what would be redacted without making changes").option("--all", "scan all history (default: last 30 days)").action(async (options) => {
|
|
57674
57311
|
const dryRun = !!options.dryRun;
|
|
57675
|
-
const home =
|
|
57676
|
-
const claudeDir =
|
|
57677
|
-
const geminiDir =
|
|
57312
|
+
const home = os60.homedir();
|
|
57313
|
+
const claudeDir = path67.join(home, ".claude", "projects");
|
|
57314
|
+
const geminiDir = path67.join(home, ".gemini", "tmp");
|
|
57678
57315
|
const allFiles = [
|
|
57679
57316
|
...findJsonlFiles(claudeDir).map((p) => ({ path: p, type: "jsonl" })),
|
|
57680
57317
|
...findJsonFiles(geminiDir).map((p) => ({ path: p, type: "json" }))
|
|
@@ -57682,7 +57319,7 @@ function registerMaskCommand(program2) {
|
|
|
57682
57319
|
const cutoff = options.all ? null : new Date(Date.now() - 30 * 24 * 60 * 60 * 1e3);
|
|
57683
57320
|
const filtered = cutoff ? allFiles.filter((f) => {
|
|
57684
57321
|
try {
|
|
57685
|
-
return
|
|
57322
|
+
return fs72.statSync(f.path).mtime >= cutoff;
|
|
57686
57323
|
} catch {
|
|
57687
57324
|
return false;
|
|
57688
57325
|
}
|
|
@@ -57738,7 +57375,7 @@ function registerMaskCommand(program2) {
|
|
|
57738
57375
|
// src/cli.ts
|
|
57739
57376
|
init_blast();
|
|
57740
57377
|
var { version } = JSON.parse(
|
|
57741
|
-
|
|
57378
|
+
fs75.readFileSync(path70.join(__dirname, "../package.json"), "utf-8")
|
|
57742
57379
|
);
|
|
57743
57380
|
var program = new Command();
|
|
57744
57381
|
program.name("node9").description("The Sudo Command for AI Agents").version(version);
|
|
@@ -57778,7 +57415,7 @@ program.command("signup").description("Create your node9 account / open the dash
|
|
|
57778
57415
|
console.log(" " + chalk40.dim("Opening ") + chalk40.cyan.underline(url));
|
|
57779
57416
|
const opener = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
|
|
57780
57417
|
try {
|
|
57781
|
-
const child =
|
|
57418
|
+
const child = spawn8(opener, [url], {
|
|
57782
57419
|
stdio: "ignore",
|
|
57783
57420
|
detached: true,
|
|
57784
57421
|
shell: process.platform === "win32"
|
|
@@ -57921,16 +57558,16 @@ program.command("uninstall").description("Remove all Node9 hooks and optionally
|
|
|
57921
57558
|
} catch {
|
|
57922
57559
|
}
|
|
57923
57560
|
if (options.purge) {
|
|
57924
|
-
const node9Dir =
|
|
57925
|
-
if (
|
|
57561
|
+
const node9Dir = path70.join(os63.homedir(), ".node9");
|
|
57562
|
+
if (fs75.existsSync(node9Dir)) {
|
|
57926
57563
|
const alsoSnapshots = undoLeftoverPaths().length > 0 ? ", old undo snapshots" : "";
|
|
57927
57564
|
const confirmed = await confirm3({
|
|
57928
57565
|
message: `Permanently delete ${node9Dir} (config, audit log, credentials${alsoSnapshots})?`,
|
|
57929
57566
|
default: false
|
|
57930
57567
|
});
|
|
57931
57568
|
if (confirmed) {
|
|
57932
|
-
|
|
57933
|
-
if (
|
|
57569
|
+
fs75.rmSync(node9Dir, { recursive: true });
|
|
57570
|
+
if (fs75.existsSync(node9Dir)) {
|
|
57934
57571
|
console.error(
|
|
57935
57572
|
chalk40.red("\n \u26A0\uFE0F ~/.node9/ could not be fully deleted \u2014 remove it manually.")
|
|
57936
57573
|
);
|
|
@@ -58066,7 +57703,7 @@ program.command("tail").description("Stream live agent activity to the terminal"
|
|
|
58066
57703
|
});
|
|
58067
57704
|
program.command("monitor").description("Live interactive dashboard \u2014 activity feed, approvals, security signals").action(async () => {
|
|
58068
57705
|
try {
|
|
58069
|
-
const dashboardPath =
|
|
57706
|
+
const dashboardPath = path70.join(__dirname, "dashboard.mjs");
|
|
58070
57707
|
const dynamicImport = new Function("id", "return import(id)");
|
|
58071
57708
|
const mod = await dynamicImport(`file://${dashboardPath}`);
|
|
58072
57709
|
await mod.startMonitor();
|
|
@@ -58104,14 +57741,14 @@ Claude Code spawns this command every ~300ms and writes a JSON payload to stdin.
|
|
|
58104
57741
|
Run "node9 addto claude" to register it as the statusLine.`
|
|
58105
57742
|
).argument("[subcommand]", 'Optional: "debug on" / "debug off" to toggle stdin logging').argument("[state]", 'on|off \u2014 used with "debug" subcommand').action(async (subcommand, state) => {
|
|
58106
57743
|
if (subcommand === "debug") {
|
|
58107
|
-
const flagFile =
|
|
57744
|
+
const flagFile = path70.join(os63.homedir(), ".node9", "hud-debug");
|
|
58108
57745
|
if (state === "on") {
|
|
58109
|
-
|
|
58110
|
-
|
|
57746
|
+
fs75.mkdirSync(path70.dirname(flagFile), { recursive: true });
|
|
57747
|
+
fs75.writeFileSync(flagFile, "");
|
|
58111
57748
|
console.log("HUD debug logging enabled \u2192 ~/.node9/hud-debug.log");
|
|
58112
57749
|
console.log("Tail it with: tail -f ~/.node9/hud-debug.log");
|
|
58113
57750
|
} else if (state === "off") {
|
|
58114
|
-
if (
|
|
57751
|
+
if (fs75.existsSync(flagFile)) fs75.unlinkSync(flagFile);
|
|
58115
57752
|
console.log("HUD debug logging disabled.");
|
|
58116
57753
|
} else {
|
|
58117
57754
|
console.error("Usage: node9 hud debug on|off");
|
|
@@ -58234,9 +57871,9 @@ if (process.argv[2] !== "daemon") {
|
|
|
58234
57871
|
const isCheckHook = process.argv[2] === "check";
|
|
58235
57872
|
if (isCheckHook) {
|
|
58236
57873
|
if (process.env.NODE9_DEBUG === "1" || getConfig().settings.enableHookLogDebug) {
|
|
58237
|
-
const logPath =
|
|
57874
|
+
const logPath = path70.join(os63.homedir(), ".node9", "hook-debug.log");
|
|
58238
57875
|
const msg = reason instanceof Error ? reason.message : String(reason);
|
|
58239
|
-
|
|
57876
|
+
fs75.appendFileSync(logPath, `[${(/* @__PURE__ */ new Date()).toISOString()}] UNHANDLED: ${msg}
|
|
58240
57877
|
`);
|
|
58241
57878
|
}
|
|
58242
57879
|
process.exit(0);
|