@pushary/agent-hooks 0.33.0 → 0.35.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/dist/bin/pushary-clean.js +1 -1
- package/dist/bin/pushary-codex-hook.js +1 -1
- package/dist/bin/pushary-codex.js +1 -1
- package/dist/bin/pushary-gemini-hook.js +1 -1
- package/dist/bin/pushary-hook.js +2 -2
- package/dist/bin/pushary-notification-hook.js +1 -1
- package/dist/bin/pushary-post-hook.js +1 -1
- package/dist/bin/pushary-prompt-hook.js +1 -1
- package/dist/bin/pushary-session-start-hook.js +1 -1
- package/dist/bin/pushary-setup.js +2 -2
- package/dist/bin/pushary-stop-hook.js +1 -1
- package/dist/{chunk-OCPDWNG2.js → chunk-FIBI2QZC.js} +12 -6
- package/dist/{chunk-UU3ETDK4.js → chunk-JE3WQW63.js} +69 -6
- package/dist/{chunk-AV2F2ZTZ.js → chunk-ZJICOAAN.js} +3 -2
- package/dist/src/index.d.ts +1 -0
- package/dist/src/index.js +2 -2
- package/package.json +1 -1
package/dist/bin/pushary-hook.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
handlePreToolUse
|
|
4
|
-
} from "../chunk-
|
|
4
|
+
} from "../chunk-JE3WQW63.js";
|
|
5
5
|
import "../chunk-KQYIHZ5E.js";
|
|
6
|
-
import "../chunk-
|
|
6
|
+
import "../chunk-FIBI2QZC.js";
|
|
7
7
|
import "../chunk-R5AJNXZS.js";
|
|
8
8
|
import "../chunk-DWED7BS3.js";
|
|
9
9
|
import "../chunk-Z5PL3K7C.js";
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
addClaudeMcpServer,
|
|
4
4
|
addPusharyHooks,
|
|
5
5
|
addPusharyToolPermissions
|
|
6
|
-
} from "../chunk-
|
|
6
|
+
} from "../chunk-ZJICOAAN.js";
|
|
7
7
|
import {
|
|
8
8
|
GEMINI_HOOK_BINARY,
|
|
9
9
|
addCodexHookTrust,
|
|
@@ -24,7 +24,7 @@ import {
|
|
|
24
24
|
} from "../chunk-J7JWI3KU.js";
|
|
25
25
|
import {
|
|
26
26
|
reportEvent
|
|
27
|
-
} from "../chunk-
|
|
27
|
+
} from "../chunk-FIBI2QZC.js";
|
|
28
28
|
import "../chunk-DWED7BS3.js";
|
|
29
29
|
import {
|
|
30
30
|
isValidApiKey
|
|
@@ -190,8 +190,11 @@ var fetchModeOverride = async (apiKey) => (await fetchModeState(apiKey)).mode;
|
|
|
190
190
|
import { isAbsolute, relative } from "path";
|
|
191
191
|
var hookPrefixes = {
|
|
192
192
|
Bash: (input) => `bash: ${input.command ?? "(no command)"}`,
|
|
193
|
+
PowerShell: (input) => `powershell: ${input.command ?? "(no command)"}`,
|
|
194
|
+
Monitor: (input) => `monitor: ${input.command ?? "(no command)"}`,
|
|
193
195
|
Write: (input) => `write file: ${input.file_path ?? "(unknown path)"}`,
|
|
194
196
|
Edit: (input) => `edit file: ${input.file_path ?? "(unknown path)"}`,
|
|
197
|
+
MultiEdit: (input) => `edit file: ${input.file_path ?? "(unknown path)"}`,
|
|
195
198
|
Read: (input) => `read file: ${input.file_path ?? "(unknown path)"}`
|
|
196
199
|
};
|
|
197
200
|
var describeTodoProgress = (todos) => {
|
|
@@ -208,8 +211,11 @@ var describeTodoProgress = (todos) => {
|
|
|
208
211
|
};
|
|
209
212
|
var eventPrefixes = {
|
|
210
213
|
Bash: (input) => `ran: ${String(input.command ?? "")}`,
|
|
214
|
+
PowerShell: (input) => `ran: ${String(input.command ?? "")}`,
|
|
215
|
+
Monitor: (input) => `ran: ${String(input.command ?? "")}`,
|
|
211
216
|
Write: (input) => `wrote: ${input.file_path ?? "unknown"}`,
|
|
212
217
|
Edit: (input) => `edited: ${input.file_path ?? "unknown"}`,
|
|
218
|
+
MultiEdit: (input) => `edited: ${input.file_path ?? "unknown"}`,
|
|
213
219
|
Read: (input) => `read: ${input.file_path ?? "unknown"}`,
|
|
214
220
|
TodoWrite: (input) => describeTodoProgress(input.todos)
|
|
215
221
|
};
|
|
@@ -230,10 +236,10 @@ var deriveCommandHead = (command) => {
|
|
|
230
236
|
return head ? head.slice(0, TOOL_TARGET_MAX_LENGTH) : void 0;
|
|
231
237
|
};
|
|
232
238
|
var deriveToolTarget = (toolName, toolInput) => {
|
|
233
|
-
if (toolName === "Bash") {
|
|
239
|
+
if (toolName === "Bash" || toolName === "PowerShell" || toolName === "Monitor") {
|
|
234
240
|
return deriveCommandHead(toolInput.command);
|
|
235
241
|
}
|
|
236
|
-
if (toolName === "Edit" || toolName === "Write") {
|
|
242
|
+
if (toolName === "Edit" || toolName === "Write" || toolName === "MultiEdit") {
|
|
237
243
|
const filePath = toolInput.file_path;
|
|
238
244
|
if (typeof filePath !== "string") return void 0;
|
|
239
245
|
const separator = Math.max(filePath.lastIndexOf("/"), filePath.lastIndexOf("\\"));
|
|
@@ -259,16 +265,16 @@ var relativizeReceiptPath = (filePath, cwd) => {
|
|
|
259
265
|
var deriveReceiptMeta = (toolName, toolInput, toolResult, cwd) => {
|
|
260
266
|
try {
|
|
261
267
|
const ok = !isToolResultError(toolResult);
|
|
262
|
-
if (toolName === "Edit" || toolName === "Write") {
|
|
268
|
+
if (toolName === "Edit" || toolName === "Write" || toolName === "MultiEdit") {
|
|
263
269
|
const filePath = toolInput.file_path;
|
|
264
270
|
if (typeof filePath !== "string" || !filePath) return void 0;
|
|
265
271
|
return {
|
|
266
|
-
kind: toolName === "
|
|
272
|
+
kind: toolName === "Write" ? "write" : "edit",
|
|
267
273
|
target: relativizeReceiptPath(filePath, cwd).slice(0, RECEIPT_TARGET_MAX_LENGTH),
|
|
268
274
|
ok
|
|
269
275
|
};
|
|
270
276
|
}
|
|
271
|
-
if (toolName === "Bash") {
|
|
277
|
+
if (toolName === "Bash" || toolName === "PowerShell" || toolName === "Monitor") {
|
|
272
278
|
const head = deriveCommandHead(toolInput.command);
|
|
273
279
|
if (!head) return void 0;
|
|
274
280
|
return {
|
|
@@ -294,7 +300,7 @@ var rawActionBody = (toolName, toolInput) => {
|
|
|
294
300
|
+ ${after ?? ""}`;
|
|
295
301
|
}
|
|
296
302
|
if (toolName === "Write" || toolName === "write_file") return firstString(toolInput.content);
|
|
297
|
-
if (toolName === "Bash" || toolName === "run_shell_command" || toolName === "shell" || toolName === "apply_patch") {
|
|
303
|
+
if (toolName === "Bash" || toolName === "PowerShell" || toolName === "Monitor" || toolName === "run_shell_command" || toolName === "shell" || toolName === "apply_patch") {
|
|
298
304
|
return firstString(toolInput.command);
|
|
299
305
|
}
|
|
300
306
|
return void 0;
|
|
@@ -20,7 +20,7 @@ import {
|
|
|
20
20
|
savePendingQuestion,
|
|
21
21
|
sendNotification,
|
|
22
22
|
waitForAnswer
|
|
23
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-FIBI2QZC.js";
|
|
24
24
|
import {
|
|
25
25
|
isGatingMoment,
|
|
26
26
|
recordKeylessMoment
|
|
@@ -53,6 +53,13 @@ var deny = (reason) => ({
|
|
|
53
53
|
permissionDecisionReason: reason
|
|
54
54
|
}
|
|
55
55
|
});
|
|
56
|
+
var allowWithInput = (updatedInput) => ({
|
|
57
|
+
hookSpecificOutput: {
|
|
58
|
+
hookEventName: "PreToolUse",
|
|
59
|
+
permissionDecision: "allow",
|
|
60
|
+
updatedInput
|
|
61
|
+
}
|
|
62
|
+
});
|
|
56
63
|
var ask = (reason) => ({
|
|
57
64
|
hookSpecificOutput: {
|
|
58
65
|
hookEventName: "PreToolUse",
|
|
@@ -200,11 +207,64 @@ var keylessNoticeOnce = (sessionId) => {
|
|
|
200
207
|
} catch {
|
|
201
208
|
}
|
|
202
209
|
};
|
|
203
|
-
var
|
|
204
|
-
var
|
|
210
|
+
var FULL_DEFER_MODES = /* @__PURE__ */ new Set(["plan", "auto", "dontAsk"]);
|
|
211
|
+
var ACCEPT_EDITS_DEFER_TOOLS = /* @__PURE__ */ new Set(["Write", "Edit", "MultiEdit", "NotebookEdit"]);
|
|
212
|
+
var nativeModeGatingDisabled = () => {
|
|
205
213
|
const flag = process.env.PUSHARY_RESPECT_PERMISSION_MODE;
|
|
206
|
-
|
|
207
|
-
|
|
214
|
+
return flag === "0" || flag === "false";
|
|
215
|
+
};
|
|
216
|
+
var shouldDeferToNativeMode = (permissionMode, toolName) => {
|
|
217
|
+
if (nativeModeGatingDisabled()) return false;
|
|
218
|
+
if (typeof permissionMode !== "string") return false;
|
|
219
|
+
if (FULL_DEFER_MODES.has(permissionMode)) return true;
|
|
220
|
+
if (permissionMode === "acceptEdits" && ACCEPT_EDITS_DEFER_TOOLS.has(toolName)) return true;
|
|
221
|
+
if (permissionMode === "bypassPermissions") {
|
|
222
|
+
const flag = process.env.PUSHARY_DEFER_BYPASS;
|
|
223
|
+
return flag === "1" || flag === "true";
|
|
224
|
+
}
|
|
225
|
+
return false;
|
|
226
|
+
};
|
|
227
|
+
var parseSingleQuestion = (toolInput) => {
|
|
228
|
+
const questions = toolInput.questions;
|
|
229
|
+
if (!Array.isArray(questions) || questions.length !== 1) return void 0;
|
|
230
|
+
const q = questions[0];
|
|
231
|
+
if (!q || typeof q.question !== "string" || q.multiSelect === true) return void 0;
|
|
232
|
+
const labels = Array.isArray(q.options) ? q.options.map((o) => o && typeof o === "object" ? o.label : void 0).filter((l) => typeof l === "string" && l.length > 0) : [];
|
|
233
|
+
if (labels.length < 2) return void 0;
|
|
234
|
+
return { question: q.question, header: typeof q.header === "string" ? q.header : void 0, labels };
|
|
235
|
+
};
|
|
236
|
+
var handleAskUserQuestion = async (apiKey, input) => {
|
|
237
|
+
const parsed = parseSingleQuestion(input.tool_input ?? {});
|
|
238
|
+
if (!parsed) return void 0;
|
|
239
|
+
const projectName = basename(input.cwd ?? process.cwd());
|
|
240
|
+
let result;
|
|
241
|
+
try {
|
|
242
|
+
result = await askUser(apiKey, {
|
|
243
|
+
question: parsed.question,
|
|
244
|
+
type: "select",
|
|
245
|
+
options: [...parsed.labels],
|
|
246
|
+
context: parsed.header ? `${parsed.header}: your agent is asking in ${projectName}` : `Your agent is asking in ${projectName}`,
|
|
247
|
+
agentName: `Claude Code - ${projectName}`,
|
|
248
|
+
sessionId: input.session_id,
|
|
249
|
+
machineId: getMachineId(),
|
|
250
|
+
toolName: "AskUserQuestion"
|
|
251
|
+
});
|
|
252
|
+
} catch {
|
|
253
|
+
return void 0;
|
|
254
|
+
}
|
|
255
|
+
if (result.suppressed || result.noDevices) {
|
|
256
|
+
await cancelQuestion(apiKey, result.correlationId).catch(() => {
|
|
257
|
+
});
|
|
258
|
+
return void 0;
|
|
259
|
+
}
|
|
260
|
+
const deadline = hookWaitDeadline(START_MS, effectiveWaitSeconds("wait", 0, "claude"), "claude", Date.now());
|
|
261
|
+
const answer = await pollForAnswer(apiKey, result.correlationId, deadline);
|
|
262
|
+
const value = answer.answered ? (answer.value ?? "").trim() : "";
|
|
263
|
+
if (!value || isDeferAnswer(answer.value)) {
|
|
264
|
+
savePendingQuestion(input.session_id || DEFAULT_SESSION, result.correlationId);
|
|
265
|
+
return void 0;
|
|
266
|
+
}
|
|
267
|
+
return allowWithInput({ ...input.tool_input ?? {}, answers: { [parsed.question]: value } });
|
|
208
268
|
};
|
|
209
269
|
var handleKeyless = (input) => {
|
|
210
270
|
try {
|
|
@@ -235,7 +295,10 @@ var handlePreToolUse = async (input) => {
|
|
|
235
295
|
if (modeState.kill) {
|
|
236
296
|
return deny("Stopped by user \u2014 this agent was halted from Pushary");
|
|
237
297
|
}
|
|
238
|
-
if (
|
|
298
|
+
if (input.tool_name === "AskUserQuestion") {
|
|
299
|
+
return handleAskUserQuestion(apiKey, input);
|
|
300
|
+
}
|
|
301
|
+
if (shouldDeferToNativeMode(input.permission_mode, input.tool_name)) {
|
|
239
302
|
return void 0;
|
|
240
303
|
}
|
|
241
304
|
const toolPolicy = resolvePolicy(policy, input.tool_name, modeState.mode, input.tool_input);
|
|
@@ -65,9 +65,10 @@ var addPusharyHooks = (settings, binDir) => {
|
|
|
65
65
|
return /\s/.test(path) ? `"${path}"` : path;
|
|
66
66
|
};
|
|
67
67
|
const hooks = ensureRecord(settings, "hooks");
|
|
68
|
+
const SHELL_AND_FILE_TOOLS = "Bash|Write|Edit|MultiEdit|NotebookEdit|PowerShell|Monitor";
|
|
68
69
|
const preToolUse = (Array.isArray(hooks.PreToolUse) ? hooks.PreToolUse : []).filter((entry) => !isPusharyHook(entry));
|
|
69
70
|
preToolUse.push({
|
|
70
|
-
matcher:
|
|
71
|
+
matcher: `${SHELL_AND_FILE_TOOLS}|AskUserQuestion`,
|
|
71
72
|
hooks: [{
|
|
72
73
|
type: "command",
|
|
73
74
|
command: resolve("pushary-hook"),
|
|
@@ -77,7 +78,7 @@ var addPusharyHooks = (settings, binDir) => {
|
|
|
77
78
|
hooks.PreToolUse = preToolUse;
|
|
78
79
|
const postToolUse = (Array.isArray(hooks.PostToolUse) ? hooks.PostToolUse : []).filter((entry) => !isPusharyHook(entry));
|
|
79
80
|
postToolUse.push({
|
|
80
|
-
matcher:
|
|
81
|
+
matcher: `${SHELL_AND_FILE_TOOLS}|TodoWrite`,
|
|
81
82
|
hooks: [{
|
|
82
83
|
type: "command",
|
|
83
84
|
command: resolve("pushary-post-hook"),
|
package/dist/src/index.d.ts
CHANGED
|
@@ -14,6 +14,7 @@ interface HookOutput {
|
|
|
14
14
|
hookEventName: 'PreToolUse';
|
|
15
15
|
permissionDecision: 'allow' | 'deny' | 'ask';
|
|
16
16
|
permissionDecisionReason?: string;
|
|
17
|
+
updatedInput?: Record<string, unknown>;
|
|
17
18
|
};
|
|
18
19
|
}
|
|
19
20
|
declare const handlePreToolUse: (input: ToolInput) => Promise<HookOutput | undefined>;
|
package/dist/src/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
handlePreToolUse
|
|
3
|
-
} from "../chunk-
|
|
3
|
+
} from "../chunk-JE3WQW63.js";
|
|
4
4
|
import "../chunk-KQYIHZ5E.js";
|
|
5
5
|
import {
|
|
6
6
|
askUser,
|
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
reportEvent,
|
|
15
15
|
resolvePolicy,
|
|
16
16
|
waitForAnswer
|
|
17
|
-
} from "../chunk-
|
|
17
|
+
} from "../chunk-FIBI2QZC.js";
|
|
18
18
|
import "../chunk-R5AJNXZS.js";
|
|
19
19
|
import "../chunk-DWED7BS3.js";
|
|
20
20
|
import "../chunk-Z5PL3K7C.js";
|