@pushary/agent-hooks 1.0.0 → 1.2.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 +250 -49
- package/data/cursor-plugin/scripts/pushary-gate.mjs +24 -0
- package/data/cursor-plugin/skills/pushary/SKILL.md +250 -49
- package/data/vscode-plugin/scripts/pushary-gate.mjs +24 -0
- package/data/vscode-plugin/skills/pushary/SKILL.md +250 -49
- 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 +50 -20
- 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-DUOG74E7.js → chunk-2DT7STR5.js} +1 -1
- package/dist/{chunk-IWZG2Y4Z.js → chunk-4UT44NRP.js} +5 -1
- package/dist/{chunk-MDV7ZRAT.js → chunk-5AATCXJN.js} +29 -5
- package/dist/{chunk-7ZDFVWRR.js → chunk-6QCN5XQE.js} +1 -1
- package/dist/{chunk-TTBRBWAK.js → chunk-7DQVIIHX.js} +97 -16
- package/dist/{chunk-S2W4ZSHE.js → chunk-7ERWAYVV.js} +1 -1
- package/dist/{chunk-447SBIC7.js → chunk-7GH3D6YG.js} +9 -9
- package/dist/{chunk-DOYARIYB.js → chunk-7TDQ7KDY.js} +1 -1
- package/dist/{chunk-3C4ERARU.js → chunk-BXLFUTSD.js} +3 -3
- package/dist/{chunk-XK34HTMW.js → chunk-C3WH44MH.js} +3 -3
- package/dist/{chunk-IYA3NCZG.js → chunk-CG4ZUQ5O.js} +2 -2
- package/dist/{chunk-MSOFZYI3.js → chunk-CVCSUAXI.js} +3 -3
- package/dist/{chunk-R744XA2M.js → chunk-DRAATYTY.js} +5 -5
- package/dist/{chunk-2PS3DTHQ.js → chunk-ERP7FOFQ.js} +3 -3
- package/dist/{chunk-RFNMSC6N.js → chunk-JOTV75GX.js} +1 -1
- package/dist/{chunk-Y55JNI2I.js → chunk-JQJB7BZE.js} +1 -1
- package/dist/{chunk-DMJTWULU.js → chunk-KEVJ2WW6.js} +1 -1
- package/dist/{chunk-IBU7UU3R.js → chunk-KHTBSSY5.js} +1 -1
- package/dist/{chunk-I3TWY7GH.js → chunk-KODKICKJ.js} +6 -6
- package/dist/{chunk-7WMFPYR5.js → chunk-KZPUARCU.js} +1 -1
- package/dist/{chunk-D2N2EJH2.js → chunk-LAXU5U75.js} +2 -2
- package/dist/{chunk-XKDKUFMP.js → chunk-LGO7U23Z.js} +1 -1
- package/dist/{chunk-XNXIMIFY.js → chunk-LWKVEMVK.js} +1 -1
- package/dist/{chunk-GTR72MIU.js → chunk-OGSRCIOD.js} +1 -1
- package/dist/{chunk-HGEI7SVM.js → chunk-PCT2MYG5.js} +6 -6
- package/dist/{chunk-LTPQKBJH.js → chunk-PX53RT6Q.js} +1 -1
- package/dist/{chunk-MGI6MLFU.js → chunk-PX54KULQ.js} +3 -3
- package/dist/{chunk-BOZETFXB.js → chunk-RN6ZWIAC.js} +1 -1
- package/dist/{chunk-CDTGL7TT.js → chunk-U42ES5U3.js} +1 -1
- package/dist/{chunk-EMCNSBF3.js → chunk-UWP66NDF.js} +1 -1
- package/dist/{chunk-UWQVODHT.js → chunk-VDOKRCWM.js} +1 -1
- package/dist/{chunk-TVY7AT6O.js → chunk-VE2ZWUML.js} +1 -1
- package/dist/{chunk-BPD4P3NN.js → chunk-VIQ7CCWW.js} +2 -2
- package/dist/{chunk-2SL5X7UB.js → chunk-W6XVHP4U.js} +4 -4
- package/dist/{chunk-3UUAK2AK.js → chunk-WC5PYFDK.js} +1 -1
- package/dist/{chunk-ZZIUQVAN.js → chunk-YK3OU4E2.js} +4 -4
- package/dist/{chunk-HS2KEAFD.js → chunk-YT6H7BB5.js} +21 -14
- package/dist/{chunk-A3D43VXO.js → chunk-ZFQPSGPO.js} +1 -1
- package/dist/{reapply-I4NB5SSM.js → reapply-47AMVIXN.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;
|
|
@@ -1423,6 +1495,7 @@ var matchesGlobPath = (glob, path) => {
|
|
|
1423
1495
|
const compiled = compiledGlob(glob);
|
|
1424
1496
|
return compiled ? matchGlobTokens(compiled, path) : false;
|
|
1425
1497
|
};
|
|
1498
|
+
var SCOPE_PATH_MAX_LENGTH = 200;
|
|
1426
1499
|
var evaluateScope = (contract, path) => {
|
|
1427
1500
|
if (!contract) return { outcome: "no_contract" };
|
|
1428
1501
|
if (typeof path !== "string" || path.length === 0) return { outcome: "in_scope" };
|
|
@@ -1436,6 +1509,7 @@ var evaluateScope = (contract, path) => {
|
|
|
1436
1509
|
return { outcome: "out_of_scope", path };
|
|
1437
1510
|
};
|
|
1438
1511
|
var scopeRequiresHuman = (verdict) => verdict.outcome === "out_of_scope" || verdict.outcome === "off_limits";
|
|
1512
|
+
var widenablePath = (path) => path.length > 0 && path.length <= SCOPE_PATH_MAX_LENGTH ? path : void 0;
|
|
1439
1513
|
var scopeChangeReason = (verdict) => {
|
|
1440
1514
|
if (verdict.outcome === "out_of_scope") {
|
|
1441
1515
|
return `Outside the scope you approved: ${verdict.path}`;
|
|
@@ -1449,6 +1523,7 @@ var isScopeContract = (value) => {
|
|
|
1449
1523
|
if (!value || typeof value !== "object") return false;
|
|
1450
1524
|
const c = value;
|
|
1451
1525
|
const strings = (v) => Array.isArray(v) && v.every((x) => typeof x === "string");
|
|
1526
|
+
if (c.promises !== void 0 && !strings(c.promises)) return false;
|
|
1452
1527
|
return strings(c.allowedPaths) && strings(c.offLimitsPaths) && typeof c.doneWhen === "string";
|
|
1453
1528
|
};
|
|
1454
1529
|
var autoApprove = (tool) => ({
|
|
@@ -1624,7 +1699,7 @@ var resolveGate = (input) => {
|
|
|
1624
1699
|
kind: "gate",
|
|
1625
1700
|
policy,
|
|
1626
1701
|
scopeReason,
|
|
1627
|
-
scopePath: scopeReason && "path" in scopeVerdict ? scopeVerdict.path : void 0
|
|
1702
|
+
scopePath: scopeReason && "path" in scopeVerdict ? widenablePath(scopeVerdict.path) : void 0
|
|
1628
1703
|
};
|
|
1629
1704
|
};
|
|
1630
1705
|
var toPolicyVersion = (value) => typeof value === "string" || typeof value === "number" ? String(value) : null;
|
|
@@ -1706,6 +1781,7 @@ var claudePermissionRequestOutput = (decision, reason, updatedInput) => ({
|
|
|
1706
1781
|
decision: decision === "allow" ? { behavior: "allow", ...updatedInput ? { updatedInput } : {} } : { behavior: "deny", ...reason ? { message: reason } : {} }
|
|
1707
1782
|
}
|
|
1708
1783
|
});
|
|
1784
|
+
var COMPATIBLE_GATE_EVENT = "PreToolUse";
|
|
1709
1785
|
var gateOutputFor = (source, event, decision, reason) => {
|
|
1710
1786
|
let output;
|
|
1711
1787
|
if (source === "claude" || source === "vscode") {
|
|
@@ -1743,6 +1819,11 @@ var gateOutputFor = (source, event, decision, reason) => {
|
|
|
1743
1819
|
user_message: "Command denied via Pushary.",
|
|
1744
1820
|
agent_message: reason ?? "Denied from Pushary"
|
|
1745
1821
|
};
|
|
1822
|
+
} else {
|
|
1823
|
+
const profile = hookCompatibleProfileBySource(source);
|
|
1824
|
+
if (profile && event === COMPATIBLE_GATE_EVENT) {
|
|
1825
|
+
output = renderPreToolUseVerdict(profile, claudePreToolUseOutput(decision, reason));
|
|
1826
|
+
}
|
|
1746
1827
|
}
|
|
1747
1828
|
return output;
|
|
1748
1829
|
};
|
|
@@ -1903,12 +1984,12 @@ export {
|
|
|
1903
1984
|
MANAGED_PROVIDERS,
|
|
1904
1985
|
COMPATIBLE_AGENT_TYPES,
|
|
1905
1986
|
PHONE_ANSWERED_TOOLS,
|
|
1987
|
+
canonicalToolName,
|
|
1906
1988
|
toToolLookup,
|
|
1907
1989
|
renderPreToolUseVerdict,
|
|
1908
1990
|
HOOK_COMPATIBLE_PROFILES,
|
|
1909
1991
|
hookCompatibleProfile,
|
|
1910
1992
|
hookCompatibleProfileBySource,
|
|
1911
|
-
compatibleConfigDir,
|
|
1912
1993
|
compatibleTargetFiles,
|
|
1913
1994
|
hookWritePath,
|
|
1914
1995
|
isHookActivationReport,
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
openCodeConfigDirFrom
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-LWKVEMVK.js";
|
|
4
4
|
import {
|
|
5
5
|
codexHomeFrom
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-PX53RT6Q.js";
|
|
7
7
|
import {
|
|
8
|
-
HOOK_COMPATIBLE_PROFILES
|
|
9
|
-
|
|
10
|
-
} from "./chunk-TTBRBWAK.js";
|
|
8
|
+
HOOK_COMPATIBLE_PROFILES
|
|
9
|
+
} from "./chunk-7DQVIIHX.js";
|
|
11
10
|
|
|
12
11
|
// src/vscode-config.ts
|
|
13
12
|
import { homedir } from "os";
|
|
@@ -238,17 +237,17 @@ var agentProbes = (home = homedir2()) => ({
|
|
|
238
237
|
// never used.
|
|
239
238
|
configMarkers: [openCodeConfigDirFrom(home)]
|
|
240
239
|
},
|
|
241
|
-
...compatibleProbes(
|
|
240
|
+
...compatibleProbes(),
|
|
242
241
|
// "Other" is a set of printed instructions for any MCP or HTTP client. There is
|
|
243
242
|
// nothing to detect, and it must never be auto-selected.
|
|
244
243
|
custom: { binary: null, paths: [], configMarkers: [] }
|
|
245
244
|
});
|
|
246
|
-
var compatibleProbes = (
|
|
245
|
+
var compatibleProbes = () => HOOK_COMPATIBLE_PROFILES.reduce((probes, profile) => ({
|
|
247
246
|
...probes,
|
|
248
247
|
[profile.agentType]: {
|
|
249
248
|
binary: profile.binary,
|
|
250
249
|
paths: [],
|
|
251
|
-
configMarkers: [
|
|
250
|
+
configMarkers: []
|
|
252
251
|
}
|
|
253
252
|
}), {});
|
|
254
253
|
var detectAllAgents = (deps = defaultDeps, home) => {
|
|
@@ -278,7 +277,8 @@ You have Pushary MCP tools that reach the user on their phone. Use them proactiv
|
|
|
278
277
|
- When you need the user to make a decision or answer a clarifying question, call \`ask_user\` instead of guessing or stalling. Use type "confirm" for yes/no, "select" for a fixed set of options, and "input" for free text. Read \`answered\`, \`status\` and the returned handoff instead of assuming the tool blocked. Silence is not consent; choice/text answers do not authorize a separate action.
|
|
279
278
|
- Ask once, on one channel. If you also have a built-in way to prompt the user, use that or \`ask_user\` for a given question, never both. \`ask_user\` is the one that reaches the user when they are away from this machine, so prefer it. Raising both strands the user in whichever prompt you are not waiting on.
|
|
280
279
|
- Honor authorization already granted in this session. Ask before a risky or irreversible action outside that authorization, or when an enforced host policy requires it. Do not ask again for an already authorized step, and never bypass an enforced gate. When a Pushary hook result says the user approved a specific command after a denial, rerunning that exact command is the approved path and not a bypass of that gate.
|
|
281
|
-
- Call \`propose_scope\` only for an unresolved or requested file boundary. A ratified scope narrows what may proceed; it does not bypass other approval rules. Do not add a plan approval merely because work spans several files, and do not propose a new scope mid-run just to widen it. Let the installed gate request any scope expansion before the edit executes.
|
|
280
|
+
- Call \`propose_scope\` only for an unresolved or requested file boundary. A ratified scope narrows what may proceed; it does not bypass other approval rules. Do not add a plan approval merely because work spans several files, and do not propose a new scope mid-run just to widen it. Let the installed gate request any scope expansion before the edit executes. Only file paths are checked, and only on tool calls that carry one, so put a boundary that is not a path (recipients, channels, spend, systems you will not open) in \`promises\` and never in \`allowedPaths\`. Read the \`enforces\` field that comes back: an empty array means nothing in that contract is checked automatically, and you must say so rather than report that a scope is in force. \`hookSeen: false\` means no hook has reported that sessionId, so the gate will never find the contract: fix the session id rather than proceeding as if a scope were in force.
|
|
281
|
+
- Before a task of more than two steps, break it into steps and find the forks. Settle by yourself every fork that a file, a command or a tool call can answer, then ask the rest as one numbered round with your recommended answer against each. A question in the terminal is free; a push is not. When the user is at the terminal, ask the whole round there. When the user is away, send only the fork that stops the run, and decide the rest on your recommendation.
|
|
282
282
|
- When you are blocked, stuck, or hit an error you cannot resolve on your own, call \`send_notification\` so the user knows, and call \`ask_user\` if you need a decision to continue.
|
|
283
283
|
- When meaningful work finishes while the user is away, or they requested an alert, call \`send_notification\` so the user knows it is done. Skip trivial completions and duplicate reports to someone already reading. Always pass \`context\` with a \`type\` of "task_complete", "error" or "info": it is what tells Pushary this is a task update, so the user's own setting for where updates land can route it.
|
|
284
284
|
- Confirm notifications can offer lock-screen actions; arbitrary choices and text open the app. The Mac notch handles personal account questions, not Partner customer enrollment.
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
canonicalGateInputs
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-5AATCXJN.js";
|
|
4
4
|
import {
|
|
5
5
|
canonicalJson
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-PX53RT6Q.js";
|
|
7
7
|
import {
|
|
8
8
|
writeFileAtomic
|
|
9
9
|
} from "./chunk-4LL6LG5X.js";
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
BLOCKED_ACTION_GRANT_TTL_SECONDS,
|
|
12
12
|
blockedActionIdentity,
|
|
13
13
|
shouldDeferToNativeMode
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-7DQVIIHX.js";
|
|
15
15
|
|
|
16
16
|
// src/native-defer.ts
|
|
17
17
|
var nativeDeferOptions = () => {
|
|
@@ -2,17 +2,17 @@ import {
|
|
|
2
2
|
CLAUDE_HOOK_EVENTS,
|
|
3
3
|
GEMINI_HOOK_EVENTS,
|
|
4
4
|
hasGeminiHooks
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-ERP7FOFQ.js";
|
|
6
6
|
import {
|
|
7
7
|
CODEX_HOOK_EVENTS,
|
|
8
8
|
hasCodexHooks,
|
|
9
9
|
holdBudgetOf
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-PX53RT6Q.js";
|
|
11
11
|
import {
|
|
12
12
|
CURSOR_GATE_EVENTS,
|
|
13
13
|
HOOK_LOCATOR_BINARY,
|
|
14
14
|
hookCommandHoldBudget
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-7DQVIIHX.js";
|
|
16
16
|
|
|
17
17
|
// src/diagnostics/wiring.ts
|
|
18
18
|
var record = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
@@ -2,10 +2,10 @@ import {
|
|
|
2
2
|
resolveBinary,
|
|
3
3
|
resolveGlobalPackageVersion,
|
|
4
4
|
resolvePackageVersionFromBinary
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-PX53RT6Q.js";
|
|
6
6
|
import {
|
|
7
7
|
MANAGED_PROVIDERS
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-7DQVIIHX.js";
|
|
9
9
|
|
|
10
10
|
// src/live-capabilities.ts
|
|
11
11
|
var CLAUDE_BRIDGE_CAPABILITY = "claude-bridge";
|
|
@@ -4,17 +4,17 @@ import {
|
|
|
4
4
|
} from "./chunk-XHKBHWLX.js";
|
|
5
5
|
import {
|
|
6
6
|
getMachineId
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-KZPUARCU.js";
|
|
8
8
|
import {
|
|
9
9
|
pusharyDir,
|
|
10
10
|
resolveGlobalBinary
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-PX53RT6Q.js";
|
|
12
12
|
import {
|
|
13
13
|
getPackageVersion
|
|
14
14
|
} from "./chunk-DINDL2CF.js";
|
|
15
15
|
import {
|
|
16
16
|
readControlMode
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-7TDQ7KDY.js";
|
|
18
18
|
import {
|
|
19
19
|
readJsonSafe,
|
|
20
20
|
writeFileAtomic,
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import {
|
|
2
2
|
detectClaudeVersion
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-JQJB7BZE.js";
|
|
4
4
|
import {
|
|
5
5
|
addClaudeMcpServer,
|
|
6
6
|
addPusharyHooks,
|
|
7
7
|
addPusharyToolPermissions
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-PX54KULQ.js";
|
|
9
9
|
import {
|
|
10
10
|
claudeUnprovenHolds,
|
|
11
11
|
claudeWired,
|
|
12
12
|
codexUnprovenHolds,
|
|
13
13
|
codexWired,
|
|
14
14
|
geminiWired
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-C3WH44MH.js";
|
|
16
16
|
import {
|
|
17
17
|
CLAUDE_HOOK_BINARY,
|
|
18
18
|
CLAUDE_HOOK_EVENTS,
|
|
@@ -24,7 +24,7 @@ import {
|
|
|
24
24
|
needsReregistration,
|
|
25
25
|
registrationSignatures,
|
|
26
26
|
supportedClaudeEvents
|
|
27
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-ERP7FOFQ.js";
|
|
28
28
|
import {
|
|
29
29
|
CODEX_HOOK_BINARY,
|
|
30
30
|
addCodexHookTrust,
|
|
@@ -44,7 +44,7 @@ import {
|
|
|
44
44
|
registrationHolderOf,
|
|
45
45
|
resolveGlobalBinary,
|
|
46
46
|
vscodePluginMcp
|
|
47
|
-
} from "./chunk-
|
|
47
|
+
} from "./chunk-PX53RT6Q.js";
|
|
48
48
|
import {
|
|
49
49
|
readJsonSafe,
|
|
50
50
|
writeFileAtomic,
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import {
|
|
2
2
|
NOTIFICATION_MATCHED_TYPES,
|
|
3
3
|
POSTTOOLUSE_MIRRORED_TOOLS
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-UWP66NDF.js";
|
|
5
5
|
import {
|
|
6
6
|
isProtectedByScope,
|
|
7
7
|
registerHookEntry
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-PX53RT6Q.js";
|
|
9
9
|
import {
|
|
10
10
|
CLAUDE_PRETOOLUSE_MATCHER,
|
|
11
11
|
HOOK_BUDGETS,
|
|
12
12
|
HOOK_LOCATOR_BINARY
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-7DQVIIHX.js";
|
|
14
14
|
|
|
15
15
|
// src/gemini-config.ts
|
|
16
16
|
var GEMINI_HOOK_BINARY = "pushary-gemini-hook";
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import {
|
|
2
2
|
activeIdentity
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-YT6H7BB5.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-BXLFUTSD.js";
|
|
11
11
|
import {
|
|
12
12
|
isGatingMoment,
|
|
13
13
|
recordKeylessMoment
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-2DT7STR5.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-5AATCXJN.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-KZPUARCU.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-7DQVIIHX.js";
|
|
77
77
|
|
|
78
78
|
// src/decision-episode.ts
|
|
79
79
|
var EPISODE_PATH = "/api/agent/decision-episode";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
SETUP_FLAGS
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-WC5PYFDK.js";
|
|
4
4
|
import {
|
|
5
5
|
parseFlags
|
|
6
6
|
} from "./chunk-GMXKITVA.js";
|
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
CLAUDE_CONNECTOR_URL,
|
|
15
15
|
COWORK_CONNECTOR_LIMIT,
|
|
16
16
|
COWORK_STANDING_INSTRUCTIONS
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-7DQVIIHX.js";
|
|
18
18
|
|
|
19
19
|
// src/cli/cowork.ts
|
|
20
20
|
import { readFileSync } from "fs";
|
|
@@ -6,16 +6,16 @@ import {
|
|
|
6
6
|
} from "./chunk-YKLCWWEI.js";
|
|
7
7
|
import {
|
|
8
8
|
hookOwnerOf
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-W6XVHP4U.js";
|
|
10
10
|
import {
|
|
11
11
|
ensureDaemonRunning
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-CVCSUAXI.js";
|
|
13
13
|
import {
|
|
14
14
|
buildTranscriptRecords,
|
|
15
15
|
decodePublicKey,
|
|
16
16
|
generateSessionKey,
|
|
17
17
|
wrapSessionKey
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-6QCN5XQE.js";
|
|
19
19
|
import {
|
|
20
20
|
fetchTranscriptRecipients,
|
|
21
21
|
uploadTranscriptRecords
|
|
@@ -23,14 +23,14 @@ import {
|
|
|
23
23
|
import {
|
|
24
24
|
transcriptEnvironmentPreference,
|
|
25
25
|
transcriptsEnabled
|
|
26
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-KHTBSSY5.js";
|
|
27
27
|
import {
|
|
28
28
|
codexHome,
|
|
29
29
|
pusharyDir
|
|
30
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-PX53RT6Q.js";
|
|
31
31
|
import {
|
|
32
32
|
readTranscriptPreference
|
|
33
|
-
} from "./chunk-
|
|
33
|
+
} from "./chunk-7TDQ7KDY.js";
|
|
34
34
|
import {
|
|
35
35
|
writeJsonAtomic
|
|
36
36
|
} from "./chunk-4LL6LG5X.js";
|