@pushary/agent-hooks 0.85.2 → 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 +17 -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 +4 -4
- 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-Q4URN3E7.js → chunk-2255DZ74.js} +1 -1
- package/dist/{chunk-GY3I353G.js → chunk-2C6B6V2U.js} +7 -3
- package/dist/{chunk-LSB6PFLN.js → chunk-2TZCZ7CL.js} +1 -1
- package/dist/{chunk-DPDUB4XF.js → chunk-33T5OOKP.js} +11 -5
- package/dist/{chunk-GM74DUMS.js → chunk-5EUZYWID.js} +1 -1
- package/dist/{chunk-CWV4CMB6.js → chunk-7C5CJC3H.js} +1 -1
- package/dist/{chunk-KZIGJLOX.js → chunk-7G5VO76N.js} +1 -1
- package/dist/chunk-ATBKJNWS.js +19 -0
- package/dist/{chunk-K337LIBD.js → chunk-CY4TZK5O.js} +5 -0
- package/dist/{chunk-JBLRZGTT.js → chunk-FOY5FISQ.js} +1 -1
- package/dist/{chunk-XJDL3MUE.js → chunk-GK4CED6Z.js} +12 -18
- package/dist/{chunk-PKUNB3SN.js → chunk-MNQI6ZZU.js} +1 -1
- package/dist/{chunk-4YMWLMAP.js → chunk-MTKR4YLW.js} +1 -1
- package/dist/{chunk-NTIUQB3E.js → chunk-N52CIK47.js} +1 -1
- package/dist/{chunk-LCA2EQTK.js → chunk-PZR4XMFU.js} +1 -1
- package/dist/{chunk-JT5NQQCE.js → chunk-Q7N3XGWM.js} +2 -2
- package/dist/{chunk-4U2YRHNF.js → chunk-QW27ZFA4.js} +2 -2
- package/dist/{chunk-Y7E2MC3G.js → chunk-S3UD7O35.js} +51 -6
- package/dist/{chunk-KJW6NKF7.js → chunk-VPJAAGD4.js} +7 -3
- package/dist/{chunk-LXWISFF3.js → chunk-VZNDR3Z7.js} +1 -1
- package/dist/{chunk-T54OT7IY.js → chunk-XPAGN3SC.js} +1 -1
- package/dist/src/index.js +6 -8
- package/package.json +1 -1
|
@@ -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";
|
|
@@ -45,7 +46,7 @@ import {
|
|
|
45
46
|
hookWaitDeadline,
|
|
46
47
|
parseAgentQuestionAnswers,
|
|
47
48
|
resolveGate
|
|
48
|
-
} from "./chunk-
|
|
49
|
+
} from "./chunk-CY4TZK5O.js";
|
|
49
50
|
|
|
50
51
|
// src/decision-episode.ts
|
|
51
52
|
var EPISODE_PATH = "/api/agent/decision-episode";
|
|
@@ -448,6 +449,47 @@ var handleAskUserQuestion = async (apiKey, input) => {
|
|
|
448
449
|
if (!answers) return void 0;
|
|
449
450
|
return allowWithInput({ ...input.tool_input ?? {}, answers });
|
|
450
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
|
+
};
|
|
451
493
|
var handleKeyless = (input) => {
|
|
452
494
|
try {
|
|
453
495
|
if (isGatingMoment(input.tool_name, input.tool_input ?? {})) {
|
|
@@ -493,6 +535,9 @@ var handlePreToolUse = async (input) => {
|
|
|
493
535
|
return handleAskUserQuestion(apiKey, input);
|
|
494
536
|
}
|
|
495
537
|
if (verdict.kind === "deny") return deny(verdict.reason);
|
|
538
|
+
if (input.tool_name === "ExitPlanMode") {
|
|
539
|
+
return handleExitPlanMode(apiKey, input);
|
|
540
|
+
}
|
|
496
541
|
if (shouldDeferToNativeMode(input.permission_mode, input.tool_name)) {
|
|
497
542
|
return void 0;
|
|
498
543
|
}
|
|
@@ -524,7 +569,7 @@ var toPermissionRequestOutput = (hookOutput) => {
|
|
|
524
569
|
};
|
|
525
570
|
var handlePermissionRequest = async (input) => {
|
|
526
571
|
if (PRETOOLUSE_HANDLED_TOOLS.has(input.tool_name)) {
|
|
527
|
-
const reclaimDeferredExec = input.tool_name
|
|
572
|
+
const reclaimDeferredExec = !PRETOOLUSE_PHONE_ANSWERED_TOOLS.includes(input.tool_name) && shouldDeferToNativeMode(input.permission_mode, input.tool_name);
|
|
528
573
|
if (!reclaimDeferredExec) return void 0;
|
|
529
574
|
}
|
|
530
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.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-PKUNB3SN.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,
|