pushary 1.9.93 → 1.9.94
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/CHANGELOG.md +6 -0
- package/dist/{api-QUARGXSY.js → api-QBIRIMGU.js} +10 -10
- package/dist/bin/pushary-bell-hook.js +26 -26
- package/dist/bin/pushary-bell.js +10 -10
- package/dist/bin/pushary-claude.js +27 -27
- package/dist/bin/pushary-clean.js +34 -34
- package/dist/bin/pushary-codex-bridge.js +21 -21
- package/dist/bin/pushary-codex-hook.js +34 -32
- package/dist/bin/pushary-codex-session.js +8 -8
- package/dist/bin/pushary-codex.js +14 -14
- package/dist/bin/pushary-connect.js +27 -27
- package/dist/bin/pushary-cowork.js +5 -5
- package/dist/bin/pushary-daemon.js +39 -39
- package/dist/bin/pushary-disconnect.js +26 -26
- package/dist/bin/pushary-display-hook.js +17 -17
- package/dist/bin/pushary-doctor.js +42 -42
- package/dist/bin/pushary-elicitation-hook.js +26 -26
- package/dist/bin/pushary-gemini-bridge.js +15 -15
- package/dist/bin/pushary-gemini-hook.js +28 -28
- package/dist/bin/pushary-hook.js +30 -30
- package/dist/bin/pushary-login.js +20 -20
- package/dist/bin/pushary-logout.js +25 -25
- package/dist/bin/pushary-mcp.js +11 -11
- package/dist/bin/pushary-mode.js +15 -15
- package/dist/bin/pushary-notification-hook.js +25 -25
- package/dist/bin/pushary-opencode-hook.js +27 -27
- package/dist/bin/pushary-permission-denied-hook.js +30 -30
- package/dist/bin/pushary-permission-hook.js +30 -30
- package/dist/bin/pushary-post-hook.js +25 -25
- package/dist/bin/pushary-prompt-hook.js +25 -25
- package/dist/bin/pushary-session-end-hook.js +27 -27
- package/dist/bin/pushary-session-start-hook.js +35 -35
- package/dist/bin/pushary-setup.js +48 -48
- package/dist/bin/pushary-stats.js +5 -5
- package/dist/bin/pushary-status.js +32 -32
- package/dist/bin/pushary-stop-hook.js +25 -25
- package/dist/bin/pushary-stopfailure-hook.js +25 -25
- package/dist/bin/pushary-suggestions.js +15 -15
- package/dist/bin/pushary-transcript-register.js +18 -18
- package/dist/bin/pushary-transcripts.js +26 -26
- package/dist/bin/pushary-upgrade.js +40 -40
- package/dist/bin/pushary-wait.js +15 -15
- package/dist/bin/pushary.js +7 -7
- package/dist/{chunk-OFQJHWAS.js → chunk-2TA5UKNE.js} +10 -10
- package/dist/{chunk-3CJFBWID.js → chunk-3DASOC3M.js} +3 -3
- package/dist/{chunk-7YB2XRY7.js → chunk-3GZCHFYV.js} +3 -3
- package/dist/{chunk-ANDG4PUV.js → chunk-4GNFBBE6.js} +6 -6
- package/dist/{chunk-2FL5PLA4.js → chunk-4N6MND55.js} +2 -2
- package/dist/{chunk-XDWJX7LT.js → chunk-4YPTEVZD.js} +3 -3
- package/dist/{chunk-7PQ66CB3.js → chunk-4YSFD4RY.js} +1 -1
- package/dist/{chunk-NZKH2RMQ.js → chunk-5M6ASRLB.js} +1 -1
- package/dist/{chunk-GLA6MCOG.js → chunk-5QSPRDUO.js} +1 -1
- package/dist/{chunk-ONRA5ON4.js → chunk-5ZBYW7IO.js} +1 -1
- package/dist/{chunk-RFP4Q5I3.js → chunk-6SN6L5YT.js} +11 -11
- package/dist/{chunk-4HQTZQ4D.js → chunk-6YX4VASU.js} +2 -2
- package/dist/{chunk-NPH4DJAU.js → chunk-7Y3AQNHV.js} +5 -5
- package/dist/{chunk-JZ2MRWC4.js → chunk-AEKTC2DX.js} +3 -3
- package/dist/{chunk-DV7LLH25.js → chunk-AMPF5FAS.js} +1 -1
- package/dist/{chunk-UGGACQMD.js → chunk-ANZECRZO.js} +3 -3
- package/dist/{chunk-RXAQOAZI.js → chunk-AUIRBCYE.js} +3 -3
- package/dist/{chunk-ATWH6TGY.js → chunk-BE4KMA7N.js} +18 -15
- package/dist/{chunk-UHS3JZLN.js → chunk-BOHUB5VP.js} +2 -2
- package/dist/{chunk-CFD3IESN.js → chunk-CA2V7TKX.js} +6 -6
- package/dist/{chunk-4PD7FP55.js → chunk-CDIVGMBR.js} +2 -2
- package/dist/{chunk-MSJXRN22.js → chunk-CS2C7S5L.js} +5 -5
- package/dist/{chunk-HUNGCBCF.js → chunk-E2WYLZIL.js} +3 -3
- package/dist/{chunk-SPPMPM7F.js → chunk-EFCHGKAD.js} +1 -1
- package/dist/{chunk-CQMY74I2.js → chunk-ERQD5UVH.js} +7 -7
- package/dist/{chunk-PS2K6ZQ3.js → chunk-F74RBPJY.js} +6 -6
- package/dist/{chunk-NDPOESVW.js → chunk-FQZSKWWL.js} +1 -1
- package/dist/{chunk-3JVV6PMG.js → chunk-FSMR6GJT.js} +5 -5
- package/dist/{chunk-Y7AX6BS4.js → chunk-GPGLRSGY.js} +3 -3
- package/dist/{chunk-7VJ7PEI3.js → chunk-HHE7ONVT.js} +4 -4
- package/dist/{chunk-A2FDS7E3.js → chunk-HHKBWPXA.js} +5 -5
- package/dist/{chunk-7GFWYFLO.js → chunk-HRFOVTCQ.js} +10 -10
- package/dist/{chunk-FTJ5DQL7.js → chunk-HZQIC3DG.js} +2 -2
- package/dist/{chunk-NPZ5L2WQ.js → chunk-IB5MLSE3.js} +1 -1
- package/dist/{chunk-CSUO5YJG.js → chunk-IMNXYNBJ.js} +2 -2
- package/dist/{chunk-76ROCOWD.js → chunk-JCZ7WE5G.js} +7 -7
- package/dist/{chunk-N7CPX5S5.js → chunk-JJ2AA3N6.js} +5 -5
- package/dist/{chunk-VMIWR724.js → chunk-JLWI2HZF.js} +1 -1
- package/dist/{chunk-OLMKZINV.js → chunk-K3E3NFTT.js} +6 -6
- package/dist/{chunk-5V2YDO4U.js → chunk-K56A3LSA.js} +4 -4
- package/dist/{chunk-X3AHEUQ5.js → chunk-KH3QOWTE.js} +3 -3
- package/dist/{chunk-KJ752DUH.js → chunk-KXCSF2IK.js} +6 -6
- package/dist/{chunk-CHVXLS7U.js → chunk-LFIFIIMK.js} +2 -2
- package/dist/{chunk-NHGOCUX7.js → chunk-MC7I3SZW.js} +1 -1
- package/dist/{chunk-7DOSRSRU.js → chunk-OSDL6OND.js} +6 -6
- package/dist/{chunk-XTNCXIYR.js → chunk-OWCWJBGW.js} +4 -4
- package/dist/{chunk-BETKU76V.js → chunk-PGCDYBKG.js} +3 -3
- package/dist/{chunk-2BVVMWVF.js → chunk-QNFDU72D.js} +1 -1
- package/dist/{chunk-YLCNW7YN.js → chunk-QR7RXGNF.js} +2 -2
- package/dist/{chunk-LTMMFZHG.js → chunk-QU2G6MM7.js} +1 -1
- package/dist/{chunk-66VEUAN5.js → chunk-QVCDU4NT.js} +1 -1
- package/dist/{chunk-YT3ENXBT.js → chunk-QYP4EEDA.js} +2 -2
- package/dist/{chunk-UZRKR6NZ.js → chunk-RCDCFFG4.js} +3 -3
- package/dist/{chunk-LANGH7UF.js → chunk-REV2QMUD.js} +4 -4
- package/dist/{chunk-V3LBQFQM.js → chunk-RGMS5EDS.js} +1 -1
- package/dist/{chunk-SR44ZNZF.js → chunk-SKYDYDGX.js} +5 -5
- package/dist/{chunk-JJWZIPDL.js → chunk-SSXMA23D.js} +4 -4
- package/dist/{chunk-H4MIOBC6.js → chunk-SV6WE5QB.js} +2 -2
- package/dist/{chunk-V7TNHTHH.js → chunk-TYHOBIDF.js} +1 -1
- package/dist/{chunk-5TQC2LS6.js → chunk-UC6IZRXP.js} +4 -4
- package/dist/{chunk-2BXWBKVN.js → chunk-UFT4R4V7.js} +3 -3
- package/dist/{chunk-OC47FGOY.js → chunk-VDBRLNW7.js} +1 -1
- package/dist/{chunk-373552A3.js → chunk-X5DCL36E.js} +4 -4
- package/dist/{chunk-HALVTC2N.js → chunk-X7GKDLW7.js} +5 -5
- package/dist/{chunk-WW4OMRZX.js → chunk-XASOD3XX.js} +1 -1
- package/dist/{chunk-OMN5UCMW.js → chunk-XERTD7VZ.js} +520 -40
- package/dist/{chunk-CO6TQ44W.js → chunk-YQCRX4T6.js} +3 -3
- package/dist/{chunk-RXQT5FTX.js → chunk-Z4JULPCS.js} +1 -1
- package/dist/{chunk-UNPDFIPQ.js → chunk-Z5QJONDX.js} +2 -2
- package/dist/{chunk-PFHU3CW4.js → chunk-ZZ5QZ24I.js} +1 -1
- package/dist/{codex-app-cards-switch-XP2H2CZO.js → codex-app-cards-switch-QEMMPNK3.js} +11 -11
- package/dist/{codex-desktop-launch-QRFE2GHZ.js → codex-desktop-launch-LNIZPXSJ.js} +1 -1
- package/dist/{codex-session-launch-EUUWALWW.js → codex-session-launch-IZ4IQDS7.js} +18 -18
- package/dist/{config-WBDMUTD4.js → config-3J5OOY3O.js} +3 -3
- package/dist/{global-upgrade-ZXFLRGGV.js → global-upgrade-LQM7IFAP.js} +10 -10
- package/dist/{identity-NUQ75BP7.js → identity-IQ3JVAIM.js} +4 -4
- package/dist/{live-capabilities-SIQ25SSK.js → live-capabilities-3AWVBJSK.js} +5 -5
- package/dist/{paths-BGO6PZFZ.js → paths-TAAVCO2D.js} +3 -3
- package/dist/{reapply-AD5ATZOO.js → reapply-37FCVQCJ.js} +28 -28
- package/dist/src/index.js +29 -29
- package/dist/{upgrade-lock-B5HTMEWT.js → upgrade-lock-GWB57A36.js} +4 -4
- package/dist/{usage-YHFALPKW.js → usage-QJYVQ3GS.js} +3 -3
- package/package.json +1 -1
|
@@ -2062,7 +2062,7 @@ var operandTextsOf = (command) => command.args.flatMap((arg) => {
|
|
|
2062
2062
|
});
|
|
2063
2063
|
var positionalTextsOf = (command) => command.args.filter((arg) => parameterOf(arg) === null).map((arg) => arg.text);
|
|
2064
2064
|
var firstOperandOf = (command, isSwitch) => command.args.find((arg) => !isSwitch.test(arg.text))?.text;
|
|
2065
|
-
var
|
|
2065
|
+
var namesAPathThatNeedsAPerson = (text3, judge) => judge.namesAFileThatNeedsAPerson(text3.trim());
|
|
2066
2066
|
var isAssignmentTarget = (word) => POWERSHELL_ASSIGNMENT_TARGET.test(word.text) || word.text === POWERSHELL_ARRAY_SEPARATOR;
|
|
2067
2067
|
var wordsAfterAnAssignment = (words) => {
|
|
2068
2068
|
const operator = words.findIndex((word) => isPowerShellAssignmentOperator(word));
|
|
@@ -2121,10 +2121,10 @@ var copyDestinationOf = (command) => {
|
|
|
2121
2121
|
};
|
|
2122
2122
|
var writesASecretFileFromPowerShell = (command, judge) => {
|
|
2123
2123
|
if (command.cmdlet !== COPY_ITEM) {
|
|
2124
|
-
return POWERSHELL_FILE_WRITERS.has(command.cmdlet) && operandTextsOf(command).some((text3) =>
|
|
2124
|
+
return POWERSHELL_FILE_WRITERS.has(command.cmdlet) && operandTextsOf(command).some((text3) => namesAPathThatNeedsAPerson(text3, judge));
|
|
2125
2125
|
}
|
|
2126
2126
|
const destination = copyDestinationOf(command);
|
|
2127
|
-
return destination !== void 0 &&
|
|
2127
|
+
return destination !== void 0 && namesAPathThatNeedsAPerson(destination, judge);
|
|
2128
2128
|
};
|
|
2129
2129
|
var formatsADisk = (command) => DISK_ERASERS.has(command.cmdlet);
|
|
2130
2130
|
var changesAWindowsService = (command) => {
|
|
@@ -2142,7 +2142,7 @@ var stageIsDestructive = (stage, judge) => {
|
|
|
2142
2142
|
};
|
|
2143
2143
|
var stageHasAVisibleConsequence = (stage, judge) => {
|
|
2144
2144
|
const command = powerShellCommandOf(stage);
|
|
2145
|
-
return stage.redirectTargets.some((target) =>
|
|
2145
|
+
return stage.redirectTargets.some((target) => namesAPathThatNeedsAPerson(target.text, judge)) || command !== null && !onlyReads(command, judge) && powerShellCommandChangesSomething(command, judge);
|
|
2146
2146
|
};
|
|
2147
2147
|
var fetchesWithPowerShell = (stage, judge) => {
|
|
2148
2148
|
const command = powerShellCommandOf(stage);
|
|
@@ -4538,7 +4538,7 @@ var sqlClientChangesData = (invocation) => {
|
|
|
4538
4538
|
var PULL_REQUEST_CLIS = /* @__PURE__ */ new Set(["gh", "glab"]);
|
|
4539
4539
|
var PULL_REQUEST_NOUNS = /* @__PURE__ */ new Set(["pr", "mr"]);
|
|
4540
4540
|
var MERGE_SUBCOMMAND = "merge";
|
|
4541
|
-
var PULL_REQUEST_MERGE_PATH = /(?:^|\/)pulls
|
|
4541
|
+
var PULL_REQUEST_MERGE_PATH = /(?:^|\/)pulls\/[^/\s]+\/merge(?:[?#]|$)/;
|
|
4542
4542
|
var mergesAPullRequest = ({ program, args }) => {
|
|
4543
4543
|
if (program === void 0 || !PULL_REQUEST_CLIS.has(basenameOf(program.text))) return false;
|
|
4544
4544
|
const words = args.filter((arg) => !arg.text.startsWith("-"));
|
|
@@ -4594,13 +4594,127 @@ var DEPLOY_AND_SCHEMA_COMMAND_PATTERNS = [
|
|
|
4594
4594
|
"Bash(gcloud run deploy:*)",
|
|
4595
4595
|
"Bash(gcloud functions deploy:*)"
|
|
4596
4596
|
];
|
|
4597
|
+
var RELEASE_AND_CLUSTER_PROGRAMS = /* @__PURE__ */ new Set(["kubectl", "fastlane"]);
|
|
4598
|
+
var RELEASE_AND_CLUSTER_COMMAND_PATTERNS = [
|
|
4599
|
+
"Bash(kubectl patch:*)",
|
|
4600
|
+
"Bash(kubectl edit:*)",
|
|
4601
|
+
"Bash(kubectl set:*)",
|
|
4602
|
+
"Bash(kubectl create:*)",
|
|
4603
|
+
"Bash(kubectl drain:*)",
|
|
4604
|
+
"Bash(kubectl cordon:*)",
|
|
4605
|
+
"Bash(kubectl taint:*)",
|
|
4606
|
+
"Bash(fastlane deliver:*)",
|
|
4607
|
+
"Bash(fastlane supply:*)",
|
|
4608
|
+
"Bash(fastlane pilot upload:*)",
|
|
4609
|
+
"Bash(fastlane upload_to_app_store:*)",
|
|
4610
|
+
"Bash(fastlane upload_to_testflight:*)",
|
|
4611
|
+
"Bash(fastlane upload_to_play_store:*)"
|
|
4612
|
+
];
|
|
4613
|
+
var SUBMITS_THE_BUILD_TO_A_STORE = /^--auto-submit(?:-with-profile)?(?:=|$)/;
|
|
4614
|
+
var EAS_PROGRAM = /^eas(?:-cli)?(?:@[\w.-]+)?$/;
|
|
4615
|
+
var EAS_COMMANDS_THAT_PUBLISH = /^(?:submit|deploy|update|update:(?:republish|rollback|roll-back-to-embedded)|channel:(?:edit|rollout))$/;
|
|
4616
|
+
var easCommandPublishes = (invocation) => {
|
|
4617
|
+
const words = wordsOfInvocation(invocation);
|
|
4618
|
+
return words.some((word, index) => EAS_PROGRAM.test(basenameOf(word.text)) && EAS_COMMANDS_THAT_PUBLISH.test(words[index + 1]?.text ?? ""));
|
|
4619
|
+
};
|
|
4620
|
+
var publishesAnAppBuild = (invocation) => invocation.args.some((arg) => SUBMITS_THE_BUILD_TO_A_STORE.test(arg.text)) || easCommandPublishes(invocation);
|
|
4621
|
+
var PUSHES_EVERY_TAG = /* @__PURE__ */ new Set(["--tags", "--follow-tags"]);
|
|
4622
|
+
var NAMES_A_TAG = /(?:^|:)\+?refs\/tags\/|^tag$|(?:^|:)v?\d+(?:\.\d+){1,3}$|(?:^|:)v?\d+\.\d+\.\d+[-+][\w.]+$|\/v\d+\.\d+\.\d+(?:\.\d+)?(?:[-+][\w.]+)?$|^v\$/;
|
|
4623
|
+
var TAG_HELD_IN_A_VARIABLE = /^v?\$\{?(?:\w+_)?(?:tag|version)(?:_name)?\}?$/i;
|
|
4624
|
+
var GIT_PUSH = "push";
|
|
4625
|
+
var pushesATag = ({ program, args }) => {
|
|
4626
|
+
if (program === void 0 || basenameOf(program.text) !== GIT) return false;
|
|
4627
|
+
const [subcommand, ...rest] = argsAfterHarmlessGlobalFlags(args);
|
|
4628
|
+
if (subcommand?.text !== GIT_PUSH) return false;
|
|
4629
|
+
const operands = rest.filter((arg) => !FLAG.test(arg.text));
|
|
4630
|
+
return rest.some((arg) => PUSHES_EVERY_TAG.has(arg.text)) || operands.slice(1).some((operand) => NAMES_A_TAG.test(operand.text) || TAG_HELD_IN_A_VARIABLE.test(operand.text));
|
|
4631
|
+
};
|
|
4597
4632
|
var SECRET_FILE_NAME = /^(?:\.env(?:\.(?!example$|sample$|template$)[\w.-]+)?|(?:secrets?|credentials)\.(?:json|ya?ml|env|toml|ini)|credentials)$/i;
|
|
4633
|
+
var CI_WORKFLOW_FILE = /(?:^|\/)\.github\/workflows\/[^/]+$/i;
|
|
4634
|
+
var AGENT_SETTINGS_FILE = new RegExp(String.raw`(?:^|/)(?:${[
|
|
4635
|
+
String.raw`\.claude/settings(?:\.local)?\.json`,
|
|
4636
|
+
String.raw`\.claude\.json`,
|
|
4637
|
+
String.raw`\.codex/(?:config\.toml|hooks\.json)`,
|
|
4638
|
+
String.raw`\.cursor/hooks\.json`,
|
|
4639
|
+
String.raw`\.gemini/(?:settings\.json|config/hooks\.json)`,
|
|
4640
|
+
String.raw`\.qwen/settings\.json`,
|
|
4641
|
+
String.raw`\.factory/hooks\.json`,
|
|
4642
|
+
String.raw`\.hermes/config\.ya?ml`,
|
|
4643
|
+
String.raw`\.config/opencode/(?:opencode\.jsonc?|plugins?/.+)`,
|
|
4644
|
+
String.raw`\.pushary(?:/.+)?`,
|
|
4645
|
+
String.raw`\.git/hooks(?:/.+)?`,
|
|
4646
|
+
String.raw`\.ssh(?:/(?!known_hosts(?:\.old)?$).+)?`
|
|
4647
|
+
].join("|")})$`, "i");
|
|
4648
|
+
var withoutDotSegments = (path) => {
|
|
4649
|
+
const kept = [];
|
|
4650
|
+
for (const segment of path.split("/")) {
|
|
4651
|
+
if (segment === "..") kept.pop();
|
|
4652
|
+
else if (segment !== "" && segment !== ".") kept.push(segment);
|
|
4653
|
+
}
|
|
4654
|
+
return `${path.startsWith("/") ? "/" : ""}${kept.join("/")}`;
|
|
4655
|
+
};
|
|
4656
|
+
var pathNeedsAPersonToChange = (path) => {
|
|
4657
|
+
const written = withoutDotSegments(normalizeSeparators(path));
|
|
4658
|
+
return SECRET_FILE_NAME.test(basenameOf(written)) || CI_WORKFLOW_FILE.test(written) || AGENT_SETTINGS_FILE.test(written);
|
|
4659
|
+
};
|
|
4598
4660
|
var REDIRECTS_INTO_A_SECRET_FILE = />>?\s*(?:[^\s;|&<>]*\/)?\.env(?:\.[\w-]+)?(?=$|[\s;|&)])/;
|
|
4599
4661
|
var COPIES_ONTO_ITS_LAST_OPERAND = /* @__PURE__ */ new Set(["cp", "install", "ln", "rsync", "scp"]);
|
|
4600
|
-
var WRITES_EVERY_OPERAND = /* @__PURE__ */ new Set(["mv", "tee", "rm", "unlink", "shred", "truncate"]);
|
|
4601
|
-
var EDITS_IN_PLACE = /* @__PURE__ */ new Set(["sed", "gsed", "perl"]);
|
|
4602
|
-
var
|
|
4603
|
-
var
|
|
4662
|
+
var WRITES_EVERY_OPERAND = /* @__PURE__ */ new Set(["mv", "tee", "rm", "unlink", "shred", "truncate", "sponge"]);
|
|
4663
|
+
var EDITS_IN_PLACE = /* @__PURE__ */ new Set(["sed", "gsed", "perl", "yq"]);
|
|
4664
|
+
var IN_PLACE_LONG_FLAG = /^--in-?place(?:=|$)/;
|
|
4665
|
+
var IN_PLACE_LETTER = "i";
|
|
4666
|
+
var SED_FLAGS_THAT_TAKE_THE_REST = /* @__PURE__ */ new Set(["e", "f", "l"]);
|
|
4667
|
+
var SHORT_FLAGS_THAT_TAKE_THE_REST = /* @__PURE__ */ new Map([
|
|
4668
|
+
["sed", SED_FLAGS_THAT_TAKE_THE_REST],
|
|
4669
|
+
["gsed", SED_FLAGS_THAT_TAKE_THE_REST],
|
|
4670
|
+
["perl", /* @__PURE__ */ new Set(["M", "m", "I", "e", "E", "x", "F", "C", "d", "D"])]
|
|
4671
|
+
]);
|
|
4672
|
+
var flagEditsInPlace = (program, flag) => {
|
|
4673
|
+
if (IN_PLACE_LONG_FLAG.test(flag)) return true;
|
|
4674
|
+
if (!SHORT_OPTIONS.test(flag)) return false;
|
|
4675
|
+
const takesTheRest = SHORT_FLAGS_THAT_TAKE_THE_REST.get(program);
|
|
4676
|
+
for (const letter of flag.slice(1)) {
|
|
4677
|
+
if (letter === IN_PLACE_LETTER) return true;
|
|
4678
|
+
if (takesTheRest?.has(letter) === true) return false;
|
|
4679
|
+
}
|
|
4680
|
+
return false;
|
|
4681
|
+
};
|
|
4682
|
+
var MOVE = "mv";
|
|
4683
|
+
var TARGET_DIRECTORY_FLAG = "-t";
|
|
4684
|
+
var TARGET_DIRECTORY_ASSIGNMENT = /^--target-directory=(.+)$/;
|
|
4685
|
+
var BRACE_ALTERNATIVES = /\{([^{},]*(?:,[^{},]*)+)\}/;
|
|
4686
|
+
var MAX_SPELLINGS_OF_A_WORD = 64;
|
|
4687
|
+
var hasABraceGroup = (spelling) => BRACE_ALTERNATIVES.test(spelling);
|
|
4688
|
+
var spellingsOfAWord = (word) => {
|
|
4689
|
+
if (!word.plain) return [word];
|
|
4690
|
+
let spellings = [word.text];
|
|
4691
|
+
for (let index = spellings.findIndex(hasABraceGroup); index !== -1; index = spellings.findIndex(hasABraceGroup)) {
|
|
4692
|
+
const spelling = spellings[index] ?? "";
|
|
4693
|
+
const braces = BRACE_ALTERNATIVES.exec(spelling);
|
|
4694
|
+
if (braces === null) return null;
|
|
4695
|
+
const choices = (braces[1] ?? "").split(",");
|
|
4696
|
+
if (spellings.length - 1 + choices.length > MAX_SPELLINGS_OF_A_WORD) return null;
|
|
4697
|
+
spellings = [...spellings.slice(0, index), ...choices.map((choice) => spelling.replace(braces[0], choice)), ...spellings.slice(index + 1)];
|
|
4698
|
+
}
|
|
4699
|
+
return spellings.map((text3) => ({ ...word, text: text3 }));
|
|
4700
|
+
};
|
|
4701
|
+
var namesAFileThatNeedsAPerson = (word) => word !== void 0 && pathNeedsAPersonToChange(word.text);
|
|
4702
|
+
var RECURSIVE_COPY_FLAG = /^(?:-[A-Za-z]*[rRa][A-Za-z]*|--recursive|--archive)$/;
|
|
4703
|
+
var FOLDER_THAT_NEEDS_A_PERSON = new RegExp(String.raw`(?:^|/)(?:${[
|
|
4704
|
+
String.raw`\.github/workflows`,
|
|
4705
|
+
String.raw`\.claude`,
|
|
4706
|
+
String.raw`\.codex`,
|
|
4707
|
+
String.raw`\.cursor`,
|
|
4708
|
+
String.raw`\.gemini`,
|
|
4709
|
+
String.raw`\.qwen`,
|
|
4710
|
+
String.raw`\.factory`,
|
|
4711
|
+
String.raw`\.hermes`,
|
|
4712
|
+
String.raw`\.pushary`,
|
|
4713
|
+
String.raw`\.git/hooks`,
|
|
4714
|
+
String.raw`\.ssh`,
|
|
4715
|
+
String.raw`\.config/opencode(?:/plugins?)?`
|
|
4716
|
+
].join("|")})$`, "i");
|
|
4717
|
+
var folderNeedsAPersonToChange = (path) => FOLDER_THAT_NEEDS_A_PERSON.test(withoutDotSegments(normalizeSeparators(path)));
|
|
4604
4718
|
var NETWORK_SENDERS = /* @__PURE__ */ new Set([
|
|
4605
4719
|
"curl",
|
|
4606
4720
|
"wget",
|
|
@@ -4618,16 +4732,46 @@ var NETWORK_SENDERS = /* @__PURE__ */ new Set([
|
|
|
4618
4732
|
"rclone"
|
|
4619
4733
|
]);
|
|
4620
4734
|
var FILE_REFERENCE_PREFIX = /^(?:[\w.-]+=)?@|^[\w.-]+:/;
|
|
4621
|
-
var
|
|
4622
|
-
var
|
|
4623
|
-
var
|
|
4735
|
+
var referencesAFileThatNeedsAPerson = (word) => pathNeedsAPersonToChange(word.text.replace(FILE_REFERENCE_PREFIX, ""));
|
|
4736
|
+
var sendsAFileThatNeedsAPerson = ({ program, args }) => program !== void 0 && NETWORK_SENDERS.has(basenameOf(program.text)) && args.some(referencesAFileThatNeedsAPerson);
|
|
4737
|
+
var targetDirectoryOf = (args) => {
|
|
4738
|
+
const flag = args.findIndex((arg) => arg.text === TARGET_DIRECTORY_FLAG);
|
|
4739
|
+
if (flag !== -1) return args[flag + 1]?.text;
|
|
4740
|
+
return args.map((arg) => TARGET_DIRECTORY_ASSIGNMENT.exec(arg.text)?.[1]).find((directory) => directory !== void 0);
|
|
4741
|
+
};
|
|
4742
|
+
var copiesOntoAFileThatNeedsAPerson = (args, operands) => {
|
|
4743
|
+
const targetDirectory = targetDirectoryOf(args);
|
|
4744
|
+
const destination = targetDirectory ?? operands.at(-1)?.text;
|
|
4745
|
+
if (destination === void 0) return false;
|
|
4746
|
+
const sources = targetDirectory === void 0 ? operands.slice(0, -1) : operands.filter((operand) => operand.text !== targetDirectory);
|
|
4747
|
+
const landingPaths = [destination, ...sources.map((source) => `${destination}/${basenameOf(source.text)}`)];
|
|
4748
|
+
return landingPaths.some(pathNeedsAPersonToChange) || args.some((arg) => RECURSIVE_COPY_FLAG.test(arg.text)) && landingPaths.some(folderNeedsAPersonToChange);
|
|
4749
|
+
};
|
|
4750
|
+
var GIT_HOOKS_PATH_SETTING = /^core\.hookspath(?:=|$)/i;
|
|
4751
|
+
var GIT_ONE_COMMAND_SETTING_FLAG = "-c";
|
|
4752
|
+
var GIT_CONFIG_SUBCOMMAND = "config";
|
|
4753
|
+
var GIT_CONFIG_UNSET_FLAGS = /* @__PURE__ */ new Set(["--unset", "--unset-all"]);
|
|
4754
|
+
var changesWhereGitLooksForHooks = ({ program, args }) => {
|
|
4755
|
+
if (program === void 0 || basenameOf(program.text) !== GIT) return false;
|
|
4756
|
+
const setting = args.findIndex((arg) => GIT_HOOKS_PATH_SETTING.test(arg.text));
|
|
4757
|
+
if (setting === -1) return false;
|
|
4758
|
+
if (args[setting - 1]?.text === GIT_ONE_COMMAND_SETTING_FLAG) return true;
|
|
4759
|
+
return args.some((arg) => arg.text === GIT_CONFIG_SUBCOMMAND) && (args[setting + 1] !== void 0 || args.some((arg) => GIT_CONFIG_UNSET_FLAGS.has(arg.text)));
|
|
4760
|
+
};
|
|
4761
|
+
var writesAFileThatNeedsAPerson = ({ program, args }) => {
|
|
4624
4762
|
if (program === void 0) return false;
|
|
4625
|
-
if (
|
|
4763
|
+
if (sendsAFileThatNeedsAPerson({ program, args })) return true;
|
|
4626
4764
|
const name = basenameOf(program.text);
|
|
4627
|
-
const
|
|
4628
|
-
if (COPIES_ONTO_ITS_LAST_OPERAND.has(name)
|
|
4629
|
-
|
|
4630
|
-
|
|
4765
|
+
const editsInPlace = EDITS_IN_PLACE.has(name) && args.some((arg) => flagEditsInPlace(name, arg.text));
|
|
4766
|
+
if (!COPIES_ONTO_ITS_LAST_OPERAND.has(name) && !WRITES_EVERY_OPERAND.has(name) && !editsInPlace) return false;
|
|
4767
|
+
const spelled = args.filter((arg) => !FLAG.test(arg.text)).map(spellingsOfAWord);
|
|
4768
|
+
if (spelled.includes(null)) return true;
|
|
4769
|
+
const operands = spelled.flatMap((words) => words ?? []);
|
|
4770
|
+
if (COPIES_ONTO_ITS_LAST_OPERAND.has(name)) return copiesOntoAFileThatNeedsAPerson(args, operands);
|
|
4771
|
+
if (WRITES_EVERY_OPERAND.has(name)) {
|
|
4772
|
+
return operands.some((operand) => namesAFileThatNeedsAPerson(operand) || folderNeedsAPersonToChange(operand.text)) || name === MOVE && copiesOntoAFileThatNeedsAPerson(args, operands);
|
|
4773
|
+
}
|
|
4774
|
+
return operands.some(namesAFileThatNeedsAPerson);
|
|
4631
4775
|
};
|
|
4632
4776
|
var GITHUB_COMMANDS_THAT_ONLY_READ = /* @__PURE__ */ new Set([
|
|
4633
4777
|
"search",
|
|
@@ -4733,7 +4877,7 @@ var AWS_OPTIONS_WITH_VALUES = /* @__PURE__ */ new Set([
|
|
|
4733
4877
|
"--cli-binary-format"
|
|
4734
4878
|
]);
|
|
4735
4879
|
var AWS_LOCAL_COMMANDS = /* @__PURE__ */ new Set(["configure", "help", "history", "sso", "login", "logout"]);
|
|
4736
|
-
var AWS_READ_OPERATION = /^(?:describe|list|get|head|batch-get|lookup|search|filter|scan|query|select|wait|validate|estimate|simulate|tail|ls|presign|help)(?:-|$)/;
|
|
4880
|
+
var AWS_READ_OPERATION = /^(?:describe|list|get|head|batch-get|lookup|search|filter|scan|query|select|wait|validate|estimate|simulate|tail|ls|presign|help|login|update-kubeconfig|start-query|stop-query|assume-role)(?:-|$)/;
|
|
4737
4881
|
var AWS_S3_SERVICE = "s3";
|
|
4738
4882
|
var AWS_S3_COPIES = /* @__PURE__ */ new Set(["cp", "sync"]);
|
|
4739
4883
|
var S3_URL_PREFIX = "s3://";
|
|
@@ -4803,11 +4947,16 @@ var githubCommandOnlyReads = (noun, verb) => {
|
|
|
4803
4947
|
const readVerbs = GITHUB_READ_COMMANDS.get(noun.text);
|
|
4804
4948
|
return readVerbs !== void 0 && (verb === void 0 || readVerbs.has(verb.text));
|
|
4805
4949
|
};
|
|
4806
|
-
var
|
|
4950
|
+
var githubCommandWordsOf = (args) => {
|
|
4807
4951
|
const meaningful = argsAfterHarmlessGlobalFlags(args);
|
|
4808
4952
|
const [noun, verb] = positionalWordsOf(meaningful, GITHUB_OPTIONS_WITH_VALUES);
|
|
4809
|
-
|
|
4810
|
-
|
|
4953
|
+
return { meaningful, noun, verb };
|
|
4954
|
+
};
|
|
4955
|
+
var githubApiArgsOf = ({ meaningful, noun }) => noun === void 0 ? [] : meaningful.slice(meaningful.indexOf(noun) + 1);
|
|
4956
|
+
var githubCliWrites = (args) => {
|
|
4957
|
+
const words = githubCommandWordsOf(args);
|
|
4958
|
+
if (words.noun?.text === GITHUB_API_SUBCOMMAND) return githubApiRequestWrites(githubApiArgsOf(words));
|
|
4959
|
+
return !githubCommandOnlyReads(words.noun, words.verb);
|
|
4811
4960
|
};
|
|
4812
4961
|
var stripeCliWrites = (args) => {
|
|
4813
4962
|
const [command, operation] = positionalWordsOf(args, STRIPE_OPTIONS_WITH_VALUES);
|
|
@@ -4826,8 +4975,9 @@ var twilioCliWrites = (args) => {
|
|
|
4826
4975
|
if (topic === void 0 || !topic.text.includes(TWILIO_TOPIC_SEPARATOR)) return false;
|
|
4827
4976
|
return !TWILIO_READ_ACTIONS.has(topic.text.split(TWILIO_TOPIC_SEPARATOR).at(-1) ?? "");
|
|
4828
4977
|
};
|
|
4978
|
+
var GITHUB_CLI = "gh";
|
|
4829
4979
|
var REMOTE_API_CLI_WRITES = /* @__PURE__ */ new Map([
|
|
4830
|
-
[
|
|
4980
|
+
[GITHUB_CLI, githubCliWrites],
|
|
4831
4981
|
["stripe", stripeCliWrites],
|
|
4832
4982
|
["aws", awsCliWrites],
|
|
4833
4983
|
["twilio", twilioCliWrites]
|
|
@@ -4836,6 +4986,191 @@ var invocationWritesThroughARemoteApi = ({ program, args }) => {
|
|
|
4836
4986
|
const writes = program === void 0 ? void 0 : REMOTE_API_CLI_WRITES.get(basenameOf(program.text));
|
|
4837
4987
|
return writes !== void 0 && writes(args);
|
|
4838
4988
|
};
|
|
4989
|
+
var GITHUB_REPO_NOUN = "repo";
|
|
4990
|
+
var GITHUB_EDIT_VERB = "edit";
|
|
4991
|
+
var GITHUB_CREATE_VERB = "create";
|
|
4992
|
+
var GITHUB_PUBLIC_OPTION = /^--public(?:=(?!false$).*)?$/;
|
|
4993
|
+
var GITHUB_VISIBILITY_OPTION = /^--visibility(?:=|$)/;
|
|
4994
|
+
var GITHUB_COMMANDS_WITH_A_CONSEQUENCE = /* @__PURE__ */ new Map([
|
|
4995
|
+
["secret", /* @__PURE__ */ new Set(["set"])],
|
|
4996
|
+
["variable", /* @__PURE__ */ new Set(["set"])],
|
|
4997
|
+
[GITHUB_REPO_NOUN, /* @__PURE__ */ new Set(["archive", "rename"])],
|
|
4998
|
+
["ssh-key", /* @__PURE__ */ new Set(["add"])],
|
|
4999
|
+
["gpg-key", /* @__PURE__ */ new Set(["add"])]
|
|
5000
|
+
]);
|
|
5001
|
+
var HTTP_METHODS_THAT_CHANGE_A_RESOURCE = /* @__PURE__ */ new Set(["DELETE", "PUT", "PATCH"]);
|
|
5002
|
+
var GITHUB_API_ENDPOINTS_FOR_EVERYDAY_WORK = /(?:^|\/)(?:issues|pulls|comments|notifications|labels|assignees|reviews|reactions|requested_reviewers)(?:\/|$)/;
|
|
5003
|
+
var GITHUB_API_ENDPOINTS_THAT_PUBLISH = /(?:^|\/)(?:merges|releases|dispatches|transfer|keys|deployments|hooks|git\/refs)\/?$/;
|
|
5004
|
+
var GRAPHQL_QUERY_FIELD = /^query=/;
|
|
5005
|
+
var GRAPHQL_FIELD_WORDS_THAT_DELETE_OR_PUBLISH = /delete|archive|transfer|merge|branchprotectionrule/;
|
|
5006
|
+
var GRAPHQL_FIELDS_THAT_PUBLISH = /* @__PURE__ */ new Set([
|
|
5007
|
+
"updaterepository",
|
|
5008
|
+
"createref",
|
|
5009
|
+
"updateref",
|
|
5010
|
+
"updaterefs",
|
|
5011
|
+
"createcommitonbranch"
|
|
5012
|
+
]);
|
|
5013
|
+
var WORDS_AND_THE_TEXT_BETWEEN = /(\W+)/;
|
|
5014
|
+
var OPENS_A_CALL = /^\s*\(/;
|
|
5015
|
+
var GRAPHQL_STRING = /"(?:[^"\\]|\\.)*"/g;
|
|
5016
|
+
var graphqlFieldsCalledIn = (query) => {
|
|
5017
|
+
const parts = query.replace(GRAPHQL_STRING, '""').split(WORDS_AND_THE_TEXT_BETWEEN);
|
|
5018
|
+
return parts.filter((part, index) => index % 2 === 0 && part !== "" && OPENS_A_CALL.test(parts[index + 1] ?? "")).map((field) => field.toLowerCase());
|
|
5019
|
+
};
|
|
5020
|
+
var graphqlFieldDeletesOrPublishes = (field) => GRAPHQL_FIELDS_THAT_PUBLISH.has(field) || GRAPHQL_FIELD_WORDS_THAT_DELETE_OR_PUBLISH.test(field);
|
|
5021
|
+
var SINGLE_SHORT_OPTION = /^-[A-Za-z]$/;
|
|
5022
|
+
var takesTheNextGithubApiWord = (text3) => GITHUB_API_LONG_OPTIONS_WITH_A_VALUE.has(text3) || SINGLE_SHORT_OPTION.test(text3) && GITHUB_API_SHORT_OPTIONS_WITH_A_VALUE.has(text3.charAt(1));
|
|
5023
|
+
var githubApiEndpointOf = (args) => (args.find((arg, index) => !FLAG.test(arg.text) && !takesTheNextGithubApiWord(args[index - 1]?.text ?? ""))?.text ?? "").replace(URL_QUERY_OR_FRAGMENT2, "");
|
|
5024
|
+
var graphqlQueriesOf = (options) => options.flatMap(({ name, value }) => value !== void 0 && GITHUB_API_BODY_OPTIONS.has(name) && GRAPHQL_QUERY_FIELD.test(value.text) ? [value] : []);
|
|
5025
|
+
var graphqlQueryHasAConsequence = (query) => query.expands || GITHUB_API_FILE_FIELD.test(query.text) || GRAPHQL_MUTATION.test(query.text) && graphqlFieldsCalledIn(query.text).some(graphqlFieldDeletesOrPublishes);
|
|
5026
|
+
var graphqlRequestHasAConsequence = (options) => {
|
|
5027
|
+
const queries = graphqlQueriesOf(options);
|
|
5028
|
+
return queries.length === 0 || queries.some(graphqlQueryHasAConsequence);
|
|
5029
|
+
};
|
|
5030
|
+
var HTTP_DELETE = "DELETE";
|
|
5031
|
+
var githubApiMethodHasAConsequence = (method, endpoint) => {
|
|
5032
|
+
if (method.expands) return true;
|
|
5033
|
+
const name = method.text.toUpperCase();
|
|
5034
|
+
return name === HTTP_DELETE || HTTP_METHODS_THAT_CHANGE_A_RESOURCE.has(name) && !GITHUB_API_ENDPOINTS_FOR_EVERYDAY_WORK.test(endpoint);
|
|
5035
|
+
};
|
|
5036
|
+
var githubApiRequestHasAConsequence = (args) => {
|
|
5037
|
+
const options = githubApiOptionsOf(args);
|
|
5038
|
+
if (options === null) return true;
|
|
5039
|
+
const endpoint = githubApiEndpointOf(args);
|
|
5040
|
+
if (endpoint === GITHUB_GRAPHQL_ENDPOINT) return graphqlRequestHasAConsequence(options);
|
|
5041
|
+
if (GITHUB_API_ENDPOINTS_THAT_PUBLISH.test(endpoint)) return githubApiRequestWrites(args);
|
|
5042
|
+
const method = options.filter((option) => HTTP_METHOD_OPTIONS.has(option.name)).at(-1)?.value;
|
|
5043
|
+
return method !== void 0 && githubApiMethodHasAConsequence(method, endpoint);
|
|
5044
|
+
};
|
|
5045
|
+
var githubCommandHasAConsequence = ({ program, args }) => {
|
|
5046
|
+
if (program === void 0 || basenameOf(program.text) !== GITHUB_CLI) return false;
|
|
5047
|
+
const words = githubCommandWordsOf(args);
|
|
5048
|
+
const { noun, verb } = words;
|
|
5049
|
+
if (noun === void 0) return false;
|
|
5050
|
+
if (noun.text === GITHUB_API_SUBCOMMAND) return githubApiRequestHasAConsequence(githubApiArgsOf(words));
|
|
5051
|
+
if (noun.text === GITHUB_REPO_NOUN && verb?.text === GITHUB_EDIT_VERB) return words.meaningful.some((arg) => GITHUB_VISIBILITY_OPTION.test(arg.text));
|
|
5052
|
+
if (noun.text === GITHUB_REPO_NOUN && verb?.text === GITHUB_CREATE_VERB) return words.meaningful.some((arg) => GITHUB_PUBLIC_OPTION.test(arg.text));
|
|
5053
|
+
return verb !== void 0 && (GITHUB_COMMANDS_WITH_A_CONSEQUENCE.get(noun.text)?.has(verb.text) ?? false);
|
|
5054
|
+
};
|
|
5055
|
+
var STRIPE_CLI = "stripe";
|
|
5056
|
+
var STRIPE_LIVE_MODE = /^--live$|[sr]k_live_/;
|
|
5057
|
+
var STRIPE_API_KEY_OPTION = "--api-key";
|
|
5058
|
+
var STRIPE_API_KEY_HELD_IN_A_VARIABLE = /^(?:--api-key|STRIPE_API_KEY)=.*\$/;
|
|
5059
|
+
var stripeMayUseLiveData = (words) => words.some((word, index) => STRIPE_LIVE_MODE.test(word.text) || STRIPE_API_KEY_HELD_IN_A_VARIABLE.test(word.text) || word.expands && words[index - 1]?.text === STRIPE_API_KEY_OPTION);
|
|
5060
|
+
var writesThroughAServiceApi = (invocation) => {
|
|
5061
|
+
const innermost = innermostInvocation(invocation);
|
|
5062
|
+
const name = basenameOf(innermost.program?.text ?? "");
|
|
5063
|
+
if (name === GITHUB_CLI) return false;
|
|
5064
|
+
if (name === STRIPE_CLI && !stripeMayUseLiveData(wordsOfInvocation(invocation))) return false;
|
|
5065
|
+
return invocationWritesThroughARemoteApi(innermost);
|
|
5066
|
+
};
|
|
5067
|
+
var NO_SHORT_OPTIONS = /* @__PURE__ */ new Set();
|
|
5068
|
+
var HTTP_CLIENT_SYNTAX = /* @__PURE__ */ new Map([
|
|
5069
|
+
["curl", {
|
|
5070
|
+
bodyOption: /^--(?:data(?:-[a-z]+)?|json|form(?:-string)?|upload-file)(?:=|$)/,
|
|
5071
|
+
methodOption: /^--request(?:=|$)/,
|
|
5072
|
+
getOption: /^--get$/,
|
|
5073
|
+
shortOptionsWithAValue: /* @__PURE__ */ new Set([..."AbcCdDeEFHKmoPQrtTuUwxXyYz"]),
|
|
5074
|
+
shortBodyOptions: /* @__PURE__ */ new Set(["d", "F", "T"]),
|
|
5075
|
+
shortMethodOption: "X",
|
|
5076
|
+
shortGetOption: "G"
|
|
5077
|
+
}],
|
|
5078
|
+
["wget", {
|
|
5079
|
+
bodyOption: /^--(?:post-(?:data|file)|body-(?:data|file))(?:=|$)/,
|
|
5080
|
+
methodOption: /^--method(?:=|$)/,
|
|
5081
|
+
getOption: null,
|
|
5082
|
+
shortOptionsWithAValue: NO_SHORT_OPTIONS,
|
|
5083
|
+
shortBodyOptions: NO_SHORT_OPTIONS,
|
|
5084
|
+
shortMethodOption: null,
|
|
5085
|
+
shortGetOption: null
|
|
5086
|
+
}]
|
|
5087
|
+
]);
|
|
5088
|
+
var SHORT_OPTIONS = /^-[^-]/;
|
|
5089
|
+
var optionValueAt = (args, index, attached) => {
|
|
5090
|
+
const arg = args[index];
|
|
5091
|
+
return attached === "" || arg === void 0 ? args[index + 1] : { ...arg, text: attached };
|
|
5092
|
+
};
|
|
5093
|
+
var readHttpRequest = (args, syntax) => {
|
|
5094
|
+
let sendsABody = false;
|
|
5095
|
+
let forcesAGet = false;
|
|
5096
|
+
const methods = [];
|
|
5097
|
+
args.forEach((arg, index) => {
|
|
5098
|
+
if (LONG_OPTION.test(arg.text)) {
|
|
5099
|
+
sendsABody ||= syntax.bodyOption.test(arg.text);
|
|
5100
|
+
forcesAGet ||= syntax.getOption?.test(arg.text) ?? false;
|
|
5101
|
+
const separator = arg.text.indexOf(FLAG_VALUE_SEPARATOR);
|
|
5102
|
+
const method = syntax.methodOption.test(arg.text) ? optionValueAt(args, index, separator === -1 ? "" : arg.text.slice(separator + 1)) : void 0;
|
|
5103
|
+
if (method !== void 0) methods.push(method);
|
|
5104
|
+
return;
|
|
5105
|
+
}
|
|
5106
|
+
if (!SHORT_OPTIONS.test(arg.text)) return;
|
|
5107
|
+
for (let position = 1; position < arg.text.length; position += 1) {
|
|
5108
|
+
const letter = arg.text.charAt(position);
|
|
5109
|
+
forcesAGet ||= letter === syntax.shortGetOption;
|
|
5110
|
+
if (!syntax.shortOptionsWithAValue.has(letter)) continue;
|
|
5111
|
+
sendsABody ||= syntax.shortBodyOptions.has(letter);
|
|
5112
|
+
const method = letter === syntax.shortMethodOption ? optionValueAt(args, index, arg.text.slice(position + 1)) : void 0;
|
|
5113
|
+
if (method !== void 0) methods.push(method);
|
|
5114
|
+
return;
|
|
5115
|
+
}
|
|
5116
|
+
});
|
|
5117
|
+
return { sendsABody, forcesAGet, methods };
|
|
5118
|
+
};
|
|
5119
|
+
var requestSendsData = ({ sendsABody, forcesAGet, methods }) => methods.length === 0 ? sendsABody && !forcesAGet : methods.some((method) => method.expands || !HTTP_READ_METHODS.has(method.text.toUpperCase()));
|
|
5120
|
+
var THIS_MACHINE_ADDRESS = /^(?:(?:https?:\/\/)?(?:(?:[\w-]+\.)*localhost|127(?:\.\d{1,3}){3}|0\.0\.0\.0|\[::1\]|host\.docker\.internal)|https?:\/\/(?:10(?:\.\d{1,3}){3}|192\.168(?:\.\d{1,3}){2}|172\.(?:1[6-9]|2\d|3[01])(?:\.\d{1,3}){2}))(?::(?:\d+|\$\w+|\$\{[^}]*\}))?(?:[/?#]|$)/i;
|
|
5121
|
+
var ROUTES_THE_REQUEST_ELSEWHERE = /^(?:--(?:resolve|connect-to|proxy[\w.]*|preproxy|socks[\w-]*|config)(?:=|$)|-[A-Za-z]*[xK])/;
|
|
5122
|
+
var URL_WITH_A_SCHEME = /^[a-z][a-z\d+.-]*:\/\//i;
|
|
5123
|
+
var requestStaysOnThisMachine = (args) => {
|
|
5124
|
+
if (args.some((arg) => ROUTES_THE_REQUEST_ELSEWHERE.test(arg.text))) return false;
|
|
5125
|
+
const addresses = args.filter((arg) => !FLAG.test(arg.text) && (URL_WITH_A_SCHEME.test(arg.text) || THIS_MACHINE_ADDRESS.test(arg.text)));
|
|
5126
|
+
return addresses.length > 0 && addresses.every((arg) => THIS_MACHINE_ADDRESS.test(arg.text));
|
|
5127
|
+
};
|
|
5128
|
+
var sendsDataOffThisMachine = ({ program, args }) => {
|
|
5129
|
+
const syntax = program === void 0 ? void 0 : HTTP_CLIENT_SYNTAX.get(basenameOf(program.text));
|
|
5130
|
+
return syntax !== void 0 && requestSendsData(readHttpRequest(args, syntax)) && !requestStaysOnThisMachine(args);
|
|
5131
|
+
};
|
|
5132
|
+
var KUBECTL = "kubectl";
|
|
5133
|
+
var KUBECTL_EXEC = "exec";
|
|
5134
|
+
var kubectlExecRunsMoreThanAReadOnlyCommand = ({ program, args }) => {
|
|
5135
|
+
if (program === void 0 || basenameOf(program.text) !== KUBECTL) return false;
|
|
5136
|
+
const endOfOptions = args.findIndex((arg) => arg.text === END_OF_OPTIONS3);
|
|
5137
|
+
const kubectlWords = endOfOptions === -1 ? args : args.slice(0, endOfOptions);
|
|
5138
|
+
if (!kubectlWords.some((arg) => arg.text === KUBECTL_EXEC)) return false;
|
|
5139
|
+
const command = endOfOptions === -1 ? [] : args.slice(endOfOptions + 1);
|
|
5140
|
+
return command.length === 0 || command.some((arg) => arg.expands) || !isSafeReadOnlyCommand(posixCommandOf(command.map((arg) => arg.text)));
|
|
5141
|
+
};
|
|
5142
|
+
var SSH = "ssh";
|
|
5143
|
+
var SSH_OPTION_LETTERS_WITH_A_VALUE = /* @__PURE__ */ new Set([..."BbcDEeFIiJLlmOoPpQRSWw"]);
|
|
5144
|
+
var SSH_SHORT_OPTION_CLUSTER = /^-[A-Za-z]+$/;
|
|
5145
|
+
var SSH_OPTION_THAT_RUNS_A_COMMAND = /(?:proxy|local|remote|knownhosts)command/i;
|
|
5146
|
+
var SSH_CONFIG_OPTION = "-o";
|
|
5147
|
+
var sshOptionTakesTheNextWord = (text3) => {
|
|
5148
|
+
if (!SSH_SHORT_OPTION_CLUSTER.test(text3)) return false;
|
|
5149
|
+
const letters = text3.slice(1);
|
|
5150
|
+
const firstValueOption = [...letters].findIndex((letter) => SSH_OPTION_LETTERS_WITH_A_VALUE.has(letter));
|
|
5151
|
+
return firstValueOption === letters.length - 1;
|
|
5152
|
+
};
|
|
5153
|
+
var sshOptionRunsACommand = (args) => args.some((arg, index) => (args[index - 1]?.text === SSH_CONFIG_OPTION || arg.text.startsWith(SSH_CONFIG_OPTION)) && SSH_OPTION_THAT_RUNS_A_COMMAND.test(arg.text));
|
|
5154
|
+
var sshRemoteCommandOf = (args) => {
|
|
5155
|
+
let index = 0;
|
|
5156
|
+
while (index < args.length) {
|
|
5157
|
+
const text3 = args[index]?.text ?? "";
|
|
5158
|
+
if (text3 === END_OF_OPTIONS3) {
|
|
5159
|
+
index += 1;
|
|
5160
|
+
break;
|
|
5161
|
+
}
|
|
5162
|
+
if (!FLAG.test(text3)) break;
|
|
5163
|
+
index += sshOptionTakesTheNextWord(text3) ? 2 : 1;
|
|
5164
|
+
}
|
|
5165
|
+
return args.slice(index + 1);
|
|
5166
|
+
};
|
|
5167
|
+
var sshRunsMoreThanAReadOnlyCommand = ({ program, args }) => {
|
|
5168
|
+
if (program === void 0 || basenameOf(program.text) !== SSH) return false;
|
|
5169
|
+
if (sshOptionRunsACommand(args)) return true;
|
|
5170
|
+
const command = sshRemoteCommandOf(args);
|
|
5171
|
+
return command.length > 0 && (command.some((arg) => arg.expands) || !isSafeReadOnlyCommand(command.map((arg) => arg.text).join(" ")));
|
|
5172
|
+
};
|
|
5173
|
+
var changesSomethingHostedElsewhere = (invocation) => githubCommandHasAConsequence(invocation) || writesThroughAServiceApi(invocation) || sendsDataOffThisMachine(invocation) || kubectlExecRunsMoreThanAReadOnlyCommand(invocation) || sshRunsMoreThanAReadOnlyCommand(invocation);
|
|
4839
5174
|
var segmentWritesThroughARemoteApi = (segment, depth) => {
|
|
4840
5175
|
const innermost = innermostInvocation(segment.invocation);
|
|
4841
5176
|
return invocationWritesThroughARemoteApi(innermost) || commandsNestedIn(innermost, inlineScriptsOf(innermost, segment.heredocs)).some((nested) => commandWritesThroughARemoteApiAt(nested, depth + 1));
|
|
@@ -4853,6 +5188,7 @@ var commandNeedsAPerson = (toolName, command) => {
|
|
|
4853
5188
|
const segments = readableCommandSegments(command);
|
|
4854
5189
|
return segments === null || classifyDecisionRisk(readingTool, command) !== "standard" || segments.some((segment) => segmentNeedsAPerson(readingTool, segment)) || pipesIntoASqlClient(command) || shellDialectOf(toolName) === "powershell" && powerShellCommandHasAVisibleConsequence(command, posixShellJudgeFor(toolName));
|
|
4855
5190
|
};
|
|
5191
|
+
var sessionGrantMustAskAbout = (toolName, command) => commandNeedsAPerson(toolName, command) || SHELL_DIALECT_BY_TOOL.has(toolName) && commandHasAVisibleConsequence(toolName, command);
|
|
4856
5192
|
var VISIBLE_DATA_LOSS_PATTERNS = [
|
|
4857
5193
|
"Bash(git branch -D:*)",
|
|
4858
5194
|
"Bash(git branch --delete:*)",
|
|
@@ -5134,15 +5470,17 @@ var honoursPreviewFlags = ({ program, args }) => {
|
|
|
5134
5470
|
};
|
|
5135
5471
|
var onlyPreviews = (invocation) => invocation.program !== void 0 && honoursPreviewFlags(invocation) && invocation.args.some((arg) => !arg.expands && PREVIEW_FLAG.test(arg.text));
|
|
5136
5472
|
var changesWhatIsDeployed = (toolName, invocation, normalized) => !onlyPreviews(invocation) && (changesProduction(invocation) || mergesAPullRequest(invocation) || isCoveredByPolicy(DEPLOY_AND_SCHEMA_COMMAND_PATTERNS, toolName, normalized));
|
|
5473
|
+
var releasesOrChangesACluster = (toolName, invocation, normalized) => !onlyPreviews(invocation) && (pushesATag(invocation) || publishesAnAppBuild(invocation) || RELEASE_AND_CLUSTER_PROGRAMS.has(basenameOf(invocation.program?.text ?? "")) && isCoveredByPolicy(RELEASE_AND_CLUSTER_COMMAND_PATTERNS, toolName, normalized));
|
|
5137
5474
|
var invocationHasAVisibleConsequence = (toolName, invocation, depth) => {
|
|
5138
5475
|
if (depth > MAX_CONSEQUENCE_DEPTH) return true;
|
|
5139
5476
|
if (invocation.program === void 0) return false;
|
|
5140
5477
|
const normalized = quotedInvocation(invocation);
|
|
5141
5478
|
const innermost = innermostInvocation(invocation);
|
|
5142
5479
|
const script = shellScriptOf(invocation);
|
|
5143
|
-
return classifyDecisionRisk(toolName, normalized) === "destructive" || changesWhatIsDeployed(toolName, invocation, normalized) ||
|
|
5480
|
+
return classifyDecisionRisk(toolName, normalized) === "destructive" || changesWhatIsDeployed(toolName, invocation, normalized) || releasesOrChangesACluster(toolName, invocation, normalized) || writesAFileThatNeedsAPerson(invocation) || changesWhereGitLooksForHooks(invocation) || changesSomethingHostedElsewhere(invocation) || losesDataVisibly(toolName, invocation, normalized, depth) || subcommandDestroysVisibly(invocation) || sqlClientChangesData(invocation) || innermost !== invocation && invocationHasAVisibleConsequence(toolName, innermost, depth) || script === null && passesAnInlineScript(invocation) || script !== null && commandHasAVisibleConsequenceAt(toolName, script, depth + 1) || readingsPastGlobalFlags(invocation).some((reading) => invocationHasAVisibleConsequence(toolName, reading, depth + 1));
|
|
5144
5481
|
};
|
|
5145
5482
|
var RUNS_FETCHED_CODE = /(?:\$\(|`|<\()\s*(?:curl|wget)\b/;
|
|
5483
|
+
var RUNS_DECODED_CODE = /(?:^|[;&|(\s])(?:bash|sh|zsh|source|\.|python3?|node|ruby|perl)\s+(?:-[A-Za-z]+\s+)*["']?(?:<\(|\$\()[^)]*\b(?:base64|xxd|openssl)\b/;
|
|
5146
5484
|
var FETCHING_PROGRAMS = /* @__PURE__ */ new Set(["curl", "wget"]);
|
|
5147
5485
|
var READS_ITS_SCRIPT_FROM_STANDARD_INPUT = /^-[A-Za-z]*s[A-Za-z]*$/;
|
|
5148
5486
|
var interpreterNameOf = (program) => basenameOf(program.text).replace(/\d+(?:\.\d+)*$/, "");
|
|
@@ -5162,7 +5500,79 @@ var runsADownloadedScript = (invocations) => {
|
|
|
5162
5500
|
};
|
|
5163
5501
|
var pipedSegmentsOf = (command) => (shellSegmentsReadingAPipe(commandForReading(command)) ?? []).map((segment) => innermostInvocation(invocationOf(withoutShellGrouping(segment))));
|
|
5164
5502
|
var pipesIntoASqlClient = (command) => pipedSegmentsOf(command).some((invocation) => sqlClientSyntaxOf(invocation) !== void 0);
|
|
5165
|
-
var
|
|
5503
|
+
var DECODING_FLAGS_BY_PROGRAM = /* @__PURE__ */ new Map([
|
|
5504
|
+
["base64", /^(?:-[A-Za-z]*[dD]|--decode)$/],
|
|
5505
|
+
["xxd", /^-[A-Za-z]*r/],
|
|
5506
|
+
["openssl", /^-d$/]
|
|
5507
|
+
]);
|
|
5508
|
+
var decodes = (invocation) => {
|
|
5509
|
+
const { program, args } = innermostInvocation(invocation);
|
|
5510
|
+
const decodingFlags = program === void 0 ? void 0 : DECODING_FLAGS_BY_PROGRAM.get(basenameOf(program.text));
|
|
5511
|
+
return decodingFlags !== void 0 && args.some((arg) => decodingFlags.test(arg.text));
|
|
5512
|
+
};
|
|
5513
|
+
var producesCodeTheCommandDoesNotShow = (invocation) => fetches(invocation) || decodes(invocation);
|
|
5514
|
+
var pipesHiddenCodeIntoAnInterpreter = (command, invocations) => invocations.some(producesCodeTheCommandDoesNotShow) && pipedSegmentsOf(command).some(runsWhatItReads);
|
|
5515
|
+
var CODE_THAT_DELETES_RECURSIVELY = /\b(?:rmtree|rimraf|rm_rf|rm_r|removedirs)\b|\b(?:rm|rmSync|remove|rmdir|rmdirSync)\s*\([^)]*recursive/;
|
|
5516
|
+
var CODE_THAT_DECODES = /\b(?:b64decode|atob|base64)\b/;
|
|
5517
|
+
var CODE_THAT_RUNS_CODE_IT_BUILDS = /(?<![.\w])(?:eval|exec)\s*\(/;
|
|
5518
|
+
var CODE_THAT_RUNS_COMMANDS = /\b(?:execSync|execFileSync|spawnSync|execFile|spawn|exec|child_process|subprocess|popen|Popen|system)\b/;
|
|
5519
|
+
var CODE_THAT_WRITES_A_FILE = /\b(?:writeFile|appendFile|copyFile|cpSync|renameSync|symlinkSync)\w*\s*\(|(?<![\w.])(?:cp|rename|symlink)\s*\(|\bfs(?:\.promises)?\.(?:cp|rename|symlink)\s*\(|\bshutil\.(?:copy\w*|move)\s*\(|\bos\.(?:rename|replace|symlink)\s*\(|\.write_(?:text|bytes)\s*\(|\bopen\s*\([^)]*,\s*['"`][wax]/;
|
|
5520
|
+
var CODE_STRING_LITERAL = /'([^'\\\n]*)'|"([^"\\\n]*)"|`([^`\\\n]*)`/g;
|
|
5521
|
+
var CODE_PATH_DIVISION = /'\s*\/\s*'/g;
|
|
5522
|
+
var DOUBLE_QUOTE2 = /"/g;
|
|
5523
|
+
var PATH_WITH_A_DOT = /\./;
|
|
5524
|
+
var LONGEST_PATH_SPELLED_IN_PARTS = 4;
|
|
5525
|
+
var SHELL_COMMAND_IN_A_STRING = /\S\s+\S/;
|
|
5526
|
+
var stringLiteralsOf = (code) => [...code.matchAll(CODE_STRING_LITERAL)].map((literal) => literal[1] ?? literal[2] ?? literal[3] ?? "");
|
|
5527
|
+
var pathsSpelledIn = (code) => {
|
|
5528
|
+
const literals = stringLiteralsOf(code.replace(DOUBLE_QUOTE2, "'").replace(CODE_PATH_DIVISION, "/"));
|
|
5529
|
+
return literals.flatMap((_, start) => Array.from({ length: Math.min(LONGEST_PATH_SPELLED_IN_PARTS, literals.length - start) }, (_2, extra) => literals.slice(start, start + extra + 1).join("/"))).filter((spelled) => PATH_WITH_A_DOT.test(spelled));
|
|
5530
|
+
};
|
|
5531
|
+
var commandsSpelledIn = (code) => [
|
|
5532
|
+
...stringLiteralsOf(code).filter((literal) => SHELL_COMMAND_IN_A_STRING.test(literal)),
|
|
5533
|
+
...code.split("\n").map((line) => stringLiteralsOf(line).join(" ")).filter((line) => SHELL_COMMAND_IN_A_STRING.test(line))
|
|
5534
|
+
];
|
|
5535
|
+
var INTERPRETERS_THAT_TAKE_INLINE_CODE = /* @__PURE__ */ new Set([...INLINE_CODE_INTERPRETERS, "bun", "deno", "tsx", "ts-node"]);
|
|
5536
|
+
var RUNNERS_OF_AN_INTERPRETER = /* @__PURE__ */ new Set([
|
|
5537
|
+
"uv",
|
|
5538
|
+
"poetry",
|
|
5539
|
+
"pnpm",
|
|
5540
|
+
"npm",
|
|
5541
|
+
"yarn",
|
|
5542
|
+
"bundle",
|
|
5543
|
+
"pipenv",
|
|
5544
|
+
"hatch",
|
|
5545
|
+
"pdm",
|
|
5546
|
+
"rye",
|
|
5547
|
+
"conda",
|
|
5548
|
+
"mamba"
|
|
5549
|
+
]);
|
|
5550
|
+
var isAnInterpreter = (word) => INTERPRETERS_THAT_TAKE_INLINE_CODE.has(interpreterNameOf(word));
|
|
5551
|
+
var interpreterInvocationOf = (invocation) => {
|
|
5552
|
+
const innermost = innermostInvocation(invocation);
|
|
5553
|
+
const { program, args } = innermost;
|
|
5554
|
+
if (program === void 0) return [];
|
|
5555
|
+
if (isAnInterpreter(program)) return [innermost];
|
|
5556
|
+
if (!RUNNERS_OF_AN_INTERPRETER.has(basenameOf(program.text))) return [];
|
|
5557
|
+
const start = args.findIndex(isAnInterpreter);
|
|
5558
|
+
const interpreter = args[start];
|
|
5559
|
+
return interpreter === void 0 ? [] : [{ program: interpreter, args: args.slice(start + 1) }];
|
|
5560
|
+
};
|
|
5561
|
+
var inlineCodeOf = ({ args }) => args.flatMap((arg, index) => {
|
|
5562
|
+
const namesInlineCode = (FLAG.test(arg.text) || arg.text === INLINE_CODE_SUBCOMMAND) && arg.text !== STANDARD_INPUT_ARGUMENT;
|
|
5563
|
+
if (!namesInlineCode || !passesInlineCode(arg.text)) return [];
|
|
5564
|
+
const separator = arg.text.indexOf(FLAG_VALUE_SEPARATOR);
|
|
5565
|
+
if (separator !== -1) return [arg.text.slice(separator + 1)];
|
|
5566
|
+
const code = args[index + 1];
|
|
5567
|
+
return code === void 0 ? [] : [code.text];
|
|
5568
|
+
});
|
|
5569
|
+
var interpreterCodeIn = (command, invocations) => {
|
|
5570
|
+
const interpreters = invocations.flatMap(interpreterInvocationOf);
|
|
5571
|
+
const heredocs = interpreters.some(runsWhatItReads) ? withHeredocBodiesSetAside(command).bodies : [];
|
|
5572
|
+
return [...interpreters.flatMap(inlineCodeOf), ...heredocs];
|
|
5573
|
+
};
|
|
5574
|
+
var codeNeedsAPerson = (code, depth) => CODE_THAT_DELETES_RECURSIVELY.test(code) || CODE_THAT_RUNS_CODE_IT_BUILDS.test(code) && CODE_THAT_DECODES.test(code) || CODE_THAT_WRITES_A_FILE.test(code) && pathsSpelledIn(code).some(pathNeedsAPersonToChange) || CODE_THAT_RUNS_COMMANDS.test(code) && commandsSpelledIn(code).some((command) => commandHasAVisibleConsequenceAt(SHELL_TOOL, command, depth + 1));
|
|
5575
|
+
var runsInterpreterCodeThatNeedsAPerson = (command, invocations, depth) => interpreterCodeIn(command, invocations).some((code) => codeNeedsAPerson(code, depth));
|
|
5166
5576
|
var WORDS_THAT_OPEN_A_COMMAND = String.raw`if|then|elif|else|do|while|until|!`;
|
|
5167
5577
|
var SHELL_GROUPING_PREFIX = new RegExp(String.raw`^\s*(?:(?:${WORDS_THAT_OPEN_A_COMMAND})\s+|[({]\s*)+`);
|
|
5168
5578
|
var GROUP_OPENER_BY_CLOSER = /* @__PURE__ */ new Map([[")", "("], ["}", "{"]]);
|
|
@@ -5201,7 +5611,7 @@ var withHeredocBodiesSetAside = (command) => {
|
|
|
5201
5611
|
};
|
|
5202
5612
|
var REDIRECTION_TARGET = String.raw`(?:'[^']*'|"[^"]*"|[^\s;|&()<>]+)`;
|
|
5203
5613
|
var INPUT_REDIRECTION = new RegExp(String.raw`\d*(?:<<<|<(?![<(&>]))\s*${REDIRECTION_TARGET}`, "g");
|
|
5204
|
-
var OUTPUT_REDIRECTION = new RegExp(String.raw`(?:\d*|&)(?:>>?|>\||<>|>&|<&)\s
|
|
5614
|
+
var OUTPUT_REDIRECTION = new RegExp(String.raw`(?<!\d)(?:\d*|&)(?:>>?|>\||<>|>&|<&)\s*(${REDIRECTION_TARGET})`, "g");
|
|
5205
5615
|
var REDIRECTED_INPUT_MARK = "\uE000";
|
|
5206
5616
|
var ROUGH_SEPARATORS = ["&&", "||", "$(", "\n", ";", "|", "&", "`", "(", ")", "{", "}"];
|
|
5207
5617
|
var SEPARATORS_INSIDE_DOUBLE_QUOTES = /* @__PURE__ */ new Set(["$(", "`", ")"]);
|
|
@@ -5243,6 +5653,10 @@ var invocationOfRoughPiece = (text3) => {
|
|
|
5243
5653
|
const parsed = invocationOf(piece);
|
|
5244
5654
|
return parsed.program !== void 0 ? parsed : invocationOf(piece.replace(QUOTE_CHARACTERS, ""));
|
|
5245
5655
|
};
|
|
5656
|
+
var substitutionFedTo = (pieces, index) => {
|
|
5657
|
+
const next = pieces[index + 1];
|
|
5658
|
+
return next !== void 0 && SUBSTITUTION_OPENERS.has(next.before) ? next.text : null;
|
|
5659
|
+
};
|
|
5246
5660
|
var roughSegmentsOf = (command) => {
|
|
5247
5661
|
const { text: text3, bodies } = withHeredocBodiesSetAside(commandForReading(command));
|
|
5248
5662
|
const pieces = roughPiecesOf(text3.replace(INPUT_REDIRECTION, ` ${REDIRECTED_INPUT_MARK} `).replace(OUTPUT_REDIRECTION, " "));
|
|
@@ -5251,34 +5665,88 @@ var roughSegmentsOf = (command) => {
|
|
|
5251
5665
|
const heredocCount = occurrencesOf(piece.text, HEREDOC_MARK);
|
|
5252
5666
|
const heredocs = bodies.slice(heredocsSeen, heredocsSeen + heredocCount);
|
|
5253
5667
|
heredocsSeen += heredocCount;
|
|
5668
|
+
const substitution = substitutionFedTo(pieces, index);
|
|
5254
5669
|
return {
|
|
5255
5670
|
invocation: invocationOfRoughPiece(piece.text),
|
|
5256
5671
|
readsInput: piece.text.includes(REDIRECTED_INPUT_MARK) || heredocCount > 0 || piece.before === PIPE3,
|
|
5257
5672
|
readsAPipe: piece.before === PIPE3,
|
|
5258
|
-
feedsASubstitution:
|
|
5673
|
+
feedsASubstitution: substitution !== null,
|
|
5674
|
+
substitution,
|
|
5675
|
+
evalRunsOneEnvironmentSetup: evalRunsOneEnvironmentSetup(pieces, index),
|
|
5259
5676
|
heredocs
|
|
5260
5677
|
};
|
|
5261
5678
|
});
|
|
5262
5679
|
};
|
|
5263
|
-
var
|
|
5680
|
+
var ENVIRONMENT_SETUP_COMMANDS = [
|
|
5681
|
+
String.raw`fnm\s+env`,
|
|
5682
|
+
String.raw`brew\s+shellenv`,
|
|
5683
|
+
String.raw`(?:py|rb|nod|go|j)env\s+(?:virtualenv-)?init`,
|
|
5684
|
+
String.raw`direnv\s+(?:export|hook)`,
|
|
5685
|
+
"ssh-agent",
|
|
5686
|
+
String.raw`mise\s+(?:activate|env)`,
|
|
5687
|
+
String.raw`rtx\s+activate`,
|
|
5688
|
+
String.raw`zoxide\s+init`,
|
|
5689
|
+
String.raw`starship\s+init`,
|
|
5690
|
+
String.raw`conda\s+shell\.\w+\s+hook`,
|
|
5691
|
+
String.raw`minikube\s+docker-env`,
|
|
5692
|
+
String.raw`docker-machine\s+env`,
|
|
5693
|
+
String.raw`opam\s+env`,
|
|
5694
|
+
String.raw`aws\s+configure\s+export-credentials`,
|
|
5695
|
+
String.raw`poetry\s+env\s+activate`,
|
|
5696
|
+
"dircolors",
|
|
5697
|
+
String.raw`uv\s+generate-shell-completion`,
|
|
5698
|
+
String.raw`fzf\s+--(?:zsh|bash)`,
|
|
5699
|
+
String.raw`thefuck\s+--alias`,
|
|
5700
|
+
String.raw`luarocks\s+path`,
|
|
5701
|
+
String.raw`op\s+signin`,
|
|
5702
|
+
String.raw`(?:gh|kubectl|helm|npm|pnpm|rustup|deno|bun)\s+completion`,
|
|
5703
|
+
String.raw`(?:micro)?mamba\s+shell\s+hook`,
|
|
5704
|
+
"path_helper"
|
|
5705
|
+
];
|
|
5706
|
+
var SETS_UP_THE_ENVIRONMENT = new RegExp(
|
|
5707
|
+
String.raw`^\s*(?:[^\s()$\x60"';|&]*/)?(?:${ENVIRONMENT_SETUP_COMMANDS.join("|")})(?:\s[^()$\x60"';|&]*)?$`
|
|
5708
|
+
);
|
|
5709
|
+
var EVAL_BEFORE_ITS_ARGUMENT = /^\s*eval\s+["']?$/;
|
|
5710
|
+
var EVAL_AFTER_ITS_ARGUMENT = /^["']?\s*$/;
|
|
5711
|
+
var SUBSTITUTION_CLOSERS = /* @__PURE__ */ new Set([")", "`"]);
|
|
5712
|
+
var WHAT_MAY_FOLLOW_AN_EVAL = /* @__PURE__ */ new Set(["&&", "||", ";", "\n", "|", "&", ")", "}"]);
|
|
5713
|
+
var evalRunsOneEnvironmentSetup = (pieces, index) => {
|
|
5714
|
+
const opening = pieces[index];
|
|
5715
|
+
const substitution = pieces[index + 1];
|
|
5716
|
+
const closing = pieces[index + 2];
|
|
5717
|
+
const next = pieces[index + 3];
|
|
5718
|
+
return opening !== void 0 && EVAL_BEFORE_ITS_ARGUMENT.test(opening.text) && substitution !== void 0 && SUBSTITUTION_OPENERS.has(substitution.before) && SETS_UP_THE_ENVIRONMENT.test(substitution.text) && closing !== void 0 && SUBSTITUTION_CLOSERS.has(closing.before) && EVAL_AFTER_ITS_ARGUMENT.test(closing.text) && (next === void 0 || WHAT_MAY_FOLLOW_AN_EVAL.has(next.before));
|
|
5719
|
+
};
|
|
5720
|
+
var roughSegmentHasAVisibleConsequence = (toolName, segment, producesHiddenCode, depth) => {
|
|
5264
5721
|
const innermost = innermostInvocation(segment.invocation);
|
|
5265
5722
|
const runsAHeredocScript = innermost.program !== void 0 && POSIX_SHELL_PROGRAMS.has(basenameOf(innermost.program.text));
|
|
5266
|
-
return invocationHasAVisibleConsequence(toolName, segment.invocation, depth) || sqlClientSyntaxOf(innermost) !== void 0 && (segment.readsInput || segment.feedsASubstitution) || segment.readsAPipe &&
|
|
5723
|
+
return invocationHasAVisibleConsequence(toolName, segment.invocation, depth) || sqlClientSyntaxOf(innermost) !== void 0 && (segment.readsInput || segment.feedsASubstitution) || segment.substitution !== null && basenameOf(innermost.program?.text ?? "") === EVAL && !segment.evalRunsOneEnvironmentSetup || segment.readsAPipe && producesHiddenCode && runsWhatItReads(innermost) || runsAHeredocScript && segment.heredocs.some((body) => commandHasAVisibleConsequenceAt(toolName, body, depth + 1));
|
|
5267
5724
|
};
|
|
5268
5725
|
var roughReadingHasAVisibleConsequence = (toolName, command, depth) => {
|
|
5269
5726
|
const segments = roughSegmentsOf(command);
|
|
5270
5727
|
const invocations = segments.map((segment) => segment.invocation);
|
|
5271
|
-
const
|
|
5272
|
-
return segments.some((segment) => roughSegmentHasAVisibleConsequence(toolName, segment,
|
|
5728
|
+
const producesHiddenCode = invocations.some(producesCodeTheCommandDoesNotShow);
|
|
5729
|
+
return segments.some((segment) => roughSegmentHasAVisibleConsequence(toolName, segment, producesHiddenCode, depth)) || runsADownloadedScript(invocations) || runsInterpreterCodeThatNeedsAPerson(command, invocations, depth);
|
|
5273
5730
|
};
|
|
5274
5731
|
var commandHasAVisibleConsequenceAt = (toolName, command, depth) => {
|
|
5275
5732
|
if (toolName === "Bash" && isSafeReadOnlyCommand(command)) return false;
|
|
5276
5733
|
const readable = withHeredocSubstitutionsAsQuotedText(command);
|
|
5277
5734
|
if (classifyDecisionRisk(toolName, readable) === "destructive" || RUNS_FETCHED_CODE.test(readable) || REDIRECTS_INTO_A_SECRET_FILE.test(readable)) return true;
|
|
5735
|
+
if (RUNS_DECODED_CODE.test(readable) || redirectsIntoAFileThatNeedsAPerson(command)) return true;
|
|
5278
5736
|
const segments = readableCommandSegments(command);
|
|
5279
5737
|
if (segments === null) return roughReadingHasAVisibleConsequence(toolName, command, depth);
|
|
5280
5738
|
const invocations = segments.map((segment) => invocationOf(withoutShellGrouping(segment)));
|
|
5281
|
-
return invocations.some((invocation) => invocationHasAVisibleConsequence(toolName, invocation, depth)) || pipesIntoASqlClient(command) ||
|
|
5739
|
+
return invocations.some((invocation) => invocationHasAVisibleConsequence(toolName, invocation, depth)) || pipesIntoASqlClient(command) || pipesHiddenCodeIntoAnInterpreter(command, invocations) || runsADownloadedScript(invocations) || runsInterpreterCodeThatNeedsAPerson(command, invocations, depth);
|
|
5740
|
+
};
|
|
5741
|
+
var REDIRECTION_OPERATOR_CHARACTER = /[<>]/;
|
|
5742
|
+
var redirectsIntoAFileThatNeedsAPerson = (command) => {
|
|
5743
|
+
if (!REDIRECTION_OPERATOR_CHARACTER.test(command)) return false;
|
|
5744
|
+
const text3 = withHeredocBodiesSetAside(commandForReading(command)).text;
|
|
5745
|
+
const visible = shellVisibleText(text3);
|
|
5746
|
+
return [...text3.matchAll(OUTPUT_REDIRECTION)].some((redirection) => {
|
|
5747
|
+
const operator = (redirection.index ?? 0) + redirection[0].search(REDIRECTION_OPERATOR_CHARACTER);
|
|
5748
|
+
return (visible === null || REDIRECTION_OPERATOR_CHARACTER.test(visible.charAt(operator))) && pathNeedsAPersonToChange((redirection[1] ?? "").replace(QUOTE_CHARACTERS, ""));
|
|
5749
|
+
});
|
|
5282
5750
|
};
|
|
5283
5751
|
var posixCommandOf = (words) => words.map(asOneShellWord).join(" ");
|
|
5284
5752
|
var posixShellJudgeFor = (toolName) => ({
|
|
@@ -5289,7 +5757,7 @@ var posixShellJudgeFor = (toolName) => ({
|
|
|
5289
5757
|
fetches,
|
|
5290
5758
|
runsWhatItReads,
|
|
5291
5759
|
runsScripts,
|
|
5292
|
-
|
|
5760
|
+
namesAFileThatNeedsAPerson: pathNeedsAPersonToChange
|
|
5293
5761
|
});
|
|
5294
5762
|
var commandIsDestructive = (toolName, command) => shellDialectOf(toolName) === "powershell" ? powerShellCommandIsDestructive(command, posixShellJudgeFor(toolName)) : readingsThatCanAct(command).some((reading) => classifyDecisionRisk(toolNameForAPosixReading(toolName), reading) === "destructive");
|
|
5295
5763
|
var commandHasAVisibleConsequence = (toolName, command) => shellDialectOf(toolName) === "powershell" ? powerShellCommandHasAVisibleConsequence(command, posixShellJudgeFor(toolName)) : commandHasAVisibleConsequenceAt(toolNameForAPosixReading(toolName), command, 0);
|
|
@@ -6493,7 +6961,7 @@ var unmatchedPolicyOf = (config, toolName) => ({
|
|
|
6493
6961
|
mode: config.defaultMode ?? "push_first",
|
|
6494
6962
|
pushFirstSeconds: config.defaultPushFirstSeconds ?? 20
|
|
6495
6963
|
});
|
|
6496
|
-
var sessionToolGrantCannotCover = (toolName, arg, toolInput) => typeof arg === "string" &&
|
|
6964
|
+
var sessionToolGrantCannotCover = (toolName, arg, toolInput) => typeof arg === "string" && sessionGrantMustAskAbout(toolName, arg) || parseMcpToolName(toolName) !== void 0 && (toolInput === void 0 || !mcpToolInputOnlyReads(toolName, toolInput));
|
|
6497
6965
|
var stricterOfTheReadings = (asWritten, asSpelled, unmatched) => comparePolicyStrictness(asWritten?.policy ?? unmatched, asSpelled?.policy ?? unmatched) > 0 ? asWritten : asSpelled;
|
|
6498
6966
|
var resolvePolicy = (config, toolName, modeOverride, toolInput, cwd, repoKey, sessionId) => {
|
|
6499
6967
|
const args = toolInput ? policyArgForms(toolName, toolInput, cwd) : [];
|
|
@@ -6569,6 +7037,8 @@ var strictestScopeVerdict = (scope, paths) => {
|
|
|
6569
7037
|
};
|
|
6570
7038
|
var survivesDegraded = (config, toolName, toolInputs, cwd, repoKey, sessionId) => toolInputs.length === 1 && resolveAutoResolveOrigin(config, toolName, toolInputs[0], cwd, repoKey, sessionId) === "safe_readonly";
|
|
6571
7039
|
var FULL_DEFER_MODES = /* @__PURE__ */ new Set(["plan", "auto", "dontAsk"]);
|
|
7040
|
+
var BYPASS_PERMISSION_MODE = "bypassPermissions";
|
|
7041
|
+
var isBypassPermissionMode = (permissionMode) => permissionMode === BYPASS_PERMISSION_MODE;
|
|
6572
7042
|
var FILE_EDIT_TOOLS = /* @__PURE__ */ new Set([
|
|
6573
7043
|
"Write",
|
|
6574
7044
|
"Edit",
|
|
@@ -6580,7 +7050,7 @@ var shouldDeferToNativeMode = (permissionMode, toolName, options = {}) => {
|
|
|
6580
7050
|
if (typeof permissionMode !== "string") return false;
|
|
6581
7051
|
if (FULL_DEFER_MODES.has(permissionMode)) return true;
|
|
6582
7052
|
if (permissionMode === "acceptEdits" && FILE_EDIT_TOOLS.has(toolName)) return true;
|
|
6583
|
-
if (permissionMode
|
|
7053
|
+
if (isBypassPermissionMode(permissionMode)) return options.deferBypass === true;
|
|
6584
7054
|
return false;
|
|
6585
7055
|
};
|
|
6586
7056
|
var AGENT_QUESTION_TOOL = "AskUserQuestion";
|
|
@@ -6660,6 +7130,17 @@ var PRETOOLUSE_GATED_TOOLS = [
|
|
|
6660
7130
|
var PRETOOLUSE_HANDLED_TOOLS = /* @__PURE__ */ new Set([...PRETOOLUSE_GATED_TOOLS, ...ASKED_IN_EVERY_MODE_TOOLS]);
|
|
6661
7131
|
var isPermissionRequestOwnedByPreToolUse = (toolName, permissionMode, defers = shouldDeferToNativeMode) => PRETOOLUSE_HANDLED_TOOLS.has(toolName) && (isAskedInEveryMode(toolName) || !defers(permissionMode, toolName));
|
|
6662
7132
|
var CLAUDE_PRETOOLUSE_MATCHER = [...PRETOOLUSE_HANDLED_TOOLS].join("|");
|
|
7133
|
+
var LINE_BREAK = /[\r\n]/;
|
|
7134
|
+
var bypassModeCovers = (toolName, toolInput) => {
|
|
7135
|
+
const arg = extractPolicyArg(toolName, toolInput);
|
|
7136
|
+
if (SHELL_DIALECT_BY_TOOL.has(toolName)) {
|
|
7137
|
+
return arg !== void 0 && !commandIsDestructive(toolName, arg) && !commandHasAVisibleConsequence(toolName, arg);
|
|
7138
|
+
}
|
|
7139
|
+
if (FILE_EDIT_TOOLS.has(toolName)) return arg !== void 0 && !LINE_BREAK.test(arg) && !fileEditNeedsAPerson(toolName, arg);
|
|
7140
|
+
return mcpToolOnlyReads(toolName) && mcpToolInputOnlyReads(toolName, toolInput);
|
|
7141
|
+
};
|
|
7142
|
+
var aChosenRuleGovernsInEitherRepository = (input) => aChosenRuleGoverns(input) || input.sharedRepoKey !== void 0 && input.sharedRepoKey !== input.repoKey && aChosenRuleGoverns({ ...input, repoKey: input.sharedRepoKey });
|
|
7143
|
+
var bypassModeAllows = (input) => isBypassPermissionMode(input.permissionMode) && !isModeStateDegraded(input.modeState) && noModeOverrideIsActive(input) && input.deletesFiles !== true && input.toolInputs.length > 0 && input.toolInputs.every((toolInput) => bypassModeCovers(input.toolName, toolInput)) && !aChosenRuleGovernsInEitherRepository(input);
|
|
6663
7144
|
var resolveGate = (input) => {
|
|
6664
7145
|
const { modeState, config, toolName, toolInputs, cwd, sessionId } = input;
|
|
6665
7146
|
const repoKey = input.sharedRepoKey ?? input.repoKey;
|
|
@@ -6677,8 +7158,9 @@ var resolveGate = (input) => {
|
|
|
6677
7158
|
}
|
|
6678
7159
|
const policy = resolvePolicyAcross(config, toolName, modeState.mode, toolInputs, cwd, repoKey, sessionId);
|
|
6679
7160
|
const verdict = verdictForPolicy(policy);
|
|
6680
|
-
const autoApproves = verdict === "allow";
|
|
6681
7161
|
const autoDenies = verdict === "deny";
|
|
7162
|
+
const allowedByBypassMode = !autoDenies && verdict !== "allow" && bypassModeAllows(input);
|
|
7163
|
+
const autoApproves = verdict === "allow" || allowedByBypassMode;
|
|
6682
7164
|
if (autoDenies) return { kind: "deny", policy, reason: `Denied by policy for ${policy.tool}` };
|
|
6683
7165
|
if (isAskedInEveryMode(toolName)) return { kind: "gate", policy };
|
|
6684
7166
|
if (isModeStateDegraded(modeState)) {
|
|
@@ -6692,7 +7174,7 @@ var resolveGate = (input) => {
|
|
|
6692
7174
|
if (!scopeRequiresHuman(scopeVerdict)) {
|
|
6693
7175
|
return {
|
|
6694
7176
|
kind: "allow",
|
|
6695
|
-
policy,
|
|
7177
|
+
policy: allowedByBypassMode ? autoApprove(policy.tool) : policy,
|
|
6696
7178
|
source: toolInputs.length === 1 && resolveAutoResolveOrigin(config, toolName, toolInputs[0], cwd, repoKey, sessionId) === "safe_readonly" ? "allowlist" : "policy"
|
|
6697
7179
|
};
|
|
6698
7180
|
}
|
|
@@ -6718,7 +7200,7 @@ var SCOPE_BATCH_REASON = "This patch exceeds the agreed scope. Split it into sin
|
|
|
6718
7200
|
var UNREADABLE_CALL_REASON = "Pushary could not read every target of this call. Use a supported command or a single-file edit.";
|
|
6719
7201
|
var unapprovedScopeReason = (scopeReason) => `${scopeReason}. Nobody approved this path, so the change was refused.`;
|
|
6720
7202
|
var NO_RESPONSE_REASON = "No response within timeout";
|
|
6721
|
-
var codexRaisesItsOwnPrompts = (permissionMode) => permissionMode
|
|
7203
|
+
var codexRaisesItsOwnPrompts = (permissionMode) => !isBypassPermissionMode(permissionMode);
|
|
6722
7204
|
var codexHasNoPromptOfItsOwn = (scopeReason, permissionMode) => scopeReason !== void 0 || !codexRaisesItsOwnPrompts(permissionMode);
|
|
6723
7205
|
var CODEX_ASK_PASSES = { kind: "pass" };
|
|
6724
7206
|
var codexAskUnanswered = (ask) => ({ kind: "deny", reason: unansweredRefusalReason(ask.paused) });
|
|
@@ -6743,9 +7225,7 @@ var runsACommandThatNeedsAPerson = ({ toolName, toolInputs }) => SHELL_DIALECT_B
|
|
|
6743
7225
|
const command = extractPolicyArg(toolName, toolInput);
|
|
6744
7226
|
return command !== void 0 && (commandNeedsAPerson(toolName, command) || commandWritesThroughARemoteApi(command));
|
|
6745
7227
|
});
|
|
6746
|
-
var
|
|
6747
|
-
var namesASecretOrWorkflowFile = (path) => SECRET_FILE_NAME.test(basenameOf(path)) || CI_WORKFLOW_FILE.test(normalizeSeparators(path));
|
|
6748
|
-
var fileEditNeedsAPerson = (toolName, path) => FILE_EDIT_TOOLS.has(toolName) && namesASecretOrWorkflowFile(path);
|
|
7228
|
+
var fileEditNeedsAPerson = (toolName, path) => FILE_EDIT_TOOLS.has(toolName) && pathNeedsAPersonToChange(path);
|
|
6749
7229
|
var editsAFileThatNeedsAPerson = ({ toolName, toolInputs }) => toolInputs.some((toolInput) => {
|
|
6750
7230
|
const path = extractPolicyArg(toolName, toolInput);
|
|
6751
7231
|
return path !== void 0 && fileEditNeedsAPerson(toolName, path);
|