@pushary/agent-hooks 0.89.9 → 0.89.11
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 +54 -0
- package/dist/bin/pushary-bell-hook.js +4 -4
- package/dist/bin/pushary-bell.js +7 -7
- package/dist/bin/pushary-claude.js +84 -36
- package/dist/bin/pushary-clean.js +52 -45
- package/dist/bin/pushary-codex-bridge.js +15 -9
- package/dist/bin/pushary-codex-hook.js +12 -8
- package/dist/bin/pushary-codex.js +7 -7
- package/dist/bin/pushary-connect.js +6 -6
- package/dist/bin/pushary-daemon.js +16 -16
- package/dist/bin/pushary-disconnect.js +34 -9
- package/dist/bin/pushary-doctor.js +19 -19
- package/dist/bin/pushary-elicitation-hook.js +4 -4
- package/dist/bin/pushary-gemini-bridge.js +15 -8
- package/dist/bin/pushary-gemini-hook.js +8 -8
- package/dist/bin/pushary-hook.js +11 -10
- 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 +7 -7
- package/dist/bin/pushary-opencode-hook.js +8 -8
- package/dist/bin/pushary-permission-denied-hook.js +11 -10
- package/dist/bin/pushary-permission-hook.js +11 -10
- package/dist/bin/pushary-post-hook.js +7 -7
- package/dist/bin/pushary-prompt-hook.js +7 -7
- package/dist/bin/pushary-session-end-hook.js +7 -7
- package/dist/bin/pushary-session-start-hook.js +7 -7
- package/dist/bin/pushary-setup.js +52 -54
- package/dist/bin/pushary-stats.js +2 -2
- package/dist/bin/pushary-status.js +8 -8
- package/dist/bin/pushary-stop-hook.js +7 -7
- package/dist/bin/pushary-stopfailure-hook.js +7 -7
- package/dist/bin/pushary-upgrade.js +15 -15
- package/dist/bin/pushary-wait.js +3 -3
- package/dist/{chunk-SS72Z7FV.js → chunk-253WC6O5.js} +1 -1
- package/dist/{chunk-T3LRWZKI.js → chunk-2LPEZYMC.js} +1 -1
- package/dist/{chunk-O5B7EK5U.js → chunk-34GN3IPX.js} +1 -1
- package/dist/{chunk-V6N4Q223.js → chunk-3CUDMTL4.js} +1 -1
- package/dist/{chunk-VZKXBFUA.js → chunk-3HFK3UXM.js} +1 -1
- package/dist/{chunk-543KNJKC.js → chunk-3SQYKLBW.js} +3 -3
- package/dist/{chunk-ATBKJNWS.js → chunk-6EKQZA6R.js} +5 -1
- package/dist/{chunk-NKHEHEUM.js → chunk-6XUABEX2.js} +1 -1
- package/dist/{chunk-I5L6SK5V.js → chunk-BLODMQKJ.js} +1 -1
- package/dist/{chunk-DKDDLF5P.js → chunk-DKWM5T3P.js} +1 -1
- package/dist/{chunk-4XZCDSNG.js → chunk-FXIL7RCL.js} +5 -5
- package/dist/{chunk-BAE45YLP.js → chunk-FZ73G2RO.js} +3 -3
- package/dist/{chunk-PMHTCDEO.js → chunk-IUN6VOKV.js} +1 -1
- package/dist/{chunk-OFRNZWC4.js → chunk-IUWRVTQK.js} +1 -1
- package/dist/{chunk-EJT2ER6G.js → chunk-J4K75V4D.js} +46 -35
- package/dist/{chunk-GKAKAOKC.js → chunk-JHJHCMAF.js} +65 -12
- package/dist/{chunk-J2JZJZKB.js → chunk-KVE5RCQL.js} +1 -1
- package/dist/{chunk-A4O5ROZK.js → chunk-MZGWKIUZ.js} +2 -2
- package/dist/chunk-NCVIWGVA.js +18 -0
- package/dist/{chunk-C623LWJR.js → chunk-OLAGKKSR.js} +1 -1
- package/dist/{chunk-EA3E74P2.js → chunk-PZRWFWSR.js} +6 -6
- package/dist/{chunk-VA7VUNRD.js → chunk-Q223OM5J.js} +58 -8
- package/dist/{chunk-GMI5QZLG.js → chunk-QA72MKIT.js} +5 -1
- package/dist/{chunk-AIGDBRIJ.js → chunk-SYUIXXQW.js} +1 -1
- package/dist/{chunk-TF247BET.js → chunk-TEZ2FZD6.js} +1 -1
- package/dist/{chunk-KOPUTJQC.js → chunk-TG3T3M4K.js} +1 -1
- package/dist/{chunk-FX5QSMPY.js → chunk-TRVIRETT.js} +1 -1
- package/dist/{chunk-U5TQCQ25.js → chunk-TY5HVMXT.js} +1 -1
- package/dist/chunk-UDBJHQMG.js +240 -0
- package/dist/{chunk-PZA7G4CN.js → chunk-X4ZUUFKV.js} +1 -0
- package/dist/{chunk-L4C2JXJS.js → chunk-X6RXX2NF.js} +5 -0
- package/dist/src/index.d.ts +5 -0
- package/dist/src/index.js +11 -10
- package/package.json +1 -1
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
reapplyAllAgents
|
|
4
|
-
} from "../chunk-
|
|
5
|
-
import "../chunk-
|
|
6
|
-
import "../chunk-
|
|
4
|
+
} from "../chunk-PZRWFWSR.js";
|
|
5
|
+
import "../chunk-KVE5RCQL.js";
|
|
6
|
+
import "../chunk-FZ73G2RO.js";
|
|
7
7
|
import {
|
|
8
8
|
waitForMachineReadiness
|
|
9
|
-
} from "../chunk-
|
|
10
|
-
import "../chunk-
|
|
11
|
-
import "../chunk-
|
|
12
|
-
import "../chunk-
|
|
9
|
+
} from "../chunk-TY5HVMXT.js";
|
|
10
|
+
import "../chunk-Q223OM5J.js";
|
|
11
|
+
import "../chunk-6EKQZA6R.js";
|
|
12
|
+
import "../chunk-SYUIXXQW.js";
|
|
13
13
|
import {
|
|
14
14
|
daemonHasRemoteProof,
|
|
15
15
|
daemonServiceManagerAvailable,
|
|
@@ -20,12 +20,12 @@ import {
|
|
|
20
20
|
replaceDaemonService,
|
|
21
21
|
stopDaemonService,
|
|
22
22
|
waitForDaemonRemoteProof
|
|
23
|
-
} from "../chunk-
|
|
23
|
+
} from "../chunk-3SQYKLBW.js";
|
|
24
24
|
import {
|
|
25
25
|
detectProviderLiveCapabilities,
|
|
26
26
|
hasSpawnProvider,
|
|
27
27
|
resolveControlPolicy
|
|
28
|
-
} from "../chunk-
|
|
28
|
+
} from "../chunk-6XUABEX2.js";
|
|
29
29
|
import {
|
|
30
30
|
needsShell
|
|
31
31
|
} from "../chunk-XHKBHWLX.js";
|
|
@@ -33,18 +33,18 @@ import {
|
|
|
33
33
|
execNpm,
|
|
34
34
|
npmErrorMessage,
|
|
35
35
|
resolveGlobalBinary
|
|
36
|
-
} from "../chunk-
|
|
37
|
-
import "../chunk-
|
|
36
|
+
} from "../chunk-X4ZUUFKV.js";
|
|
37
|
+
import "../chunk-DKWM5T3P.js";
|
|
38
38
|
import {
|
|
39
39
|
claudeJson,
|
|
40
40
|
codexConfigToml,
|
|
41
41
|
cursorPluginDir,
|
|
42
42
|
geminiSettings,
|
|
43
43
|
vscodePluginDir
|
|
44
|
-
} from "../chunk-
|
|
44
|
+
} from "../chunk-QA72MKIT.js";
|
|
45
45
|
import {
|
|
46
46
|
readControlMode
|
|
47
|
-
} from "../chunk-
|
|
47
|
+
} from "../chunk-3CUDMTL4.js";
|
|
48
48
|
import {
|
|
49
49
|
exitOnHelpFlag
|
|
50
50
|
} from "../chunk-LURY4WNF.js";
|
|
@@ -53,13 +53,13 @@ import "../chunk-BC3VCZ3E.js";
|
|
|
53
53
|
import {
|
|
54
54
|
isNewerVersion
|
|
55
55
|
} from "../chunk-DINDL2CF.js";
|
|
56
|
-
import "../chunk-
|
|
56
|
+
import "../chunk-IUWRVTQK.js";
|
|
57
57
|
import "../chunk-KZERVKTD.js";
|
|
58
58
|
import "../chunk-XX2V4QS5.js";
|
|
59
59
|
import {
|
|
60
60
|
getApiKey
|
|
61
61
|
} from "../chunk-2UMNXADU.js";
|
|
62
|
-
import "../chunk-
|
|
62
|
+
import "../chunk-X6RXX2NF.js";
|
|
63
63
|
|
|
64
64
|
// bin/pushary-upgrade.ts
|
|
65
65
|
import { existsSync } from "fs";
|
package/dist/bin/pushary-wait.js
CHANGED
|
@@ -4,8 +4,8 @@ import {
|
|
|
4
4
|
} from "../chunk-IIENZE2J.js";
|
|
5
5
|
import {
|
|
6
6
|
exitOnFailedResponse
|
|
7
|
-
} from "../chunk-
|
|
8
|
-
import "../chunk-
|
|
7
|
+
} from "../chunk-253WC6O5.js";
|
|
8
|
+
import "../chunk-BLODMQKJ.js";
|
|
9
9
|
import {
|
|
10
10
|
createIo
|
|
11
11
|
} from "../chunk-5RUIFDTP.js";
|
|
@@ -28,7 +28,7 @@ import {
|
|
|
28
28
|
getApiKey,
|
|
29
29
|
getBaseUrl
|
|
30
30
|
} from "../chunk-2UMNXADU.js";
|
|
31
|
-
import "../chunk-
|
|
31
|
+
import "../chunk-X6RXX2NF.js";
|
|
32
32
|
|
|
33
33
|
// bin/pushary-wait.ts
|
|
34
34
|
exitOnHelpFlag("wait");
|
|
@@ -4,13 +4,13 @@ import {
|
|
|
4
4
|
} from "./chunk-XHKBHWLX.js";
|
|
5
5
|
import {
|
|
6
6
|
resolveGlobalBinary
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-X4ZUUFKV.js";
|
|
8
8
|
import {
|
|
9
9
|
getMachineId
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-DKWM5T3P.js";
|
|
11
11
|
import {
|
|
12
12
|
pusharyDir
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-QA72MKIT.js";
|
|
14
14
|
import {
|
|
15
15
|
getPackageVersion
|
|
16
16
|
} from "./chunk-DINDL2CF.js";
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ASKED_IN_EVERY_MODE_TOOLS
|
|
3
|
+
} from "./chunk-X6RXX2NF.js";
|
|
4
|
+
|
|
1
5
|
// src/claude-tools.ts
|
|
2
6
|
var PRETOOLUSE_GATED_TOOLS = [
|
|
3
7
|
"Bash",
|
|
@@ -8,7 +12,7 @@ var PRETOOLUSE_GATED_TOOLS = [
|
|
|
8
12
|
"PowerShell",
|
|
9
13
|
"Monitor"
|
|
10
14
|
];
|
|
11
|
-
var PRETOOLUSE_PHONE_ANSWERED_TOOLS =
|
|
15
|
+
var PRETOOLUSE_PHONE_ANSWERED_TOOLS = ASKED_IN_EVERY_MODE_TOOLS;
|
|
12
16
|
var POSTTOOLUSE_MIRRORED_TOOLS = [...PRETOOLUSE_GATED_TOOLS, "TodoWrite"];
|
|
13
17
|
var PRETOOLUSE_HANDLED_TOOLS = /* @__PURE__ */ new Set([...PRETOOLUSE_GATED_TOOLS, ...PRETOOLUSE_PHONE_ANSWERED_TOOLS]);
|
|
14
18
|
|
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
savePendingCommand,
|
|
13
13
|
sendNotification,
|
|
14
14
|
waitForAnswer
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-JHJHCMAF.js";
|
|
16
16
|
import {
|
|
17
17
|
AGENT_IDENTITIES,
|
|
18
18
|
deriveReceiptMeta,
|
|
@@ -26,16 +26,16 @@ import {
|
|
|
26
26
|
summarizeStop,
|
|
27
27
|
taskTitleFrom,
|
|
28
28
|
toolResultErrorText
|
|
29
|
-
} from "./chunk-
|
|
29
|
+
} from "./chunk-TG3T3M4K.js";
|
|
30
30
|
import {
|
|
31
31
|
getMachineId
|
|
32
|
-
} from "./chunk-
|
|
32
|
+
} from "./chunk-DKWM5T3P.js";
|
|
33
33
|
import {
|
|
34
34
|
withRetry
|
|
35
35
|
} from "./chunk-BSZYIAZL.js";
|
|
36
36
|
import {
|
|
37
37
|
reportedInstallSource
|
|
38
|
-
} from "./chunk-
|
|
38
|
+
} from "./chunk-IUWRVTQK.js";
|
|
39
39
|
import {
|
|
40
40
|
getApiKey,
|
|
41
41
|
getBaseUrl
|
|
@@ -51,7 +51,7 @@ import {
|
|
|
51
51
|
pendingCommandEvents,
|
|
52
52
|
resolveAutoResolveOrigin,
|
|
53
53
|
resolvePolicy
|
|
54
|
-
} from "./chunk-
|
|
54
|
+
} from "./chunk-X6RXX2NF.js";
|
|
55
55
|
|
|
56
56
|
// src/policy.ts
|
|
57
57
|
import { createHash } from "crypto";
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
hasGeminiHooks
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-Q223OM5J.js";
|
|
4
4
|
import {
|
|
5
5
|
hasCodexHooks
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-QA72MKIT.js";
|
|
7
7
|
import {
|
|
8
8
|
HOOK_LOCATOR_BINARY
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-X6RXX2NF.js";
|
|
10
10
|
|
|
11
11
|
// src/diagnostics/wiring.ts
|
|
12
12
|
var record = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import {
|
|
2
2
|
PRETOOLUSE_HANDLED_TOOLS,
|
|
3
3
|
PRETOOLUSE_PHONE_ANSWERED_TOOLS
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-6EKQZA6R.js";
|
|
5
|
+
import {
|
|
6
|
+
defersToNativeMode
|
|
7
|
+
} from "./chunk-NCVIWGVA.js";
|
|
5
8
|
import {
|
|
6
9
|
isGatingMoment,
|
|
7
10
|
recordKeylessMoment
|
|
8
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-3HFK3UXM.js";
|
|
9
12
|
import {
|
|
10
13
|
denyReasonFrom,
|
|
11
14
|
isDeferAnswer
|
|
@@ -17,7 +20,7 @@ import {
|
|
|
17
20
|
readLastUserPrompt,
|
|
18
21
|
repoKeyFor,
|
|
19
22
|
throttlePass
|
|
20
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-FXIL7RCL.js";
|
|
21
24
|
import {
|
|
22
25
|
DEFAULT_SESSION,
|
|
23
26
|
askUser,
|
|
@@ -25,7 +28,7 @@ import {
|
|
|
25
28
|
pollForAnswer,
|
|
26
29
|
savePendingQuestion,
|
|
27
30
|
sendNotification
|
|
28
|
-
} from "./chunk-
|
|
31
|
+
} from "./chunk-JHJHCMAF.js";
|
|
29
32
|
import {
|
|
30
33
|
deriveAction,
|
|
31
34
|
deriveActionBody,
|
|
@@ -33,10 +36,10 @@ import {
|
|
|
33
36
|
deriveToolTarget,
|
|
34
37
|
describeToolCall,
|
|
35
38
|
scopePathFor
|
|
36
|
-
} from "./chunk-
|
|
39
|
+
} from "./chunk-TG3T3M4K.js";
|
|
37
40
|
import {
|
|
38
41
|
getMachineId
|
|
39
|
-
} from "./chunk-
|
|
42
|
+
} from "./chunk-DKWM5T3P.js";
|
|
40
43
|
import {
|
|
41
44
|
getApiKey,
|
|
42
45
|
getBaseUrl
|
|
@@ -50,9 +53,8 @@ import {
|
|
|
50
53
|
hookWaitDeadline,
|
|
51
54
|
parseAgentQuestionAnswers,
|
|
52
55
|
parseAgentQuestions,
|
|
53
|
-
resolveGate
|
|
54
|
-
|
|
55
|
-
} from "./chunk-L4C2JXJS.js";
|
|
56
|
+
resolveGate
|
|
57
|
+
} from "./chunk-X6RXX2NF.js";
|
|
56
58
|
|
|
57
59
|
// src/decision-episode.ts
|
|
58
60
|
var EPISODE_PATH = "/api/agent/decision-episode";
|
|
@@ -85,7 +87,16 @@ var allow = () => claudePreToolUseOutput("allow");
|
|
|
85
87
|
var deny = (reason) => claudePreToolUseOutput("deny", reason);
|
|
86
88
|
var allowWithInput = (updatedInput) => claudePreToolUseOutput("allow", void 0, updatedInput);
|
|
87
89
|
var ask = (reason) => claudePreToolUseOutput("ask", reason);
|
|
90
|
+
var storedWaitDeadline = (result, requestedDeadline) => {
|
|
91
|
+
const stored = result.waitEndsAt ? Date.parse(result.waitEndsAt) : Number.NaN;
|
|
92
|
+
return Number.isFinite(stored) ? Math.min(stored, requestedDeadline) : requestedDeadline;
|
|
93
|
+
};
|
|
94
|
+
var returnedAnswer = (result) => result.answered === true ? { answered: true, value: result.value, note: result.note } : null;
|
|
88
95
|
var handlePushOnly = async (apiKey, description, projectName, timeoutSeconds, timeoutAction, sessionId, machineId, toolName, toolTarget, decision, signals) => {
|
|
96
|
+
const effectiveWait = effectiveWaitSeconds(timeoutAction, timeoutSeconds, "claude");
|
|
97
|
+
const now = Date.now();
|
|
98
|
+
const requestedDeadline = hookWaitDeadline(START_MS, effectiveWait, "claude", now);
|
|
99
|
+
const clampCut = hookWaitClamped(START_MS, effectiveWait, "claude", now);
|
|
89
100
|
let result;
|
|
90
101
|
try {
|
|
91
102
|
result = await askUser(apiKey, {
|
|
@@ -97,6 +108,7 @@ var handlePushOnly = async (apiKey, description, projectName, timeoutSeconds, ti
|
|
|
97
108
|
machineId,
|
|
98
109
|
toolName,
|
|
99
110
|
toolTarget,
|
|
111
|
+
waitEndsAt: timeoutAction !== "approve" && timeoutAction !== "deny" || clampCut ? new Date(requestedDeadline).toISOString() : void 0,
|
|
100
112
|
...decision
|
|
101
113
|
});
|
|
102
114
|
} catch {
|
|
@@ -115,6 +127,8 @@ var handlePushOnly = async (apiKey, description, projectName, timeoutSeconds, ti
|
|
|
115
127
|
return ask(result.suppressed ? "You are at the keyboard, approve here." : "Delivery mode is Terminal, approve here.");
|
|
116
128
|
}
|
|
117
129
|
if (result.noDevices) {
|
|
130
|
+
await cancelQuestion(apiKey, result.correlationId).catch(() => {
|
|
131
|
+
});
|
|
118
132
|
switch (timeoutAction) {
|
|
119
133
|
case "approve":
|
|
120
134
|
return allow();
|
|
@@ -124,12 +138,9 @@ var handlePushOnly = async (apiKey, description, projectName, timeoutSeconds, ti
|
|
|
124
138
|
return void 0;
|
|
125
139
|
}
|
|
126
140
|
}
|
|
127
|
-
const
|
|
128
|
-
const now = Date.now();
|
|
129
|
-
const deadline = hookWaitDeadline(START_MS, effectiveWait, "claude", now);
|
|
130
|
-
const clampCut = hookWaitClamped(START_MS, effectiveWait, "claude", now);
|
|
141
|
+
const deadline = storedWaitDeadline(result, requestedDeadline);
|
|
131
142
|
announceWait(effectiveWait, result.answerUrl, sessionId);
|
|
132
|
-
const answer = await pollForAnswer(apiKey, result.correlationId, deadline);
|
|
143
|
+
const answer = returnedAnswer(result) ?? await pollForAnswer(apiKey, result.correlationId, deadline);
|
|
133
144
|
if (answer.answered) {
|
|
134
145
|
if (isDeferAnswer(answer.value)) return ask("Handling on your machine");
|
|
135
146
|
signals.humanDecision = true;
|
|
@@ -145,6 +156,7 @@ var handlePushOnly = async (apiKey, description, projectName, timeoutSeconds, ti
|
|
|
145
156
|
case "deny":
|
|
146
157
|
return deny("No response within timeout");
|
|
147
158
|
default:
|
|
159
|
+
savePendingQuestion(sessionId || DEFAULT_SESSION, result.correlationId);
|
|
148
160
|
return ask("No push response, asking in terminal");
|
|
149
161
|
}
|
|
150
162
|
};
|
|
@@ -152,6 +164,7 @@ var handleTerminalOnly = () => {
|
|
|
152
164
|
return ask();
|
|
153
165
|
};
|
|
154
166
|
var handlePushFirst = async (apiKey, description, projectName, pushFirstSeconds, sessionId, machineId, toolName, toolTarget, decision, signals) => {
|
|
167
|
+
const requestedDeadline = hookWaitDeadline(START_MS, pushFirstSeconds, "claude", Date.now());
|
|
155
168
|
let result;
|
|
156
169
|
try {
|
|
157
170
|
result = await askUser(apiKey, {
|
|
@@ -163,6 +176,7 @@ var handlePushFirst = async (apiKey, description, projectName, pushFirstSeconds,
|
|
|
163
176
|
machineId,
|
|
164
177
|
toolName,
|
|
165
178
|
toolTarget,
|
|
179
|
+
waitEndsAt: new Date(requestedDeadline).toISOString(),
|
|
166
180
|
...decision
|
|
167
181
|
});
|
|
168
182
|
} catch {
|
|
@@ -174,11 +188,13 @@ var handlePushFirst = async (apiKey, description, projectName, pushFirstSeconds,
|
|
|
174
188
|
return ask("You are at the keyboard, approve here.");
|
|
175
189
|
}
|
|
176
190
|
if (result.noDevices) {
|
|
191
|
+
await cancelQuestion(apiKey, result.correlationId).catch(() => {
|
|
192
|
+
});
|
|
177
193
|
return void 0;
|
|
178
194
|
}
|
|
179
195
|
announceWait(pushFirstSeconds, result.answerUrl, sessionId);
|
|
180
|
-
const deadline =
|
|
181
|
-
const answer = await pollForAnswer(apiKey, result.correlationId, deadline, 1500);
|
|
196
|
+
const deadline = storedWaitDeadline(result, requestedDeadline);
|
|
197
|
+
const answer = returnedAnswer(result) ?? await pollForAnswer(apiKey, result.correlationId, deadline, 1500);
|
|
182
198
|
if (answer.answered) {
|
|
183
199
|
if (isDeferAnswer(answer.value)) return ask("Handling on your machine");
|
|
184
200
|
signals.humanDecision = true;
|
|
@@ -302,15 +318,7 @@ var keylessNoticeOnce = (sessionId) => {
|
|
|
302
318
|
} catch {
|
|
303
319
|
}
|
|
304
320
|
};
|
|
305
|
-
var
|
|
306
|
-
const respect = process.env.PUSHARY_RESPECT_PERMISSION_MODE;
|
|
307
|
-
const bypass = process.env.PUSHARY_DEFER_BYPASS;
|
|
308
|
-
return {
|
|
309
|
-
respectPermissionMode: !(respect === "0" || respect === "false"),
|
|
310
|
-
deferBypass: bypass === "1" || bypass === "true"
|
|
311
|
-
};
|
|
312
|
-
};
|
|
313
|
-
var shouldDeferToNativeMode2 = (permissionMode, toolName) => shouldDeferToNativeMode(permissionMode, toolName, nativeDeferOptions());
|
|
321
|
+
var shouldDeferToNativeMode = defersToNativeMode;
|
|
314
322
|
var handedToTerminal = (result) => result.suppressed === true || result.noDevices === true || result.status === "terminal";
|
|
315
323
|
var withLabels = (question) => ({
|
|
316
324
|
...question,
|
|
@@ -336,7 +344,8 @@ var askAsOneCard = async (apiKey, input, parsed, projectName, deadline) => {
|
|
|
336
344
|
sessionId: input.session_id,
|
|
337
345
|
machineId: getMachineId(),
|
|
338
346
|
toolName: "AskUserQuestion",
|
|
339
|
-
toolUseId: input.tool_use_id
|
|
347
|
+
toolUseId: input.tool_use_id,
|
|
348
|
+
waitEndsAt: new Date(deadline).toISOString()
|
|
340
349
|
});
|
|
341
350
|
} catch {
|
|
342
351
|
return void 0;
|
|
@@ -346,7 +355,7 @@ var askAsOneCard = async (apiKey, input, parsed, projectName, deadline) => {
|
|
|
346
355
|
});
|
|
347
356
|
return void 0;
|
|
348
357
|
}
|
|
349
|
-
const answer = await pollForAnswer(apiKey, result.correlationId, deadline);
|
|
358
|
+
const answer = returnedAnswer(result) ?? await pollForAnswer(apiKey, result.correlationId, storedWaitDeadline(result, deadline));
|
|
350
359
|
const values = answer.answered && answer.value ? parseAgentQuestionAnswers(parsed, answer.value) : null;
|
|
351
360
|
if (!values || isDeferAnswer(answer.value)) {
|
|
352
361
|
savePendingQuestion(input.session_id || DEFAULT_SESSION, result.correlationId);
|
|
@@ -372,7 +381,8 @@ var askQuestionByQuestion = async (apiKey, input, parsed, projectName, deadline)
|
|
|
372
381
|
// One AskUserQuestion call raises several questions, and their payload
|
|
373
382
|
// fingerprints are identical (same tool, no target, no body). Without the
|
|
374
383
|
// index they would all collapse onto the first decision.
|
|
375
|
-
toolUseId: input.tool_use_id ? `${input.tool_use_id}#q${index}` : void 0
|
|
384
|
+
toolUseId: input.tool_use_id ? `${input.tool_use_id}#q${index}` : void 0,
|
|
385
|
+
waitEndsAt: new Date(deadline).toISOString()
|
|
376
386
|
});
|
|
377
387
|
} catch {
|
|
378
388
|
return void 0;
|
|
@@ -382,7 +392,7 @@ var askQuestionByQuestion = async (apiKey, input, parsed, projectName, deadline)
|
|
|
382
392
|
});
|
|
383
393
|
return void 0;
|
|
384
394
|
}
|
|
385
|
-
const answer = await pollForAnswer(apiKey, result.correlationId, deadline);
|
|
395
|
+
const answer = returnedAnswer(result) ?? await pollForAnswer(apiKey, result.correlationId, storedWaitDeadline(result, deadline));
|
|
386
396
|
const legacyValue = answer.answered ? answer.value?.trim() : void 0;
|
|
387
397
|
const values = legacyValue ? parseAgentQuestionAnswers([question], legacyValue) ?? parseAgentQuestionAnswers([question], JSON.stringify({
|
|
388
398
|
[question.question]: question.multiSelect ? JSON.stringify([legacyValue]) : legacyValue
|
|
@@ -410,6 +420,7 @@ var PLAN_KEEP_PLANNING = "Keep planning";
|
|
|
410
420
|
var handleExitPlanMode = async (apiKey, input) => {
|
|
411
421
|
const toolInput = input.tool_input ?? {};
|
|
412
422
|
const projectName = basename(input.cwd ?? process.cwd());
|
|
423
|
+
const deadline = hookWaitDeadline(START_MS, effectiveWaitSeconds("wait", 0, "claude"), "claude", Date.now());
|
|
413
424
|
let result;
|
|
414
425
|
try {
|
|
415
426
|
result = await askUser(apiKey, {
|
|
@@ -426,7 +437,8 @@ var handleExitPlanMode = async (apiKey, input) => {
|
|
|
426
437
|
// so approving from a lock screen is a real decision and not a blind yes.
|
|
427
438
|
actionBody: deriveActionBody("ExitPlanMode", toolInput),
|
|
428
439
|
intent: readLastPrompt(input.session_id ?? DEFAULT_SESSION) ?? (input.transcript_path ? readLastUserPrompt(input.transcript_path) : void 0),
|
|
429
|
-
blocker: "Waiting for you to approve the plan"
|
|
440
|
+
blocker: "Waiting for you to approve the plan",
|
|
441
|
+
waitEndsAt: new Date(deadline).toISOString()
|
|
430
442
|
});
|
|
431
443
|
} catch {
|
|
432
444
|
return void 0;
|
|
@@ -436,8 +448,7 @@ var handleExitPlanMode = async (apiKey, input) => {
|
|
|
436
448
|
});
|
|
437
449
|
return void 0;
|
|
438
450
|
}
|
|
439
|
-
const
|
|
440
|
-
const answer = await pollForAnswer(apiKey, result.correlationId, deadline);
|
|
451
|
+
const answer = returnedAnswer(result) ?? await pollForAnswer(apiKey, result.correlationId, storedWaitDeadline(result, deadline));
|
|
441
452
|
const value = answer.answered ? (answer.value ?? "").trim() : "";
|
|
442
453
|
if (!value || isDeferAnswer(answer.value)) {
|
|
443
454
|
savePendingQuestion(input.session_id || DEFAULT_SESSION, result.correlationId);
|
|
@@ -487,14 +498,14 @@ var handlePreToolUse = async (input) => {
|
|
|
487
498
|
const policy = await getPolicy(apiKey, modeState.policyVersion, "claude_code", true, input.session_id);
|
|
488
499
|
const verdict = resolveGate(claudeGateInput(modeState, policy, input));
|
|
489
500
|
if (verdict.kind === "kill") return deny(verdict.reason);
|
|
501
|
+
if (verdict.kind === "deny") return deny(verdict.reason);
|
|
490
502
|
if (input.tool_name === "AskUserQuestion") {
|
|
491
503
|
return handleAskUserQuestion(apiKey, input);
|
|
492
504
|
}
|
|
493
|
-
if (verdict.kind === "deny") return deny(verdict.reason);
|
|
494
505
|
if (input.tool_name === "ExitPlanMode") {
|
|
495
506
|
return handleExitPlanMode(apiKey, input);
|
|
496
507
|
}
|
|
497
|
-
if (
|
|
508
|
+
if (shouldDeferToNativeMode(input.permission_mode, input.tool_name)) {
|
|
498
509
|
return void 0;
|
|
499
510
|
}
|
|
500
511
|
switch (verdict.kind) {
|
|
@@ -525,7 +536,7 @@ var toPermissionRequestOutput = (hookOutput) => {
|
|
|
525
536
|
};
|
|
526
537
|
var handlePermissionRequest = async (input) => {
|
|
527
538
|
if (PRETOOLUSE_HANDLED_TOOLS.has(input.tool_name)) {
|
|
528
|
-
const reclaimDeferredExec = !PRETOOLUSE_PHONE_ANSWERED_TOOLS.includes(input.tool_name) &&
|
|
539
|
+
const reclaimDeferredExec = !PRETOOLUSE_PHONE_ANSWERED_TOOLS.includes(input.tool_name) && shouldDeferToNativeMode(input.permission_mode, input.tool_name);
|
|
529
540
|
if (!reclaimDeferredExec) return void 0;
|
|
530
541
|
}
|
|
531
542
|
if (input.tool_name.startsWith("mcp__pushary__")) return void 0;
|
|
@@ -17,7 +17,7 @@ var isPolicyConfig = (data) => {
|
|
|
17
17
|
var isAskUserResponse = (data) => {
|
|
18
18
|
if (!data || typeof data !== "object") return false;
|
|
19
19
|
const d = data;
|
|
20
|
-
return typeof d.correlationId === "string" && typeof d.status === "string";
|
|
20
|
+
return typeof d.correlationId === "string" && typeof d.status === "string" && (d.answered === void 0 || typeof d.answered === "boolean") && (d.value === void 0 || typeof d.value === "string") && (d.note === void 0 || typeof d.note === "string") && (d.waitEndsAt === void 0 || typeof d.waitEndsAt === "string");
|
|
21
21
|
};
|
|
22
22
|
var isWaitForAnswerResponse = (data) => {
|
|
23
23
|
if (!data || typeof data !== "object") return false;
|
|
@@ -82,13 +82,14 @@ var commandDirFor = (sessionId, namespace = "") => join(
|
|
|
82
82
|
createHash("sha256").update(namespace).digest("hex").slice(0, 16),
|
|
83
83
|
sanitize(sessionId)
|
|
84
84
|
);
|
|
85
|
-
var
|
|
86
|
-
var
|
|
85
|
+
var legacyCommandFile = (sessionId, namespace = "") => join(commandDirFor(sessionId, namespace), "command.json");
|
|
86
|
+
var commandFile = (sessionId, id, namespace = "") => join(commandDirFor(sessionId, namespace), `${createHash("sha256").update(id).digest("hex")}.json`);
|
|
87
|
+
var readCommandFile = (file) => {
|
|
87
88
|
try {
|
|
88
|
-
const value = JSON.parse(readFileSync(
|
|
89
|
+
const value = JSON.parse(readFileSync(file, "utf-8"));
|
|
89
90
|
if (typeof value.id !== "string" || typeof value.text !== "string" || typeof value.expiresAtMs !== "number") return null;
|
|
90
91
|
if (value.expiresAtMs <= Date.now()) {
|
|
91
|
-
unlinkSync(
|
|
92
|
+
unlinkSync(file);
|
|
92
93
|
return null;
|
|
93
94
|
}
|
|
94
95
|
return {
|
|
@@ -100,23 +101,68 @@ var readPendingCommand = (sessionId, namespace = "") => {
|
|
|
100
101
|
return null;
|
|
101
102
|
}
|
|
102
103
|
};
|
|
104
|
+
var readPendingCommandById = (sessionId, id, namespace = "") => {
|
|
105
|
+
const current = readCommandFile(commandFile(sessionId, id, namespace));
|
|
106
|
+
if (current?.id === id) return current;
|
|
107
|
+
const legacy = readCommandFile(legacyCommandFile(sessionId, namespace));
|
|
108
|
+
return legacy?.id === id ? legacy : null;
|
|
109
|
+
};
|
|
110
|
+
var pruneExpiredCommands = (dir) => {
|
|
111
|
+
let files;
|
|
112
|
+
try {
|
|
113
|
+
files = readdirSync(dir).filter((file) => file.endsWith(".json"));
|
|
114
|
+
} catch {
|
|
115
|
+
return [];
|
|
116
|
+
}
|
|
117
|
+
return files.flatMap((file) => {
|
|
118
|
+
const command = readCommandFile(join(dir, file));
|
|
119
|
+
return command ? [command] : [];
|
|
120
|
+
});
|
|
121
|
+
};
|
|
122
|
+
var pruneExpiredCommandStore = () => {
|
|
123
|
+
let namespaces;
|
|
124
|
+
try {
|
|
125
|
+
namespaces = readdirSync(COMMAND_DIR, { withFileTypes: true });
|
|
126
|
+
} catch {
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
for (const namespace of namespaces.filter((entry) => entry.isDirectory())) {
|
|
130
|
+
const namespaceDir = join(COMMAND_DIR, namespace.name);
|
|
131
|
+
let sessions;
|
|
132
|
+
try {
|
|
133
|
+
sessions = readdirSync(namespaceDir, { withFileTypes: true });
|
|
134
|
+
} catch {
|
|
135
|
+
continue;
|
|
136
|
+
}
|
|
137
|
+
for (const session of sessions.filter((entry) => entry.isDirectory())) {
|
|
138
|
+
pruneExpiredCommands(join(namespaceDir, session.name));
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
var readPendingCommand = (sessionId, namespace = "") => {
|
|
143
|
+
const commands = pruneExpiredCommands(commandDirFor(sessionId, namespace));
|
|
144
|
+
return commands.find((command) => !command.delivered && !command.failed) ?? commands[0] ?? null;
|
|
145
|
+
};
|
|
103
146
|
var savePendingCommand = (sessionId, command, namespace = "") => {
|
|
104
147
|
const dir = commandDirFor(sessionId, namespace);
|
|
105
148
|
try {
|
|
106
149
|
mkdirSync(dir, { recursive: true, mode: 448 });
|
|
107
|
-
|
|
150
|
+
pruneExpiredCommandStore();
|
|
151
|
+
if (readPendingCommandById(sessionId, command.id, namespace)) return false;
|
|
152
|
+
writeFileSync(commandFile(sessionId, command.id, namespace), JSON.stringify(command), { encoding: "utf-8", mode: 384, flag: "wx" });
|
|
108
153
|
return true;
|
|
109
154
|
} catch {
|
|
110
155
|
return false;
|
|
111
156
|
}
|
|
112
157
|
};
|
|
113
158
|
var updatePendingCommand = (sessionId, id, update, namespace = "") => {
|
|
114
|
-
const command =
|
|
115
|
-
if (!command
|
|
116
|
-
const
|
|
159
|
+
const command = readPendingCommandById(sessionId, id, namespace);
|
|
160
|
+
if (!command) return false;
|
|
161
|
+
const currentFile = commandFile(sessionId, id, namespace);
|
|
162
|
+
const file = existsSync(currentFile) ? currentFile : legacyCommandFile(sessionId, namespace);
|
|
117
163
|
const temporary = `${file}.${process.pid}.tmp`;
|
|
118
164
|
try {
|
|
119
|
-
writeFileSync(temporary, JSON.stringify({ ...command, ...update }), { encoding: "utf-8", mode: 384 });
|
|
165
|
+
writeFileSync(temporary, JSON.stringify({ ...command, ...update, text: "" }), { encoding: "utf-8", mode: 384 });
|
|
120
166
|
renameSync(temporary, file);
|
|
121
167
|
return true;
|
|
122
168
|
} catch {
|
|
@@ -130,9 +176,15 @@ var updatePendingCommand = (sessionId, id, update, namespace = "") => {
|
|
|
130
176
|
var markPendingCommandDelivered = (sessionId, id, namespace = "") => updatePendingCommand(sessionId, id, { delivered: true, failed: void 0 }, namespace);
|
|
131
177
|
var markPendingCommandFailed = (sessionId, id, namespace = "") => updatePendingCommand(sessionId, id, { delivered: false, failed: true }, namespace);
|
|
132
178
|
var removePendingCommand = (sessionId, id, namespace = "") => {
|
|
133
|
-
if (
|
|
179
|
+
if (!readPendingCommandById(sessionId, id, namespace)) return;
|
|
180
|
+
try {
|
|
181
|
+
unlinkSync(commandFile(sessionId, id, namespace));
|
|
182
|
+
} catch {
|
|
183
|
+
}
|
|
134
184
|
try {
|
|
135
|
-
|
|
185
|
+
if (readCommandFile(legacyCommandFile(sessionId, namespace))?.id === id) {
|
|
186
|
+
unlinkSync(legacyCommandFile(sessionId, namespace));
|
|
187
|
+
}
|
|
136
188
|
} catch {
|
|
137
189
|
}
|
|
138
190
|
};
|
|
@@ -181,6 +233,7 @@ export {
|
|
|
181
233
|
cancelQuestion,
|
|
182
234
|
sendNotification,
|
|
183
235
|
DEFAULT_SESSION,
|
|
236
|
+
readPendingCommandById,
|
|
184
237
|
readPendingCommand,
|
|
185
238
|
savePendingCommand,
|
|
186
239
|
markPendingCommandDelivered,
|