@pushary/agent-hooks 1.1.0 → 1.3.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/CHANGELOG.md +24 -0
- package/data/SKILL.md +20 -8
- package/data/cursor-plugin/skills/pushary/SKILL.md +19 -7
- package/data/vscode-plugin/skills/pushary/SKILL.md +19 -7
- package/dist/bin/pushary-bell-hook.js +18 -18
- package/dist/bin/pushary-bell.js +6 -6
- package/dist/bin/pushary-claude.js +18 -18
- package/dist/bin/pushary-clean.js +19 -19
- package/dist/bin/pushary-codex-bridge.js +10 -10
- package/dist/bin/pushary-codex-hook.js +22 -22
- package/dist/bin/pushary-codex.js +6 -6
- package/dist/bin/pushary-connect.js +6 -6
- package/dist/bin/pushary-cowork.js +3 -3
- package/dist/bin/pushary-daemon.js +22 -22
- package/dist/bin/pushary-disconnect.js +10 -10
- package/dist/bin/pushary-doctor.js +23 -23
- package/dist/bin/pushary-elicitation-hook.js +17 -17
- package/dist/bin/pushary-gemini-bridge.js +9 -9
- package/dist/bin/pushary-gemini-hook.js +19 -19
- package/dist/bin/pushary-hook.js +26 -26
- package/dist/bin/pushary-login.js +7 -7
- package/dist/bin/pushary-logout.js +4 -4
- package/dist/bin/pushary-mode.js +3 -3
- package/dist/bin/pushary-notification-hook.js +20 -20
- package/dist/bin/pushary-opencode-hook.js +19 -19
- package/dist/bin/pushary-permission-denied-hook.js +24 -24
- package/dist/bin/pushary-permission-hook.js +25 -25
- package/dist/bin/pushary-post-hook.js +20 -20
- package/dist/bin/pushary-prompt-hook.js +20 -20
- package/dist/bin/pushary-session-end-hook.js +20 -20
- package/dist/bin/pushary-session-start-hook.js +22 -22
- package/dist/bin/pushary-setup.js +26 -26
- package/dist/bin/pushary-stats.js +2 -2
- package/dist/bin/pushary-status.js +10 -10
- package/dist/bin/pushary-stop-hook.js +20 -20
- package/dist/bin/pushary-stopfailure-hook.js +20 -20
- package/dist/bin/pushary-transcript-register.js +16 -16
- package/dist/bin/pushary-transcripts.js +4 -4
- package/dist/bin/pushary-upgrade.js +14 -14
- package/dist/bin/pushary-wait.js +3 -3
- package/dist/{chunk-SA6UB3GD.js → chunk-2PLEJ7SY.js} +1 -1
- package/dist/{chunk-RZTH4MIY.js → chunk-3AIFWTVB.js} +2 -2
- package/dist/{chunk-MZUXTN7X.js → chunk-4V24U44H.js} +2 -2
- package/dist/{chunk-2MOQUNFL.js → chunk-A2URMNFM.js} +1 -1
- package/dist/{chunk-IH7YUPFN.js → chunk-A5ZWYQFV.js} +3 -3
- package/dist/{chunk-BBUZD7MU.js → chunk-B3S4SF3D.js} +1 -1
- package/dist/{chunk-76ZCJZBK.js → chunk-BL4SQNO6.js} +1 -1
- package/dist/{chunk-SM54HHVY.js → chunk-BNDHXPTQ.js} +21 -14
- package/dist/{chunk-OYYQHJAO.js → chunk-BYGEZI7B.js} +1 -1
- package/dist/{chunk-LUYYB6V2.js → chunk-DON24PNT.js} +1 -1
- package/dist/{chunk-AH5OO2YZ.js → chunk-DVO4SZMJ.js} +3 -3
- package/dist/{chunk-S2BNTXP6.js → chunk-E7WBNGJS.js} +1 -1
- package/dist/{chunk-XIHKSZHL.js → chunk-EJZCV5G4.js} +1 -1
- package/dist/{chunk-FO4HHPMO.js → chunk-EKQAKSGI.js} +1 -1
- package/dist/{chunk-PWIMJP4U.js → chunk-EU6JH7KU.js} +6 -6
- package/dist/{chunk-PQG6NTPT.js → chunk-EYMMU5HC.js} +1 -1
- package/dist/{chunk-PUDQJ772.js → chunk-FGVNU7XD.js} +1 -1
- package/dist/{chunk-INBTKFT6.js → chunk-IAEVVUXO.js} +1 -1
- package/dist/{chunk-SLEWDZOA.js → chunk-JYEGOYQC.js} +1 -1
- package/dist/{chunk-MR2PWE62.js → chunk-K4TAUYUJ.js} +7 -8
- package/dist/{chunk-J7PJALS2.js → chunk-K7UIAE7I.js} +1 -1
- package/dist/{chunk-QACXZYDA.js → chunk-KPNGPRYU.js} +4 -4
- package/dist/{chunk-6JUCFMSF.js → chunk-KS4P6F3R.js} +3 -3
- package/dist/{chunk-ISELLVBP.js → chunk-MU275U5A.js} +1 -1
- package/dist/{chunk-LQ3BHPPZ.js → chunk-N43EQPJK.js} +5 -1
- package/dist/{chunk-YM4G6CFN.js → chunk-OE6U2AXM.js} +3 -3
- package/dist/{chunk-E3WQMDCE.js → chunk-POAFXBNH.js} +1 -1
- package/dist/{chunk-EWQZISYV.js → chunk-RHLUJE4H.js} +1 -1
- package/dist/{chunk-PHJOSAXW.js → chunk-RVDHN2TJ.js} +2 -2
- package/dist/{chunk-EZ3GX3NS.js → chunk-UVXNYYHG.js} +5 -5
- package/dist/{chunk-VQYARC2K.js → chunk-WPJS3OZH.js} +109 -21
- package/dist/{chunk-WTT24AUA.js → chunk-WXXDHGTZ.js} +29 -5
- package/dist/{chunk-DKTFZCLQ.js → chunk-X3KIGNIP.js} +6 -6
- package/dist/{chunk-IPDBFJ2M.js → chunk-XBJW4MV5.js} +1 -1
- package/dist/{chunk-UP7NZXJU.js → chunk-XBO42HKH.js} +1 -1
- package/dist/{chunk-DZYIAMKR.js → chunk-XEXOHUJ6.js} +4 -4
- package/dist/{chunk-VACFOGF3.js → chunk-YF4JDCU4.js} +1 -1
- package/dist/{chunk-6T4OINZB.js → chunk-ZHL62DRA.js} +3 -3
- package/dist/{reapply-STSGYPF2.js → reapply-FUCAKR6Z.js} +8 -8
- package/dist/src/index.js +12 -12
- package/package.json +1 -1
|
@@ -256,7 +256,8 @@ var BRIDGE_HOOK_SOURCES = Object.freeze(Object.values(AGENTS).flatMap((agent) =>
|
|
|
256
256
|
|
|
257
257
|
// ../contracts/src/agent-wiring.ts
|
|
258
258
|
var COMPATIBLE_AGENT_TYPES = ["qwen_code", "codebuddy", "qoder", "droid", "devin"];
|
|
259
|
-
var CANONICAL_PATH_KEYS = ["file_path", "path"];
|
|
259
|
+
var CANONICAL_PATH_KEYS = ["file_path", "path", "notebook_path"];
|
|
260
|
+
var CANONICAL_COMMAND_KEYS = ["command"];
|
|
260
261
|
var SHELL_TOOLS = /* @__PURE__ */ new Set(["Bash", "PowerShell"]);
|
|
261
262
|
var PATH_TOOLS = /* @__PURE__ */ new Set(["Write", "Edit", "MultiEdit", "NotebookEdit", "Read"]);
|
|
262
263
|
var PHONE_ANSWERED_TOOLS = /* @__PURE__ */ new Set(["AskUserQuestion", "ExitPlanMode"]);
|
|
@@ -271,17 +272,17 @@ var canonicalToolName = (profile, toolName) => profile.toolAliases[toolName] ??
|
|
|
271
272
|
var toToolLookup = (profile, toolName, toolInput, resolvePath = (path) => path) => {
|
|
272
273
|
const tool = canonicalToolName(profile, toolName);
|
|
273
274
|
if (SHELL_TOOLS.has(tool)) {
|
|
274
|
-
const command = firstString(toolInput, [
|
|
275
|
-
if (!command) return { tool, input: toolInput,
|
|
275
|
+
const command = firstString(toolInput, [...profile.shellCommandKeys, ...CANONICAL_COMMAND_KEYS]);
|
|
276
|
+
if (!command) return { tool, input: toolInput, unreadable: true };
|
|
276
277
|
const context = Object.fromEntries(
|
|
277
278
|
profile.shellContextKeys.flatMap((key) => toolInput[key] === void 0 ? [] : [[key, toolInput[key]]])
|
|
278
279
|
);
|
|
279
|
-
return { tool, input: { command, ...context },
|
|
280
|
+
return { tool, input: { command, ...context }, unreadable: false };
|
|
280
281
|
}
|
|
281
|
-
if (!PATH_TOOLS.has(tool)) return { tool, input: toolInput,
|
|
282
|
+
if (!PATH_TOOLS.has(tool)) return { tool, input: toolInput, unreadable: false };
|
|
282
283
|
const filePath = firstString(toolInput, [...profile.pathInputKeys, ...CANONICAL_PATH_KEYS]);
|
|
283
|
-
if (!filePath) return { tool, input: toolInput,
|
|
284
|
-
return { tool, input: { ...toolInput, file_path: resolvePath(filePath) },
|
|
284
|
+
if (!filePath) return { tool, input: toolInput, unreadable: true };
|
|
285
|
+
return { tool, input: { ...toolInput, file_path: resolvePath(filePath) }, unreadable: false };
|
|
285
286
|
};
|
|
286
287
|
var renderPreToolUseVerdict = (profile, verdict) => {
|
|
287
288
|
if (profile.wire === "permission_decision") return verdict;
|
|
@@ -331,6 +332,7 @@ var QWEN_CODE = {
|
|
|
331
332
|
},
|
|
332
333
|
extraMatchers: ["mcp__.*"],
|
|
333
334
|
pathInputKeys: ["absolute_path"],
|
|
335
|
+
shellCommandKeys: [],
|
|
334
336
|
shellContextKeys: ["directory"],
|
|
335
337
|
events: without("TeammateIdle", "Elicitation", "PermissionDenied"),
|
|
336
338
|
wire: "permission_decision",
|
|
@@ -348,6 +350,7 @@ var CODEBUDDY = {
|
|
|
348
350
|
toolAliases: {},
|
|
349
351
|
extraMatchers: ["mcp__.*"],
|
|
350
352
|
pathInputKeys: [],
|
|
353
|
+
shellCommandKeys: [],
|
|
351
354
|
shellContextKeys: [],
|
|
352
355
|
events: without("Elicitation", "PermissionDenied"),
|
|
353
356
|
wire: "permission_decision",
|
|
@@ -365,6 +368,7 @@ var QODER = {
|
|
|
365
368
|
toolAliases: {},
|
|
366
369
|
extraMatchers: ["mcp__.*"],
|
|
367
370
|
pathInputKeys: [],
|
|
371
|
+
shellCommandKeys: [],
|
|
368
372
|
shellContextKeys: [],
|
|
369
373
|
events: without("Elicitation", "PermissionDenied"),
|
|
370
374
|
wire: "permission_decision",
|
|
@@ -387,6 +391,7 @@ var DROID = {
|
|
|
387
391
|
},
|
|
388
392
|
extraMatchers: ["mcp__.*"],
|
|
389
393
|
pathInputKeys: [],
|
|
394
|
+
shellCommandKeys: [],
|
|
390
395
|
shellContextKeys: [],
|
|
391
396
|
events: ["PreToolUse", "PostToolUse", "UserPromptSubmit", "Notification", "Stop", "SubagentStop", "PreCompact", "SessionStart", "SessionEnd"],
|
|
392
397
|
wire: "permission_decision",
|
|
@@ -412,6 +417,7 @@ var DEVIN = {
|
|
|
412
417
|
},
|
|
413
418
|
extraMatchers: ["mcp__.*"],
|
|
414
419
|
pathInputKeys: [],
|
|
420
|
+
shellCommandKeys: [],
|
|
415
421
|
shellContextKeys: [],
|
|
416
422
|
events: ["PreToolUse", "PostToolUse", "UserPromptSubmit", "Stop", "SessionStart", "SessionEnd"],
|
|
417
423
|
wire: "legacy_decision",
|
|
@@ -422,7 +428,6 @@ var DEVIN = {
|
|
|
422
428
|
var HOOK_COMPATIBLE_PROFILES = Object.freeze([QWEN_CODE, CODEBUDDY, QODER, DROID, DEVIN]);
|
|
423
429
|
var hookCompatibleProfile = (agentType) => HOOK_COMPATIBLE_PROFILES.find((profile) => profile.agentType === agentType);
|
|
424
430
|
var hookCompatibleProfileBySource = (source) => HOOK_COMPATIBLE_PROFILES.find((profile) => profile.source === source);
|
|
425
|
-
var compatibleConfigDir = (profile) => profile.configFile.slice(0, -1);
|
|
426
431
|
var compatibleTargetFiles = (profile) => {
|
|
427
432
|
const seen = /* @__PURE__ */ new Map();
|
|
428
433
|
for (const file of [profile.configFile, profile.mcp?.file, profile.permissionRuleFile, profile.instructions?.file]) {
|
|
@@ -688,7 +693,71 @@ var compiledGlob = (glob) => {
|
|
|
688
693
|
globCache.set(glob, compiled);
|
|
689
694
|
return compiled;
|
|
690
695
|
};
|
|
691
|
-
var
|
|
696
|
+
var PATTERN_INTENT = {
|
|
697
|
+
grant: "grant",
|
|
698
|
+
restrict: "restrict"
|
|
699
|
+
};
|
|
700
|
+
var SHELL_ESCAPE = "\\";
|
|
701
|
+
var SHELL_DOUBLE_QUOTE = '"';
|
|
702
|
+
var SHELL_SUBSTITUTION_SIGIL = "$";
|
|
703
|
+
var SHELL_GROUP_OPEN = "(";
|
|
704
|
+
var SHELL_QUOTES = /* @__PURE__ */ new Set(["'", SHELL_DOUBLE_QUOTE]);
|
|
705
|
+
var SHELL_SEGMENT_SEPARATORS = /* @__PURE__ */ new Set([";", "\n", "&", "|"]);
|
|
706
|
+
var SHELL_DOUBLED_SEPARATORS = /* @__PURE__ */ new Set(["&", "|"]);
|
|
707
|
+
var SHELL_UNDECOMPOSABLE = /* @__PURE__ */ new Set(["`", "<", ">"]);
|
|
708
|
+
var shellCommandSegments = (command) => {
|
|
709
|
+
const segments = [];
|
|
710
|
+
let current = "";
|
|
711
|
+
let quote = null;
|
|
712
|
+
for (let index = 0; index < command.length; index += 1) {
|
|
713
|
+
const char = command[index];
|
|
714
|
+
const next = command[index + 1];
|
|
715
|
+
if (quote !== null) {
|
|
716
|
+
if (char === SHELL_ESCAPE && quote === SHELL_DOUBLE_QUOTE && next !== void 0) {
|
|
717
|
+
current += char + next;
|
|
718
|
+
index += 1;
|
|
719
|
+
continue;
|
|
720
|
+
}
|
|
721
|
+
if (char === quote) quote = null;
|
|
722
|
+
current += char;
|
|
723
|
+
continue;
|
|
724
|
+
}
|
|
725
|
+
if (char === SHELL_ESCAPE && next !== void 0) {
|
|
726
|
+
current += char + next;
|
|
727
|
+
index += 1;
|
|
728
|
+
continue;
|
|
729
|
+
}
|
|
730
|
+
if (SHELL_QUOTES.has(char)) {
|
|
731
|
+
quote = char;
|
|
732
|
+
current += char;
|
|
733
|
+
continue;
|
|
734
|
+
}
|
|
735
|
+
if (SHELL_UNDECOMPOSABLE.has(char)) return null;
|
|
736
|
+
if (char === SHELL_SUBSTITUTION_SIGIL && next === SHELL_GROUP_OPEN) return null;
|
|
737
|
+
if (SHELL_SEGMENT_SEPARATORS.has(char)) {
|
|
738
|
+
if (next === char && SHELL_DOUBLED_SEPARATORS.has(char)) index += 1;
|
|
739
|
+
segments.push(current);
|
|
740
|
+
current = "";
|
|
741
|
+
continue;
|
|
742
|
+
}
|
|
743
|
+
current += char;
|
|
744
|
+
}
|
|
745
|
+
if (quote !== null) return null;
|
|
746
|
+
segments.push(current);
|
|
747
|
+
const present = segments.map((segment) => segment.trim()).filter((segment) => segment.length > 0);
|
|
748
|
+
return present.length > 0 ? present : null;
|
|
749
|
+
};
|
|
750
|
+
var everySegmentMatches = (command, matches) => {
|
|
751
|
+
const segments = shellCommandSegments(command);
|
|
752
|
+
return segments !== null && segments.every(matches);
|
|
753
|
+
};
|
|
754
|
+
var anySegmentMatches = (command, matches) => (shellCommandSegments(command) ?? [command]).some(matches);
|
|
755
|
+
var shellSegmentsMatch = (command, intent, matches) => intent === PATTERN_INTENT.restrict ? anySegmentMatches(command, matches) : everySegmentMatches(command, matches);
|
|
756
|
+
var rankWholeOrSegments = (toolName, arg, intent, matches) => {
|
|
757
|
+
const matched = toolName in POLICY_COMMAND_KEYS ? shellSegmentsMatch(arg, intent, matches) : matches(arg);
|
|
758
|
+
return matched ? "prefix" : "none";
|
|
759
|
+
};
|
|
760
|
+
var matchToolPattern = (pattern, toolName, arg, intent = PATTERN_INTENT.grant) => {
|
|
692
761
|
const open = pattern.indexOf("(");
|
|
693
762
|
if (open === -1 || !pattern.endsWith(")")) {
|
|
694
763
|
return pattern === toolName ? "tool" : "none";
|
|
@@ -696,12 +765,14 @@ var matchToolPattern = (pattern, toolName, arg) => {
|
|
|
696
765
|
if (pattern.slice(0, open) !== toolName || arg === void 0) return "none";
|
|
697
766
|
const inner = pattern.slice(open + 1, -1);
|
|
698
767
|
if (inner.endsWith(":*")) {
|
|
699
|
-
|
|
768
|
+
const prefix = inner.slice(0, -2);
|
|
769
|
+
return rankWholeOrSegments(toolName, arg, intent, (segment) => segment.startsWith(prefix));
|
|
700
770
|
}
|
|
701
771
|
if (inner.includes("*")) {
|
|
702
772
|
if (arg.length > GLOB_MAX_ARG_LENGTH) return "none";
|
|
703
773
|
const compiled = compiledGlob(inner);
|
|
704
|
-
|
|
774
|
+
if (!compiled) return "none";
|
|
775
|
+
return rankWholeOrSegments(toolName, arg, intent, (segment) => matchGlobTokens(compiled, segment));
|
|
705
776
|
}
|
|
706
777
|
return arg === inner ? "exact" : "none";
|
|
707
778
|
};
|
|
@@ -748,11 +819,11 @@ var policyArgForms = (toolName, toolInput, cwd) => {
|
|
|
748
819
|
}
|
|
749
820
|
return forms;
|
|
750
821
|
};
|
|
751
|
-
var matchToolPatternAny = (pattern, toolName, args) => {
|
|
822
|
+
var matchToolPatternAny = (pattern, toolName, args, intent = PATTERN_INTENT.grant) => {
|
|
752
823
|
if (args.length === 0) return matchToolPattern(pattern, toolName);
|
|
753
824
|
let best = "none";
|
|
754
825
|
for (const arg of args) {
|
|
755
|
-
const rank = matchToolPattern(pattern, toolName, arg);
|
|
826
|
+
const rank = matchToolPattern(pattern, toolName, arg, intent);
|
|
756
827
|
if (matchRankWeight(rank) > matchRankWeight(best)) best = rank;
|
|
757
828
|
}
|
|
758
829
|
return best;
|
|
@@ -995,6 +1066,7 @@ var verdictForPolicy = (policy) => {
|
|
|
995
1066
|
if (isAutoApprove(policy)) return "allow";
|
|
996
1067
|
return "requires_human";
|
|
997
1068
|
};
|
|
1069
|
+
var policyIntent = (policy) => policy.timeoutAction === "deny" ? PATTERN_INTENT.restrict : PATTERN_INTENT.grant;
|
|
998
1070
|
var selectGoverningRule = (policies, toolName, args, repoKey, sessionId) => {
|
|
999
1071
|
let best;
|
|
1000
1072
|
let bestWeight = 0;
|
|
@@ -1003,7 +1075,7 @@ var selectGoverningRule = (policies, toolName, args, repoKey, sessionId) => {
|
|
|
1003
1075
|
for (const candidate of policies) {
|
|
1004
1076
|
if (!isRepoKeyMatch(candidate.repoKey, repoKey)) continue;
|
|
1005
1077
|
if (candidate.sessionId && candidate.sessionId !== sessionId) continue;
|
|
1006
|
-
const rank = matchToolPatternAny(candidate.tool, toolName, args);
|
|
1078
|
+
const rank = matchToolPatternAny(candidate.tool, toolName, args, policyIntent(candidate));
|
|
1007
1079
|
if (rank === "none") continue;
|
|
1008
1080
|
const weight = matchRankWeight(rank);
|
|
1009
1081
|
const scoped = candidate.sessionId ? 2 : candidate.repoKey ? 1 : 0;
|
|
@@ -1253,6 +1325,8 @@ var ANSWER_SOURCES = [
|
|
|
1253
1325
|
"sandbox"
|
|
1254
1326
|
];
|
|
1255
1327
|
var isAnswerSource = (value) => typeof value === "string" && ANSWER_SOURCES.includes(value);
|
|
1328
|
+
var SETTLED_OUTCOMES = ["approve", "deny"];
|
|
1329
|
+
var isSettledOutcome = (value) => typeof value === "string" && SETTLED_OUTCOMES.includes(value);
|
|
1256
1330
|
var classifyDecisionRisk = (toolName, toolTarget) => {
|
|
1257
1331
|
const parts = [toolName, toolTarget ?? ""];
|
|
1258
1332
|
const matchesAny = (patterns) => parts.some((part) => patterns.some((re) => re.test(part)));
|
|
@@ -1300,6 +1374,13 @@ var CAPABILITY_PATTERNS = {
|
|
|
1300
1374
|
};
|
|
1301
1375
|
var DECISION_EPISODE_SCHEMA_VERSION = 1;
|
|
1302
1376
|
var DECISION_FEATURE_EXTRACTOR = `pushary-hooks/schema-${DECISION_EPISODE_SCHEMA_VERSION}`;
|
|
1377
|
+
var DECISION_ORIGIN = {
|
|
1378
|
+
human: "human",
|
|
1379
|
+
autopilot: "autopilot",
|
|
1380
|
+
safeReadonly: "safe_readonly",
|
|
1381
|
+
policyTimeout: "policy_timeout",
|
|
1382
|
+
killSwitch: "kill_switch"
|
|
1383
|
+
};
|
|
1303
1384
|
var EPISODE_CAPABILITIES = [...POLICY_CAPABILITIES, "other"];
|
|
1304
1385
|
var NETWORK_COMMAND_PATTERNS = [
|
|
1305
1386
|
/\bcurl\b/i,
|
|
@@ -1373,9 +1454,8 @@ var deriveBlastRadius = (capability, riskClass, targetClass) => {
|
|
|
1373
1454
|
return "low";
|
|
1374
1455
|
};
|
|
1375
1456
|
var deriveLabelTier = (origin, decision) => {
|
|
1376
|
-
if (origin
|
|
1377
|
-
|
|
1378
|
-
return "bronze";
|
|
1457
|
+
if (origin !== DECISION_ORIGIN.human) return "none";
|
|
1458
|
+
return isSettledOutcome(decision) ? "bronze" : "none";
|
|
1379
1459
|
};
|
|
1380
1460
|
var buildDecisionEpisodeFeatures = (input) => {
|
|
1381
1461
|
const isCommand = isCommandTool(input.toolName);
|
|
@@ -1423,6 +1503,7 @@ var matchesGlobPath = (glob, path) => {
|
|
|
1423
1503
|
const compiled = compiledGlob(glob);
|
|
1424
1504
|
return compiled ? matchGlobTokens(compiled, path) : false;
|
|
1425
1505
|
};
|
|
1506
|
+
var SCOPE_PATH_MAX_LENGTH = 200;
|
|
1426
1507
|
var evaluateScope = (contract, path) => {
|
|
1427
1508
|
if (!contract) return { outcome: "no_contract" };
|
|
1428
1509
|
if (typeof path !== "string" || path.length === 0) return { outcome: "in_scope" };
|
|
@@ -1436,6 +1517,7 @@ var evaluateScope = (contract, path) => {
|
|
|
1436
1517
|
return { outcome: "out_of_scope", path };
|
|
1437
1518
|
};
|
|
1438
1519
|
var scopeRequiresHuman = (verdict) => verdict.outcome === "out_of_scope" || verdict.outcome === "off_limits";
|
|
1520
|
+
var widenablePath = (path) => path.length > 0 && path.length <= SCOPE_PATH_MAX_LENGTH ? path : void 0;
|
|
1439
1521
|
var scopeChangeReason = (verdict) => {
|
|
1440
1522
|
if (verdict.outcome === "out_of_scope") {
|
|
1441
1523
|
return `Outside the scope you approved: ${verdict.path}`;
|
|
@@ -1465,9 +1547,9 @@ var resolveAutoResolveOrigin = (config, toolName, toolInput, cwd, repoKey, sessi
|
|
|
1465
1547
|
const match = selectGoverningRule(config.policies, toolName, args, repoKey, sessionId);
|
|
1466
1548
|
const governedBySpecificRule = match?.rank === "exact" || match?.rank === "prefix";
|
|
1467
1549
|
if (!governedBySpecificRule && toolName === "Bash" && typeof arg === "string" && isSafeReadOnlyCommand(arg)) {
|
|
1468
|
-
return
|
|
1550
|
+
return DECISION_ORIGIN.safeReadonly;
|
|
1469
1551
|
}
|
|
1470
|
-
return
|
|
1552
|
+
return DECISION_ORIGIN.autopilot;
|
|
1471
1553
|
};
|
|
1472
1554
|
var resolvePolicy = (config, toolName, modeOverride, toolInput, cwd, repoKey, sessionId) => {
|
|
1473
1555
|
const args = toolInput ? policyArgForms(toolName, toolInput, cwd) : [];
|
|
@@ -1625,7 +1707,7 @@ var resolveGate = (input) => {
|
|
|
1625
1707
|
kind: "gate",
|
|
1626
1708
|
policy,
|
|
1627
1709
|
scopeReason,
|
|
1628
|
-
scopePath: scopeReason && "path" in scopeVerdict ? scopeVerdict.path : void 0
|
|
1710
|
+
scopePath: scopeReason && "path" in scopeVerdict ? widenablePath(scopeVerdict.path) : void 0
|
|
1629
1711
|
};
|
|
1630
1712
|
};
|
|
1631
1713
|
var toPolicyVersion = (value) => typeof value === "string" || typeof value === "number" ? String(value) : null;
|
|
@@ -1707,6 +1789,7 @@ var claudePermissionRequestOutput = (decision, reason, updatedInput) => ({
|
|
|
1707
1789
|
decision: decision === "allow" ? { behavior: "allow", ...updatedInput ? { updatedInput } : {} } : { behavior: "deny", ...reason ? { message: reason } : {} }
|
|
1708
1790
|
}
|
|
1709
1791
|
});
|
|
1792
|
+
var COMPATIBLE_GATE_EVENT = "PreToolUse";
|
|
1710
1793
|
var gateOutputFor = (source, event, decision, reason) => {
|
|
1711
1794
|
let output;
|
|
1712
1795
|
if (source === "claude" || source === "vscode") {
|
|
@@ -1744,6 +1827,11 @@ var gateOutputFor = (source, event, decision, reason) => {
|
|
|
1744
1827
|
user_message: "Command denied via Pushary.",
|
|
1745
1828
|
agent_message: reason ?? "Denied from Pushary"
|
|
1746
1829
|
};
|
|
1830
|
+
} else {
|
|
1831
|
+
const profile = hookCompatibleProfileBySource(source);
|
|
1832
|
+
if (profile && event === COMPATIBLE_GATE_EVENT) {
|
|
1833
|
+
output = renderPreToolUseVerdict(profile, claudePreToolUseOutput(decision, reason));
|
|
1834
|
+
}
|
|
1747
1835
|
}
|
|
1748
1836
|
return output;
|
|
1749
1837
|
};
|
|
@@ -1904,12 +1992,12 @@ export {
|
|
|
1904
1992
|
MANAGED_PROVIDERS,
|
|
1905
1993
|
COMPATIBLE_AGENT_TYPES,
|
|
1906
1994
|
PHONE_ANSWERED_TOOLS,
|
|
1995
|
+
canonicalToolName,
|
|
1907
1996
|
toToolLookup,
|
|
1908
1997
|
renderPreToolUseVerdict,
|
|
1909
1998
|
HOOK_COMPATIBLE_PROFILES,
|
|
1910
1999
|
hookCompatibleProfile,
|
|
1911
2000
|
hookCompatibleProfileBySource,
|
|
1912
|
-
compatibleConfigDir,
|
|
1913
2001
|
compatibleTargetFiles,
|
|
1914
2002
|
hookWritePath,
|
|
1915
2003
|
isHookActivationReport,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
NOTIFICATION_PUSH_TYPES,
|
|
3
3
|
POSTTOOLUSE_MIRROR_ONLY_TOOLS
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-IAEVVUXO.js";
|
|
5
5
|
import {
|
|
6
6
|
cancelQuestion,
|
|
7
7
|
isPolicyConfig,
|
|
@@ -10,13 +10,13 @@ import {
|
|
|
10
10
|
} from "./chunk-LGXUGYUH.js";
|
|
11
11
|
import {
|
|
12
12
|
getMachineId
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-K7UIAE7I.js";
|
|
14
14
|
import {
|
|
15
15
|
withRetry
|
|
16
16
|
} from "./chunk-EYRGBYZG.js";
|
|
17
17
|
import {
|
|
18
18
|
reportedInstallSource
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-POAFXBNH.js";
|
|
20
20
|
import {
|
|
21
21
|
getApiKey,
|
|
22
22
|
getBaseUrl
|
|
@@ -31,7 +31,9 @@ import {
|
|
|
31
31
|
HOOK_SOURCES,
|
|
32
32
|
PENDING_COMMAND_PREFIX,
|
|
33
33
|
REPO_AWARE_AGENTS,
|
|
34
|
+
canonicalToolName,
|
|
34
35
|
gateOutputFor,
|
|
36
|
+
hookCompatibleProfileBySource,
|
|
35
37
|
isAutoApprove,
|
|
36
38
|
localRepoKey,
|
|
37
39
|
modeStateFromResponse,
|
|
@@ -40,8 +42,9 @@ import {
|
|
|
40
42
|
redactSecrets,
|
|
41
43
|
redactSecretsDeep,
|
|
42
44
|
resolveAutoResolveOrigin,
|
|
43
|
-
resolvePolicy
|
|
44
|
-
|
|
45
|
+
resolvePolicy,
|
|
46
|
+
toToolLookup
|
|
47
|
+
} from "./chunk-WPJS3OZH.js";
|
|
45
48
|
|
|
46
49
|
// src/policy.ts
|
|
47
50
|
import { createHash } from "crypto";
|
|
@@ -349,6 +352,25 @@ var OPENCODE_TOOL_NAMES = {
|
|
|
349
352
|
websearch: "WebSearch",
|
|
350
353
|
task: "Task"
|
|
351
354
|
};
|
|
355
|
+
var PATCH_ARG_KEYS = ["command", "patch", "input"];
|
|
356
|
+
var patchedFilesIn = (input) => [...new Set(PATCH_ARG_KEYS.flatMap((key) => parseApplyPatchFiles(input[key])))];
|
|
357
|
+
var lookupsForInput = (profile, toolName, input, absolute) => {
|
|
358
|
+
const lookup = toToolLookup(profile, toolName, input, absolute);
|
|
359
|
+
if (!lookup.unreadable) return [lookup];
|
|
360
|
+
const files = patchedFilesIn(input);
|
|
361
|
+
if (files.length === 0) return [lookup];
|
|
362
|
+
return files.slice(0, GATE_MAX_TOOL_INPUTS + 1).map((file) => toToolLookup(profile, toolName, { ...input, file_path: absolute(file) }, absolute));
|
|
363
|
+
};
|
|
364
|
+
var compatibleGateInputs = (profile, toolName, toolInputs, cwd) => {
|
|
365
|
+
const absolute = (path) => cwd && !isAbsolute(path) ? resolve(cwd, path) : path;
|
|
366
|
+
const lookups = toolInputs.flatMap((input) => lookupsForInput(profile, toolName, input, absolute));
|
|
367
|
+
if (lookups.length > GATE_MAX_TOOL_INPUTS) return null;
|
|
368
|
+
if (lookups.some((lookup) => lookup.unreadable)) return null;
|
|
369
|
+
return {
|
|
370
|
+
toolName: lookups[0]?.tool ?? canonicalToolName(profile, toolName),
|
|
371
|
+
toolInputs: lookups.map((lookup) => lookup.input)
|
|
372
|
+
};
|
|
373
|
+
};
|
|
352
374
|
var canonicalGateInputs = (source, toolName, toolInputs, cwd) => {
|
|
353
375
|
if (source === "codex" && toolName === "apply_patch" || source === "vscode" && ["apply_patch", "applyPatch", "copilot_applyPatch"].includes(toolName)) {
|
|
354
376
|
const paths = [...new Set(toolInputs.flatMap((input) => parseApplyPatchFiles(input.command ?? input.input ?? input.patch)))];
|
|
@@ -419,6 +441,8 @@ var canonicalGateInputs = (source, toolName, toolInputs, cwd) => {
|
|
|
419
441
|
return typeof path === "string" ? { ...input, file_path: cwd && !isAbsolute(path) ? resolve(cwd, path) : path } : input;
|
|
420
442
|
}) };
|
|
421
443
|
}
|
|
444
|
+
const profile = hookCompatibleProfileBySource(source);
|
|
445
|
+
if (profile) return compatibleGateInputs(profile, toolName, toolInputs, cwd);
|
|
422
446
|
if (source !== "gemini") return { toolName, toolInputs };
|
|
423
447
|
if (toolName === "run_shell_command") {
|
|
424
448
|
return { toolName: "Bash", toolInputs: toolInputs.map((input) => ({ command: input.command })) };
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import {
|
|
2
2
|
activeIdentity
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-BNDHXPTQ.js";
|
|
4
4
|
import {
|
|
5
5
|
blockedActionFingerprint,
|
|
6
6
|
defersToNativeMode,
|
|
7
7
|
forgetBlockedActionHint,
|
|
8
8
|
hasBlockedActionHint,
|
|
9
9
|
recordBlockedActionHint
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-A5ZWYQFV.js";
|
|
11
11
|
import {
|
|
12
12
|
isGatingMoment,
|
|
13
13
|
recordKeylessMoment
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-YF4JDCU4.js";
|
|
15
15
|
import {
|
|
16
16
|
denyReasonFrom,
|
|
17
17
|
isDeferAnswer
|
|
@@ -34,7 +34,7 @@ import {
|
|
|
34
34
|
scopePathFor,
|
|
35
35
|
settleQuestionsForToolUse,
|
|
36
36
|
throttlePass
|
|
37
|
-
} from "./chunk-
|
|
37
|
+
} from "./chunk-WXXDHGTZ.js";
|
|
38
38
|
import {
|
|
39
39
|
DECISION_STOP_REASON,
|
|
40
40
|
askUser,
|
|
@@ -49,7 +49,7 @@ import {
|
|
|
49
49
|
} from "./chunk-LGXUGYUH.js";
|
|
50
50
|
import {
|
|
51
51
|
getMachineId
|
|
52
|
-
} from "./chunk-
|
|
52
|
+
} from "./chunk-K7UIAE7I.js";
|
|
53
53
|
import {
|
|
54
54
|
getApiKey,
|
|
55
55
|
getBaseUrl
|
|
@@ -73,7 +73,7 @@ import {
|
|
|
73
73
|
parseAgentQuestions,
|
|
74
74
|
resolveGate,
|
|
75
75
|
stoppedOutput
|
|
76
|
-
} from "./chunk-
|
|
76
|
+
} from "./chunk-WPJS3OZH.js";
|
|
77
77
|
|
|
78
78
|
// src/decision-episode.ts
|
|
79
79
|
var EPISODE_PATH = "/api/agent/decision-episode";
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import {
|
|
2
2
|
AGENT_CHOICES
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-BYGEZI7B.js";
|
|
4
4
|
import {
|
|
5
5
|
isBridgeLocator
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-JYEGOYQC.js";
|
|
7
7
|
import {
|
|
8
8
|
pusharyHookExecutable
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-DVO4SZMJ.js";
|
|
10
10
|
import {
|
|
11
11
|
BELL_HOOK_BINARY
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-2PLEJ7SY.js";
|
|
13
13
|
|
|
14
14
|
// src/setup/hook-ownership.ts
|
|
15
15
|
var commandsIn = (value) => {
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import {
|
|
2
2
|
CLAUDE_HOOK_EVENTS,
|
|
3
3
|
supportedClaudeEvents
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-OE6U2AXM.js";
|
|
5
5
|
import {
|
|
6
6
|
guardBinary,
|
|
7
7
|
holdBudgetOf,
|
|
8
8
|
isProtectedByScope,
|
|
9
9
|
registerHookEntry
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-RHLUJE4H.js";
|
|
11
11
|
import {
|
|
12
12
|
HOOK_LOCATOR_BINARY,
|
|
13
13
|
withHookHoldBudget
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-WPJS3OZH.js";
|
|
15
15
|
|
|
16
16
|
// src/claude-config.ts
|
|
17
17
|
import { join } from "path";
|
|
@@ -8,15 +8,15 @@ import {
|
|
|
8
8
|
reapplyGeminiSettings,
|
|
9
9
|
reapplyVsCodePlugin,
|
|
10
10
|
repairCodexHolds
|
|
11
|
-
} from "./chunk-
|
|
12
|
-
import "./chunk-
|
|
13
|
-
import "./chunk-
|
|
14
|
-
import "./chunk-
|
|
15
|
-
import "./chunk-
|
|
16
|
-
import "./chunk-
|
|
17
|
-
import "./chunk-
|
|
11
|
+
} from "./chunk-UVXNYYHG.js";
|
|
12
|
+
import "./chunk-XBJW4MV5.js";
|
|
13
|
+
import "./chunk-ZHL62DRA.js";
|
|
14
|
+
import "./chunk-DVO4SZMJ.js";
|
|
15
|
+
import "./chunk-OE6U2AXM.js";
|
|
16
|
+
import "./chunk-IAEVVUXO.js";
|
|
17
|
+
import "./chunk-RHLUJE4H.js";
|
|
18
18
|
import "./chunk-4LL6LG5X.js";
|
|
19
|
-
import "./chunk-
|
|
19
|
+
import "./chunk-WPJS3OZH.js";
|
|
20
20
|
export {
|
|
21
21
|
inspectConfiguredManagedProviders,
|
|
22
22
|
reapplyAllAgents,
|
package/dist/src/index.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
handlePreToolUse
|
|
3
|
-
} from "../chunk-
|
|
4
|
-
import "../chunk-
|
|
5
|
-
import "../chunk-
|
|
6
|
-
import "../chunk-
|
|
7
|
-
import "../chunk-
|
|
3
|
+
} from "../chunk-X3KIGNIP.js";
|
|
4
|
+
import "../chunk-BNDHXPTQ.js";
|
|
5
|
+
import "../chunk-ZHL62DRA.js";
|
|
6
|
+
import "../chunk-A5ZWYQFV.js";
|
|
7
|
+
import "../chunk-YF4JDCU4.js";
|
|
8
8
|
import "../chunk-YHG74UFF.js";
|
|
9
|
-
import "../chunk-
|
|
9
|
+
import "../chunk-OE6U2AXM.js";
|
|
10
10
|
import {
|
|
11
11
|
fetchAccountPublicKey
|
|
12
12
|
} from "../chunk-EQRS3SGM.js";
|
|
@@ -18,20 +18,20 @@ import {
|
|
|
18
18
|
handlePostToolUse,
|
|
19
19
|
handleStop,
|
|
20
20
|
reportEvent
|
|
21
|
-
} from "../chunk-
|
|
22
|
-
import "../chunk-
|
|
21
|
+
} from "../chunk-WXXDHGTZ.js";
|
|
22
|
+
import "../chunk-IAEVVUXO.js";
|
|
23
23
|
import {
|
|
24
24
|
askUser,
|
|
25
25
|
cancelQuestion,
|
|
26
26
|
waitForAnswer
|
|
27
27
|
} from "../chunk-LGXUGYUH.js";
|
|
28
|
-
import "../chunk-
|
|
29
|
-
import "../chunk-
|
|
28
|
+
import "../chunk-K7UIAE7I.js";
|
|
29
|
+
import "../chunk-RHLUJE4H.js";
|
|
30
30
|
import "../chunk-EYRGBYZG.js";
|
|
31
31
|
import "../chunk-SAF6HGAA.js";
|
|
32
32
|
import "../chunk-7QLSKOSU.js";
|
|
33
33
|
import "../chunk-KZERVKTD.js";
|
|
34
|
-
import "../chunk-
|
|
34
|
+
import "../chunk-POAFXBNH.js";
|
|
35
35
|
import "../chunk-4LL6LG5X.js";
|
|
36
36
|
import {
|
|
37
37
|
getApiKey,
|
|
@@ -39,7 +39,7 @@ import {
|
|
|
39
39
|
} from "../chunk-2UMNXADU.js";
|
|
40
40
|
import {
|
|
41
41
|
resolvePolicy
|
|
42
|
-
} from "../chunk-
|
|
42
|
+
} from "../chunk-WPJS3OZH.js";
|
|
43
43
|
export {
|
|
44
44
|
askUser,
|
|
45
45
|
cancelQuestion,
|