@great-arrow/cli 0.1.51 → 0.1.53
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +75 -18
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -9327,6 +9327,7 @@ function mapErrorToExitCode(error) {
|
|
|
9327
9327
|
return 2 /* NETWORK_ERROR */;
|
|
9328
9328
|
}
|
|
9329
9329
|
var FAILURE_HINTS = {
|
|
9330
|
+
permission: "Review this connection's scopes and workspace permissions at /account/connections.",
|
|
9330
9331
|
auth: "Run `gad login`, then reconnect the client: /mcp \u2192 great-arrow \u2192 reconnect.",
|
|
9331
9332
|
network: "Check this machine's connectivity (VPN, proxy, DNS), then try again.",
|
|
9332
9333
|
timeout: "The request timed out. Check connectivity and retry; if it persists, see https://www.greatarrow.ai/status.",
|
|
@@ -9337,9 +9338,11 @@ var FAILURE_HINTS = {
|
|
|
9337
9338
|
function classifyRequestFailure(error) {
|
|
9338
9339
|
const message = error instanceof Error ? error.message : String(error ?? "unknown error");
|
|
9339
9340
|
let kind = "unknown";
|
|
9340
|
-
if (
|
|
9341
|
+
if (/\b403\b/.test(message)) {
|
|
9342
|
+
kind = "permission";
|
|
9343
|
+
} else if (error instanceof CliError && error.code === 1 /* AUTH_ERROR */) {
|
|
9341
9344
|
kind = "auth";
|
|
9342
|
-
} else if (/\
|
|
9345
|
+
} else if (/\b401\b/.test(message)) {
|
|
9343
9346
|
kind = "auth";
|
|
9344
9347
|
} else if (/HTTP 5\d\d|Server error/i.test(message)) {
|
|
9345
9348
|
kind = "server";
|
|
@@ -9399,7 +9402,7 @@ function isNodeError(value) {
|
|
|
9399
9402
|
|
|
9400
9403
|
// src/lib/version.ts
|
|
9401
9404
|
var CLI_PACKAGE_NAME = "@great-arrow/cli";
|
|
9402
|
-
var CLI_VERSION = "0.1.
|
|
9405
|
+
var CLI_VERSION = "0.1.53";
|
|
9403
9406
|
var GAD_INSTALL_VERSION = "2026.08.08";
|
|
9404
9407
|
var GAD_INSTALL_MIN_VERSION = "2026.06.22";
|
|
9405
9408
|
var GAD_INSTALL_HEADER = "X-GAD-Install-Version";
|
|
@@ -10675,6 +10678,42 @@ function parseMcpPayload(result) {
|
|
|
10675
10678
|
}
|
|
10676
10679
|
}
|
|
10677
10680
|
|
|
10681
|
+
// ../../src/lib/observability/scrub-pii.ts
|
|
10682
|
+
var EMAIL_RE = /[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}/g;
|
|
10683
|
+
var SSN_RE = /\b\d{3}[-.\s]?\d{2}[-.\s]?\d{4}\b/g;
|
|
10684
|
+
var CREDIT_CARD_RE = /\b\d(?:[ -]?\d){12,18}\b/g;
|
|
10685
|
+
var PHONE_RE = /(?:\+?\b1[-.\s]?)?(?:\([2-9]\d{2}\)\s?|\b[2-9]\d{2}[-.\s]?)\d{3}[-.\s]?\d{4}\b/g;
|
|
10686
|
+
function luhnValid(candidate) {
|
|
10687
|
+
const digits2 = candidate.replace(/\D/g, "");
|
|
10688
|
+
if (digits2.length < 13 || digits2.length > 19) return false;
|
|
10689
|
+
let sum = 0;
|
|
10690
|
+
let double = false;
|
|
10691
|
+
for (let i = digits2.length - 1; i >= 0; i--) {
|
|
10692
|
+
let n = digits2.charCodeAt(i) - 48;
|
|
10693
|
+
if (double) {
|
|
10694
|
+
n *= 2;
|
|
10695
|
+
if (n > 9) n -= 9;
|
|
10696
|
+
}
|
|
10697
|
+
sum += n;
|
|
10698
|
+
double = !double;
|
|
10699
|
+
}
|
|
10700
|
+
return sum % 10 === 0;
|
|
10701
|
+
}
|
|
10702
|
+
var SECRET_TOKEN_RE = /\b(?:gad_[A-Za-z0-9_-]{20,}|sk-[A-Za-z0-9-]{20,}|Bearer\s+[A-Za-z0-9._~+/=-]{8,})\b/gi;
|
|
10703
|
+
var SENSITIVE_QUERY_VALUE_RE = /((?:^|[?&])(?:code|token|access_token|refresh_token|id_token|api_key|apikey|api_secret|apisecret|key|secret|client_secret|password|state)=)[^&#\s]+/gi;
|
|
10704
|
+
function scrubPiiFromText(s) {
|
|
10705
|
+
return s.replace(EMAIL_RE, "[redacted-email]").replace(
|
|
10706
|
+
CREDIT_CARD_RE,
|
|
10707
|
+
(m) => luhnValid(m) ? "[redacted-credit-card]" : m
|
|
10708
|
+
).replace(SSN_RE, "[redacted-ssn]").replace(PHONE_RE, "[redacted-phone]");
|
|
10709
|
+
}
|
|
10710
|
+
function scrubTelemetryText(s) {
|
|
10711
|
+
return scrubPiiFromText(s).replace(SENSITIVE_QUERY_VALUE_RE, "$1[redacted]").replace(
|
|
10712
|
+
SECRET_TOKEN_RE,
|
|
10713
|
+
(match) => match.toLowerCase().startsWith("bearer ") ? "Bearer [redacted]" : "[redacted-secret]"
|
|
10714
|
+
);
|
|
10715
|
+
}
|
|
10716
|
+
|
|
10678
10717
|
// src/lib/telemetry.ts
|
|
10679
10718
|
var MAX_EVENTS_PER_PROCESS = 20;
|
|
10680
10719
|
var MAX_STRING = 240;
|
|
@@ -10682,12 +10721,14 @@ var sent = 0;
|
|
|
10682
10721
|
function enabled() {
|
|
10683
10722
|
if (process.env.GAD_TELEMETRY === "0" || process.env.GAD_TELEMETRY === "false")
|
|
10684
10723
|
return false;
|
|
10685
|
-
|
|
10724
|
+
if (process.env.GAD_TELEMETRY === "1" || process.env.GAD_TELEMETRY === "true")
|
|
10725
|
+
return true;
|
|
10726
|
+
return void 0;
|
|
10686
10727
|
}
|
|
10687
10728
|
function redact(value, depth = 0) {
|
|
10688
10729
|
if (depth > 3) return "[redacted]";
|
|
10689
10730
|
if (typeof value === "string") {
|
|
10690
|
-
const scrubbed = value.replace(/Bearer\s+\S+/gi, "Bearer [redacted]").replace(
|
|
10731
|
+
const scrubbed = scrubTelemetryText(value).replace(/Bearer\s+\S+/gi, "Bearer [redacted]").replace(
|
|
10691
10732
|
/(token|secret|password|authorization)[=:]\s*[^\s,]+/gi,
|
|
10692
10733
|
"$1=[redacted]"
|
|
10693
10734
|
);
|
|
@@ -10706,7 +10747,9 @@ function redact(value, depth = 0) {
|
|
|
10706
10747
|
}
|
|
10707
10748
|
async function captureCliEvent(input) {
|
|
10708
10749
|
if (sent >= MAX_EVENTS_PER_PROCESS) return;
|
|
10709
|
-
|
|
10750
|
+
const envConsent = enabled();
|
|
10751
|
+
if (envConsent === false) return;
|
|
10752
|
+
if (envConsent === void 0) {
|
|
10710
10753
|
try {
|
|
10711
10754
|
const config = await loadConfig();
|
|
10712
10755
|
if (config.telemetry_enabled !== true) return;
|
|
@@ -10714,28 +10757,33 @@ async function captureCliEvent(input) {
|
|
|
10714
10757
|
return;
|
|
10715
10758
|
}
|
|
10716
10759
|
}
|
|
10760
|
+
if (sent >= MAX_EVENTS_PER_PROCESS) return;
|
|
10717
10761
|
sent++;
|
|
10718
10762
|
const error = input.error instanceof Error ? { name: input.error.name, message: input.error.message } : input.error;
|
|
10719
10763
|
const payload = {
|
|
10720
10764
|
platform: "cli",
|
|
10721
10765
|
event: input.name,
|
|
10722
10766
|
level: input.error ? "error" : "info",
|
|
10723
|
-
message: error && typeof error === "object" && "message" in error ? String(error.message) : input.name,
|
|
10767
|
+
message: error && typeof error === "object" && "message" in error ? redact(String(error.message)) : redact(input.name),
|
|
10724
10768
|
version: process.env.GAD_CLI_VERSION,
|
|
10725
10769
|
code: input.context?.code,
|
|
10726
10770
|
context: redact(input.context ?? {}),
|
|
10727
10771
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
10728
10772
|
};
|
|
10729
10773
|
try {
|
|
10730
|
-
await fetch(
|
|
10731
|
-
|
|
10732
|
-
|
|
10733
|
-
|
|
10734
|
-
|
|
10735
|
-
|
|
10736
|
-
|
|
10737
|
-
|
|
10738
|
-
|
|
10774
|
+
const response = await fetch(
|
|
10775
|
+
`${input.apiUrl.replace(/\/$/, "")}/api/telemetry`,
|
|
10776
|
+
{
|
|
10777
|
+
method: "POST",
|
|
10778
|
+
headers: {
|
|
10779
|
+
"content-type": "application/json"
|
|
10780
|
+
},
|
|
10781
|
+
body: JSON.stringify(redact(payload)),
|
|
10782
|
+
signal: AbortSignal.timeout(1500)
|
|
10783
|
+
}
|
|
10784
|
+
);
|
|
10785
|
+
if (!response.ok)
|
|
10786
|
+
debugSwallow("telemetry.send", new Error(`HTTP ${response.status}`));
|
|
10739
10787
|
} catch (err) {
|
|
10740
10788
|
debugSwallow("telemetry.send", err);
|
|
10741
10789
|
}
|
|
@@ -10921,7 +10969,14 @@ var GadClient = class {
|
|
|
10921
10969
|
}
|
|
10922
10970
|
const status = response.status;
|
|
10923
10971
|
const body = await response.text().catch(() => "");
|
|
10924
|
-
if (status ===
|
|
10972
|
+
if (status === 403) {
|
|
10973
|
+
throw new CliError(
|
|
10974
|
+
"Permission denied (HTTP 403).",
|
|
10975
|
+
1 /* AUTH_ERROR */,
|
|
10976
|
+
"Check this connection's scopes and workspace permissions at /account/connections."
|
|
10977
|
+
);
|
|
10978
|
+
}
|
|
10979
|
+
if (status === 401) {
|
|
10925
10980
|
throw authError(
|
|
10926
10981
|
`Authentication failed (HTTP ${status}).`,
|
|
10927
10982
|
"Run 'gad login' to re-authenticate, or check your GAD_TOKEN."
|
|
@@ -14210,7 +14265,8 @@ function codexTransportFields(body) {
|
|
|
14210
14265
|
|
|
14211
14266
|
// src/lib/mcp-doctor.ts
|
|
14212
14267
|
var MCP_FAILURE_MESSAGE = {
|
|
14213
|
-
auth: "MCP rejected this machine's credential (401
|
|
14268
|
+
auth: "MCP rejected this machine's credential (401)",
|
|
14269
|
+
permission: "MCP denied this connection's scopes or workspace access (403)",
|
|
14214
14270
|
network: "Could not reach the MCP endpoint",
|
|
14215
14271
|
timeout: "The MCP endpoint did not answer in time",
|
|
14216
14272
|
server: "The MCP endpoint returned a server error",
|
|
@@ -14219,6 +14275,7 @@ var MCP_FAILURE_MESSAGE = {
|
|
|
14219
14275
|
};
|
|
14220
14276
|
var MCP_STATUS_WORD = {
|
|
14221
14277
|
auth: "unauthenticated",
|
|
14278
|
+
permission: "forbidden",
|
|
14222
14279
|
network: "unreachable",
|
|
14223
14280
|
timeout: "timeout",
|
|
14224
14281
|
server: "server error",
|