@pushary/agent-hooks 0.85.1 → 0.86.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 +26 -0
- package/dist/bin/pushary-bell-hook.js +4 -4
- package/dist/bin/pushary-bell.js +5 -5
- package/dist/bin/pushary-claude.js +7 -7
- package/dist/bin/pushary-clean.js +9 -8
- package/dist/bin/pushary-codex-bridge.js +5 -5
- package/dist/bin/pushary-codex-hook.js +4 -4
- package/dist/bin/pushary-codex.js +3 -3
- package/dist/bin/pushary-connect.js +6 -6
- package/dist/bin/pushary-daemon.js +4 -4
- package/dist/bin/pushary-disconnect.js +7 -6
- package/dist/bin/pushary-doctor.js +11 -11
- package/dist/bin/pushary-gemini-bridge.js +5 -5
- package/dist/bin/pushary-gemini-hook.js +12 -7
- package/dist/bin/pushary-hook.js +6 -8
- package/dist/bin/pushary-login.js +4 -4
- package/dist/bin/pushary-logout.js +4 -4
- package/dist/bin/pushary-mode.js +3 -3
- package/dist/bin/pushary-notification-hook.js +3 -3
- package/dist/bin/pushary-permission-denied-hook.js +6 -8
- package/dist/bin/pushary-permission-hook.js +6 -8
- package/dist/bin/pushary-post-hook.js +3 -3
- package/dist/bin/pushary-prompt-hook.js +3 -3
- package/dist/bin/pushary-session-end-hook.js +3 -3
- package/dist/bin/pushary-session-start-hook.js +3 -3
- package/dist/bin/pushary-setup.js +20 -19
- package/dist/bin/pushary-stats.js +2 -2
- package/dist/bin/pushary-status.js +5 -5
- package/dist/bin/pushary-stop-hook.js +3 -3
- package/dist/bin/pushary-stopfailure-hook.js +3 -3
- package/dist/bin/pushary-upgrade.js +10 -9
- package/dist/bin/pushary-wait.js +3 -3
- package/dist/{chunk-EZPRY2ZY.js → chunk-2255DZ74.js} +1 -1
- package/dist/{chunk-OZKRF7MS.js → chunk-2C6B6V2U.js} +7 -3
- package/dist/{chunk-QDKJTPAT.js → chunk-2TZCZ7CL.js} +1 -1
- package/dist/{chunk-Y7BALRVB.js → chunk-33T5OOKP.js} +19 -34
- package/dist/{chunk-KTKIZEFT.js → chunk-5EUZYWID.js} +1 -1
- package/dist/{chunk-ES3FAX5X.js → chunk-7C5CJC3H.js} +1 -1
- package/dist/{chunk-CIVG746V.js → chunk-7G5VO76N.js} +1 -1
- package/dist/chunk-ATBKJNWS.js +19 -0
- package/dist/{chunk-G3LXA2ZP.js → chunk-CY4TZK5O.js} +59 -1
- package/dist/{chunk-XIR6N66V.js → chunk-FOY5FISQ.js} +1 -1
- package/dist/{chunk-GM54KC62.js → chunk-GK4CED6Z.js} +12 -18
- package/dist/{chunk-VGADRFG6.js → chunk-MNQI6ZZU.js} +1 -1
- package/dist/{chunk-XLM6COJA.js → chunk-MTKR4YLW.js} +1 -1
- package/dist/{chunk-DNSIVHIA.js → chunk-N52CIK47.js} +1 -1
- package/dist/{chunk-BZKTCOZQ.js → chunk-PZR4XMFU.js} +1 -1
- package/dist/{chunk-VKJUVPTJ.js → chunk-Q7N3XGWM.js} +2 -2
- package/dist/{chunk-IGV4KL7B.js → chunk-QW27ZFA4.js} +2 -2
- package/dist/{chunk-LB6RSCLL.js → chunk-S3UD7O35.js} +59 -45
- package/dist/{chunk-PHXEADSL.js → chunk-VPJAAGD4.js} +7 -3
- package/dist/{chunk-55656H4Q.js → chunk-VZNDR3Z7.js} +1 -1
- package/dist/{chunk-JDQY47OW.js → chunk-XPAGN3SC.js} +1 -1
- package/dist/src/index.d.ts +3 -10
- package/dist/src/index.js +6 -8
- package/package.json +1 -1
|
@@ -65,6 +65,7 @@ var hookWaitDeadline = (startMs, policyWaitSeconds, agent, nowMs) => {
|
|
|
65
65
|
};
|
|
66
66
|
var hookWaitClamped = (startMs, policyWaitSeconds, agent, nowMs) => startMs + hookMaxWaitSeconds(agent) * 1e3 < nowMs + Math.max(policyWaitSeconds, 0) * 1e3;
|
|
67
67
|
var effectiveWaitSeconds = (timeoutAction, policySeconds, agent) => timeoutAction === "wait" ? hookMaxWaitSeconds(agent) : policySeconds;
|
|
68
|
+
var HOOK_LOCATOR_BINARY = "pushary-bridge";
|
|
68
69
|
var HOOK_BATCH_MAX_BYTES = 4 * 1024 * 1024;
|
|
69
70
|
var REPO_KEY_MAX_LENGTH = 200;
|
|
70
71
|
var isRepoKeyMatch = (ruleRepoKey, currentRepoKey) => {
|
|
@@ -502,6 +503,8 @@ var selectGoverningRule = (policies, toolName, args, repoKey, sessionId) => {
|
|
|
502
503
|
}
|
|
503
504
|
return best;
|
|
504
505
|
};
|
|
506
|
+
var ARG_PREFIX_TARGET_TOOLS = Object.keys(POLICY_COMMAND_KEYS);
|
|
507
|
+
var FILE_TARGET_TOOLS = /* @__PURE__ */ new Set(["Edit", "Write", "MultiEdit"]);
|
|
505
508
|
var API_KEY_PATTERN = /^pk_[a-f0-9]+\.[a-f0-9]+$/;
|
|
506
509
|
var isValidApiKey = (value) => API_KEY_PATTERN.test(value);
|
|
507
510
|
var ACTION_BODY_MAX = 4e3;
|
|
@@ -1035,6 +1038,56 @@ var modeStateFromResponse = (data) => {
|
|
|
1035
1038
|
degraded: false
|
|
1036
1039
|
};
|
|
1037
1040
|
};
|
|
1041
|
+
var claudePreToolUseOutput = (decision, reason, updatedInput) => ({
|
|
1042
|
+
hookSpecificOutput: {
|
|
1043
|
+
hookEventName: "PreToolUse",
|
|
1044
|
+
permissionDecision: decision,
|
|
1045
|
+
...reason ? { permissionDecisionReason: reason } : {},
|
|
1046
|
+
...updatedInput ? { updatedInput } : {}
|
|
1047
|
+
}
|
|
1048
|
+
});
|
|
1049
|
+
var claudePermissionRequestOutput = (decision, reason, updatedInput) => ({
|
|
1050
|
+
hookSpecificOutput: {
|
|
1051
|
+
hookEventName: "PermissionRequest",
|
|
1052
|
+
decision: decision === "allow" ? { behavior: "allow", ...updatedInput ? { updatedInput } : {} } : { behavior: "deny", ...reason ? { message: reason } : {} }
|
|
1053
|
+
}
|
|
1054
|
+
});
|
|
1055
|
+
var gateOutputFor = (source, event, decision, reason) => {
|
|
1056
|
+
let output;
|
|
1057
|
+
if (source === "claude") {
|
|
1058
|
+
if (event === "PreToolUse") {
|
|
1059
|
+
output = claudePreToolUseOutput(decision, reason);
|
|
1060
|
+
} else if (event === "PermissionRequest" && decision !== "ask") {
|
|
1061
|
+
output = claudePermissionRequestOutput(decision, reason);
|
|
1062
|
+
}
|
|
1063
|
+
} else if (source === "codex") {
|
|
1064
|
+
if (event === "PermissionRequest" && decision !== "ask") {
|
|
1065
|
+
output = {
|
|
1066
|
+
hookSpecificOutput: {
|
|
1067
|
+
hookEventName: "PermissionRequest",
|
|
1068
|
+
decision: decision === "allow" ? { behavior: "allow" } : { behavior: "deny", message: reason ?? "Denied from Pushary" }
|
|
1069
|
+
}
|
|
1070
|
+
};
|
|
1071
|
+
} else if (event === "PreToolUse" && decision === "deny") {
|
|
1072
|
+
output = {
|
|
1073
|
+
hookSpecificOutput: {
|
|
1074
|
+
hookEventName: "PreToolUse",
|
|
1075
|
+
permissionDecision: "deny",
|
|
1076
|
+
permissionDecisionReason: reason ?? "Denied from Pushary"
|
|
1077
|
+
}
|
|
1078
|
+
};
|
|
1079
|
+
}
|
|
1080
|
+
} else if (source === "gemini" && event === "BeforeTool" && decision !== "ask") {
|
|
1081
|
+
output = decision === "allow" ? { decision: "allow" } : { decision: "deny", reason: reason ?? "Denied from Pushary" };
|
|
1082
|
+
} else if (source === "cursor" && event === "beforeShellExecution") {
|
|
1083
|
+
output = decision === "allow" ? { permission: "allow" } : decision === "ask" ? { permission: "ask" } : {
|
|
1084
|
+
permission: "deny",
|
|
1085
|
+
user_message: "Command denied via Pushary.",
|
|
1086
|
+
agent_message: reason ?? "Denied from Pushary"
|
|
1087
|
+
};
|
|
1088
|
+
}
|
|
1089
|
+
return output;
|
|
1090
|
+
};
|
|
1038
1091
|
|
|
1039
1092
|
export {
|
|
1040
1093
|
parseAgentQuestionAnswers,
|
|
@@ -1043,10 +1096,12 @@ export {
|
|
|
1043
1096
|
hookWaitDeadline,
|
|
1044
1097
|
hookWaitClamped,
|
|
1045
1098
|
effectiveWaitSeconds,
|
|
1099
|
+
HOOK_LOCATOR_BINARY,
|
|
1046
1100
|
normalizeRepoRemote,
|
|
1047
1101
|
localRepoKey,
|
|
1048
1102
|
isSafeReadOnlyCommand,
|
|
1049
1103
|
isAutoApprove,
|
|
1104
|
+
FILE_TARGET_TOOLS,
|
|
1050
1105
|
isValidApiKey,
|
|
1051
1106
|
ACTION_BODY_MAX,
|
|
1052
1107
|
DECISION_LINE_MAX,
|
|
@@ -1057,5 +1112,8 @@ export {
|
|
|
1057
1112
|
resolvePolicy,
|
|
1058
1113
|
KILL_REASON,
|
|
1059
1114
|
resolveGate,
|
|
1060
|
-
modeStateFromResponse
|
|
1115
|
+
modeStateFromResponse,
|
|
1116
|
+
claudePreToolUseOutput,
|
|
1117
|
+
claudePermissionRequestOutput,
|
|
1118
|
+
gateOutputFor
|
|
1061
1119
|
};
|
|
@@ -1,9 +1,14 @@
|
|
|
1
|
+
import {
|
|
2
|
+
PRETOOLUSE_GATED_TOOLS,
|
|
3
|
+
PRETOOLUSE_PHONE_ANSWERED_TOOLS
|
|
4
|
+
} from "./chunk-ATBKJNWS.js";
|
|
1
5
|
import {
|
|
2
6
|
guardBinary
|
|
3
7
|
} from "./chunk-HSGEEBBL.js";
|
|
4
8
|
import {
|
|
5
|
-
HOOK_BUDGETS
|
|
6
|
-
|
|
9
|
+
HOOK_BUDGETS,
|
|
10
|
+
HOOK_LOCATOR_BINARY
|
|
11
|
+
} from "./chunk-CY4TZK5O.js";
|
|
7
12
|
|
|
8
13
|
// src/claude-config.ts
|
|
9
14
|
import { join } from "path";
|
|
@@ -21,21 +26,8 @@ var compareVersion = (a, b) => {
|
|
|
21
26
|
};
|
|
22
27
|
var atLeast = (version, floor) => compareVersion(version, floor) >= 0;
|
|
23
28
|
|
|
24
|
-
// src/claude-tools.ts
|
|
25
|
-
var PRETOOLUSE_GATED_TOOLS = [
|
|
26
|
-
"Bash",
|
|
27
|
-
"Write",
|
|
28
|
-
"Edit",
|
|
29
|
-
"MultiEdit",
|
|
30
|
-
"NotebookEdit",
|
|
31
|
-
"PowerShell",
|
|
32
|
-
"Monitor"
|
|
33
|
-
];
|
|
34
|
-
var POSTTOOLUSE_MIRRORED_TOOLS = [...PRETOOLUSE_GATED_TOOLS, "TodoWrite"];
|
|
35
|
-
var PRETOOLUSE_HANDLED_TOOLS = /* @__PURE__ */ new Set([...PRETOOLUSE_GATED_TOOLS, "AskUserQuestion"]);
|
|
36
|
-
|
|
37
29
|
// src/claude-events.ts
|
|
38
|
-
var GATED_TOOLS = [...PRETOOLUSE_GATED_TOOLS,
|
|
30
|
+
var GATED_TOOLS = [...PRETOOLUSE_GATED_TOOLS, ...PRETOOLUSE_PHONE_ANSWERED_TOOLS].join("|");
|
|
39
31
|
var MIRRORED_TOOLS = [...PRETOOLUSE_GATED_TOOLS, "TodoWrite"].join("|");
|
|
40
32
|
var ESTABLISHED = [1, 0, 0];
|
|
41
33
|
var OBSERVED = [2, 0, 0];
|
|
@@ -72,7 +64,10 @@ var ensureRecord = (target, key) => {
|
|
|
72
64
|
return created;
|
|
73
65
|
};
|
|
74
66
|
var isPusharyPermission = (rule) => typeof rule === "string" && (rule.includes("pushary") || rule.includes("MCP(pushary"));
|
|
75
|
-
var HOOK_BINARIES = new Set(
|
|
67
|
+
var HOOK_BINARIES = /* @__PURE__ */ new Set([
|
|
68
|
+
...CLAUDE_HOOK_EVENTS.map((hook) => hook.binary),
|
|
69
|
+
HOOK_LOCATOR_BINARY
|
|
70
|
+
]);
|
|
76
71
|
var namesPusharyBinary = (command) => command.split(/[\s/\\"']+/).some((segment) => HOOK_BINARIES.has(segment.replace(/\.(cmd|exe)$/i, "")));
|
|
77
72
|
var isPusharyHook = (entry2) => {
|
|
78
73
|
const hooks = asRecord(entry2)?.hooks;
|
|
@@ -178,7 +173,6 @@ var removePusharySettings = (settings) => {
|
|
|
178
173
|
export {
|
|
179
174
|
parseVersion,
|
|
180
175
|
compareVersion,
|
|
181
|
-
PRETOOLUSE_HANDLED_TOOLS,
|
|
182
176
|
addClaudeMcpServer,
|
|
183
177
|
removeClaudeMcpServers,
|
|
184
178
|
addPusharyToolPermissions,
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
hasGeminiHooks
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-2C6B6V2U.js";
|
|
4
4
|
import {
|
|
5
5
|
hasCodexHooks
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-VPJAAGD4.js";
|
|
7
7
|
|
|
8
8
|
// src/diagnostics/wiring.ts
|
|
9
9
|
var record = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
codexHomeFrom
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-VPJAAGD4.js";
|
|
4
4
|
|
|
5
5
|
// src/vscode-config.ts
|
|
6
6
|
import { homedir } from "os";
|
|
@@ -253,7 +253,7 @@ You have Pushary MCP tools that reach the user on their phone. Use them proactiv
|
|
|
253
253
|
|
|
254
254
|
- 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. \`ask_user\` blocks until the user replies or it times out, so you do not need a separate wait step.
|
|
255
255
|
- Before any risky or irreversible step (deleting files, force pushing, spending money, sending external messages), call \`ask_user\` with type "confirm" and wait for approval.
|
|
256
|
-
- Before starting a multi-step run that will change several files, call \`propose_scope\` once with the paths you expect to change, anything you promise not to touch, and what done means. The user agrees to the boundary in one tap,
|
|
256
|
+
- Before starting a multi-step run that will change several files, call \`propose_scope\` once with the paths you expect to change, anything you promise not to touch, and what done means. The user agrees to the boundary in one tap. A ratified boundary NARROWS what may proceed without asking, it does not pre-approve work inside it, so an action that would normally need approval still needs it. Skip it for a single quick edit, and do not propose a new scope mid-run just to widen one: if you need to go outside the agreed scope, do the work and let the approval that follows widen it.
|
|
257
257
|
- 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.
|
|
258
258
|
- When a task that took several steps finishes, call \`send_notification\` so the user knows it is done. 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.
|
|
259
259
|
- Use \`cancel_question\` to retract a pending question once it is no longer needed.
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
|
-
PRETOOLUSE_HANDLED_TOOLS
|
|
3
|
-
|
|
2
|
+
PRETOOLUSE_HANDLED_TOOLS,
|
|
3
|
+
PRETOOLUSE_PHONE_ANSWERED_TOOLS
|
|
4
|
+
} from "./chunk-ATBKJNWS.js";
|
|
4
5
|
import {
|
|
5
6
|
isGatingMoment,
|
|
6
7
|
recordKeylessMoment
|
|
7
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-MNQI6ZZU.js";
|
|
8
9
|
import {
|
|
9
10
|
denyReasonFrom,
|
|
10
11
|
isDeferAnswer
|
|
@@ -28,7 +29,7 @@ import {
|
|
|
28
29
|
sendNotification,
|
|
29
30
|
throttlePass,
|
|
30
31
|
waitForAnswer
|
|
31
|
-
} from "./chunk-
|
|
32
|
+
} from "./chunk-33T5OOKP.js";
|
|
32
33
|
import {
|
|
33
34
|
getMachineId
|
|
34
35
|
} from "./chunk-RN3NOEJF.js";
|
|
@@ -38,12 +39,14 @@ import {
|
|
|
38
39
|
} from "./chunk-2UMNXADU.js";
|
|
39
40
|
import {
|
|
40
41
|
buildDecisionEpisodeFeatures,
|
|
42
|
+
claudePermissionRequestOutput,
|
|
43
|
+
claudePreToolUseOutput,
|
|
41
44
|
effectiveWaitSeconds,
|
|
42
45
|
hookWaitClamped,
|
|
43
46
|
hookWaitDeadline,
|
|
44
47
|
parseAgentQuestionAnswers,
|
|
45
48
|
resolveGate
|
|
46
|
-
} from "./chunk-
|
|
49
|
+
} from "./chunk-CY4TZK5O.js";
|
|
47
50
|
|
|
48
51
|
// src/decision-episode.ts
|
|
49
52
|
var EPISODE_PATH = "/api/agent/decision-episode";
|
|
@@ -73,33 +76,10 @@ import { tmpdir } from "os";
|
|
|
73
76
|
import { existsSync, writeFileSync } from "fs";
|
|
74
77
|
var sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
75
78
|
var START_MS = Date.now();
|
|
76
|
-
var allow = () => (
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
}
|
|
81
|
-
});
|
|
82
|
-
var deny = (reason) => ({
|
|
83
|
-
hookSpecificOutput: {
|
|
84
|
-
hookEventName: "PreToolUse",
|
|
85
|
-
permissionDecision: "deny",
|
|
86
|
-
permissionDecisionReason: reason
|
|
87
|
-
}
|
|
88
|
-
});
|
|
89
|
-
var allowWithInput = (updatedInput) => ({
|
|
90
|
-
hookSpecificOutput: {
|
|
91
|
-
hookEventName: "PreToolUse",
|
|
92
|
-
permissionDecision: "allow",
|
|
93
|
-
updatedInput
|
|
94
|
-
}
|
|
95
|
-
});
|
|
96
|
-
var ask = (reason) => ({
|
|
97
|
-
hookSpecificOutput: {
|
|
98
|
-
hookEventName: "PreToolUse",
|
|
99
|
-
permissionDecision: "ask",
|
|
100
|
-
...reason ? { permissionDecisionReason: reason } : {}
|
|
101
|
-
}
|
|
102
|
-
});
|
|
79
|
+
var allow = () => claudePreToolUseOutput("allow");
|
|
80
|
+
var deny = (reason) => claudePreToolUseOutput("deny", reason);
|
|
81
|
+
var allowWithInput = (updatedInput) => claudePreToolUseOutput("allow", void 0, updatedInput);
|
|
82
|
+
var ask = (reason) => claudePreToolUseOutput("ask", reason);
|
|
103
83
|
var pollForAnswer = async (apiKey, correlationId, deadlineMs, pollInterval = 2e3) => {
|
|
104
84
|
while (Date.now() < deadlineMs) {
|
|
105
85
|
const remaining = Math.min(Math.max(deadlineMs - Date.now(), 1e3), 3e4);
|
|
@@ -469,6 +449,47 @@ var handleAskUserQuestion = async (apiKey, input) => {
|
|
|
469
449
|
if (!answers) return void 0;
|
|
470
450
|
return allowWithInput({ ...input.tool_input ?? {}, answers });
|
|
471
451
|
};
|
|
452
|
+
var PLAN_APPROVE = "Approve, start coding";
|
|
453
|
+
var PLAN_KEEP_PLANNING = "Keep planning";
|
|
454
|
+
var handleExitPlanMode = async (apiKey, input) => {
|
|
455
|
+
const toolInput = input.tool_input ?? {};
|
|
456
|
+
const projectName = basename(input.cwd ?? process.cwd());
|
|
457
|
+
let result;
|
|
458
|
+
try {
|
|
459
|
+
result = await askUser(apiKey, {
|
|
460
|
+
question: `Approve the plan and start coding in ${projectName}?`,
|
|
461
|
+
type: "select",
|
|
462
|
+
options: [PLAN_APPROVE, PLAN_KEEP_PLANNING],
|
|
463
|
+
context: `Your agent finished planning in ${projectName} and is waiting to start.`,
|
|
464
|
+
agentName: `Claude Code - ${projectName}`,
|
|
465
|
+
sessionId: input.session_id,
|
|
466
|
+
machineId: getMachineId(),
|
|
467
|
+
toolName: "ExitPlanMode",
|
|
468
|
+
action: deriveAction("ExitPlanMode", toolInput),
|
|
469
|
+
// The plan markdown itself, through the same redaction and cap as any diff,
|
|
470
|
+
// so approving from a lock screen is a real decision and not a blind yes.
|
|
471
|
+
actionBody: deriveActionBody("ExitPlanMode", toolInput),
|
|
472
|
+
intent: readLastPrompt(input.session_id ?? DEFAULT_SESSION) ?? (input.transcript_path ? readLastUserPrompt(input.transcript_path) : void 0),
|
|
473
|
+
blocker: "Waiting for you to approve the plan"
|
|
474
|
+
});
|
|
475
|
+
} catch {
|
|
476
|
+
return void 0;
|
|
477
|
+
}
|
|
478
|
+
if (result.suppressed || result.noDevices) {
|
|
479
|
+
await cancelQuestion(apiKey, result.correlationId).catch(() => {
|
|
480
|
+
});
|
|
481
|
+
return void 0;
|
|
482
|
+
}
|
|
483
|
+
const deadline = hookWaitDeadline(START_MS, effectiveWaitSeconds("wait", 0, "claude"), "claude", Date.now());
|
|
484
|
+
const answer = await pollForAnswer(apiKey, result.correlationId, deadline);
|
|
485
|
+
const value = answer.answered ? (answer.value ?? "").trim() : "";
|
|
486
|
+
if (!value || isDeferAnswer(answer.value)) {
|
|
487
|
+
savePendingQuestion(input.session_id || DEFAULT_SESSION, result.correlationId);
|
|
488
|
+
return void 0;
|
|
489
|
+
}
|
|
490
|
+
if (value === PLAN_APPROVE) return allow();
|
|
491
|
+
return deny("Plan declined from the phone. Ask what to change before coding.");
|
|
492
|
+
};
|
|
472
493
|
var handleKeyless = (input) => {
|
|
473
494
|
try {
|
|
474
495
|
if (isGatingMoment(input.tool_name, input.tool_input ?? {})) {
|
|
@@ -514,6 +535,9 @@ var handlePreToolUse = async (input) => {
|
|
|
514
535
|
return handleAskUserQuestion(apiKey, input);
|
|
515
536
|
}
|
|
516
537
|
if (verdict.kind === "deny") return deny(verdict.reason);
|
|
538
|
+
if (input.tool_name === "ExitPlanMode") {
|
|
539
|
+
return handleExitPlanMode(apiKey, input);
|
|
540
|
+
}
|
|
517
541
|
if (shouldDeferToNativeMode(input.permission_mode, input.tool_name)) {
|
|
518
542
|
return void 0;
|
|
519
543
|
}
|
|
@@ -534,18 +558,8 @@ var handlePreToolUse = async (input) => {
|
|
|
534
558
|
return void 0;
|
|
535
559
|
}
|
|
536
560
|
};
|
|
537
|
-
var permReqAllow = (updatedInput) => (
|
|
538
|
-
|
|
539
|
-
hookEventName: "PermissionRequest",
|
|
540
|
-
decision: { behavior: "allow", ...updatedInput ? { updatedInput } : {} }
|
|
541
|
-
}
|
|
542
|
-
});
|
|
543
|
-
var permReqDeny = (message) => ({
|
|
544
|
-
hookSpecificOutput: {
|
|
545
|
-
hookEventName: "PermissionRequest",
|
|
546
|
-
decision: { behavior: "deny", ...message ? { message } : {} }
|
|
547
|
-
}
|
|
548
|
-
});
|
|
561
|
+
var permReqAllow = (updatedInput) => claudePermissionRequestOutput("allow", void 0, updatedInput);
|
|
562
|
+
var permReqDeny = (message) => claudePermissionRequestOutput("deny", message);
|
|
549
563
|
var toPermissionRequestOutput = (hookOutput) => {
|
|
550
564
|
if (!hookOutput) return void 0;
|
|
551
565
|
const d = hookOutput.hookSpecificOutput;
|
|
@@ -555,7 +569,7 @@ var toPermissionRequestOutput = (hookOutput) => {
|
|
|
555
569
|
};
|
|
556
570
|
var handlePermissionRequest = async (input) => {
|
|
557
571
|
if (PRETOOLUSE_HANDLED_TOOLS.has(input.tool_name)) {
|
|
558
|
-
const reclaimDeferredExec = input.tool_name
|
|
572
|
+
const reclaimDeferredExec = !PRETOOLUSE_PHONE_ANSWERED_TOOLS.includes(input.tool_name) && shouldDeferToNativeMode(input.permission_mode, input.tool_name);
|
|
559
573
|
if (!reclaimDeferredExec) return void 0;
|
|
560
574
|
}
|
|
561
575
|
if (input.tool_name.startsWith("mcp__pushary__")) return void 0;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
|
-
HOOK_BUDGETS
|
|
3
|
-
|
|
2
|
+
HOOK_BUDGETS,
|
|
3
|
+
HOOK_LOCATOR_BINARY
|
|
4
|
+
} from "./chunk-CY4TZK5O.js";
|
|
4
5
|
|
|
5
6
|
// src/codex-config.ts
|
|
6
7
|
import { createHash } from "crypto";
|
|
@@ -63,7 +64,10 @@ var readCodexMcpAuth = (config) => {
|
|
|
63
64
|
var isPusharyCodexHook = (entry) => {
|
|
64
65
|
const hooks = asRecord(entry)?.hooks;
|
|
65
66
|
if (!Array.isArray(hooks)) return false;
|
|
66
|
-
return hooks.some((hook) =>
|
|
67
|
+
return hooks.some((hook) => {
|
|
68
|
+
const command = String(asRecord(hook)?.command ?? "");
|
|
69
|
+
return command.includes(CODEX_HOOK_BINARY) || command.includes(HOOK_LOCATOR_BINARY);
|
|
70
|
+
});
|
|
67
71
|
};
|
|
68
72
|
var addCodexHooks = (config, command) => {
|
|
69
73
|
const hooks = ensureRecord(config, "hooks");
|
package/dist/src/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { PolicyConfig, ApprovalMode, ModeState, AutoResolveOrigin, AgentQuestion } from '@pushary/contracts';
|
|
1
|
+
import { ClaudePreToolUseOutput, PolicyConfig, ApprovalMode, ModeState, AutoResolveOrigin, AgentQuestion } from '@pushary/contracts';
|
|
3
2
|
export { ApprovalMode, ModeState, PolicyConfig, ToolPolicy, resolvePolicy } from '@pushary/contracts';
|
|
3
|
+
import { ReceiptMeta } from '@pushary/hook-mapping';
|
|
4
4
|
|
|
5
5
|
interface ToolInput {
|
|
6
6
|
tool_name: string;
|
|
@@ -11,14 +11,7 @@ interface ToolInput {
|
|
|
11
11
|
tool_use_id?: string;
|
|
12
12
|
permission_mode?: string;
|
|
13
13
|
}
|
|
14
|
-
|
|
15
|
-
hookSpecificOutput: {
|
|
16
|
-
hookEventName: 'PreToolUse';
|
|
17
|
-
permissionDecision: 'allow' | 'deny' | 'ask';
|
|
18
|
-
permissionDecisionReason?: string;
|
|
19
|
-
updatedInput?: Record<string, unknown>;
|
|
20
|
-
};
|
|
21
|
-
}
|
|
14
|
+
type HookOutput = ClaudePreToolUseOutput;
|
|
22
15
|
declare const handlePreToolUse: (input: ToolInput) => Promise<HookOutput | undefined>;
|
|
23
16
|
|
|
24
17
|
declare const getPolicy: (apiKey: string, expectedVersion?: string | null, agent?: string, repoAware?: boolean, sessionId?: string) => Promise<PolicyConfig>;
|
package/dist/src/index.js
CHANGED
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
2
|
handlePreToolUse
|
|
3
|
-
} from "../chunk-
|
|
4
|
-
import "../chunk-
|
|
5
|
-
import "../chunk-
|
|
6
|
-
import "../chunk-VT4IVERX.js";
|
|
7
|
-
import "../chunk-VGADRFG6.js";
|
|
3
|
+
} from "../chunk-S3UD7O35.js";
|
|
4
|
+
import "../chunk-ATBKJNWS.js";
|
|
5
|
+
import "../chunk-MNQI6ZZU.js";
|
|
8
6
|
import "../chunk-YHG74UFF.js";
|
|
9
7
|
import {
|
|
10
8
|
askUser,
|
|
@@ -17,11 +15,11 @@ import {
|
|
|
17
15
|
handleStop,
|
|
18
16
|
reportEvent,
|
|
19
17
|
waitForAnswer
|
|
20
|
-
} from "../chunk-
|
|
18
|
+
} from "../chunk-33T5OOKP.js";
|
|
21
19
|
import "../chunk-RN3NOEJF.js";
|
|
22
20
|
import "../chunk-BSZYIAZL.js";
|
|
23
21
|
import "../chunk-SAF6HGAA.js";
|
|
24
|
-
import "../chunk-
|
|
22
|
+
import "../chunk-7C5CJC3H.js";
|
|
25
23
|
import "../chunk-7QLSKOSU.js";
|
|
26
24
|
import "../chunk-KZERVKTD.js";
|
|
27
25
|
import {
|
|
@@ -30,7 +28,7 @@ import {
|
|
|
30
28
|
} from "../chunk-2UMNXADU.js";
|
|
31
29
|
import {
|
|
32
30
|
resolvePolicy
|
|
33
|
-
} from "../chunk-
|
|
31
|
+
} from "../chunk-CY4TZK5O.js";
|
|
34
32
|
export {
|
|
35
33
|
askUser,
|
|
36
34
|
cancelQuestion,
|