@pushary/agent-hooks 1.3.1 → 1.4.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/README.md +1 -1
- package/dist/bin/pushary-bell-hook.js +18 -18
- package/dist/bin/pushary-bell.js +8 -8
- package/dist/bin/pushary-claude.js +18 -18
- package/dist/bin/pushary-clean.js +470 -92
- package/dist/bin/pushary-codex-bridge.js +10 -10
- package/dist/bin/pushary-codex-hook.js +28 -26
- package/dist/bin/pushary-codex.js +6 -6
- package/dist/bin/pushary-connect.js +8 -8
- package/dist/bin/pushary-cowork.js +5 -5
- package/dist/bin/pushary-daemon.js +24 -24
- package/dist/bin/pushary-disconnect.js +12 -12
- package/dist/bin/pushary-doctor.js +75 -26
- 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 +27 -27
- package/dist/bin/pushary-login.js +9 -9
- package/dist/bin/pushary-logout.js +6 -6
- package/dist/bin/pushary-mode.js +5 -5
- 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 +38 -59
- package/dist/bin/pushary-stats.js +4 -4
- package/dist/bin/pushary-status.js +12 -12
- package/dist/bin/pushary-stop-hook.js +20 -20
- package/dist/bin/pushary-stopfailure-hook.js +20 -20
- package/dist/bin/pushary-suggestions.js +2 -2
- package/dist/bin/pushary-transcript-register.js +16 -16
- package/dist/bin/pushary-transcripts.js +6 -6
- package/dist/bin/pushary-upgrade.js +16 -16
- package/dist/bin/pushary-wait.js +5 -5
- package/dist/bin/pushary.js +1 -1
- package/dist/{chunk-QDYJQLXT.js → chunk-2TOTCUJC.js} +2 -2
- package/dist/{chunk-I2OLM3DM.js → chunk-43Z3RLS5.js} +62 -12
- package/dist/{chunk-OMP3KDDU.js → chunk-5F5QQMCA.js} +1 -1
- package/dist/{chunk-SGZE2JBF.js → chunk-5IBVIMWT.js} +3 -3
- package/dist/{chunk-FGNABUPN.js → chunk-5MSBI6NP.js} +1 -1
- package/dist/{chunk-5UWDYOZX.js → chunk-7IEB2GV4.js} +80 -8
- package/dist/{chunk-EAGMQMRM.js → chunk-7PQZYCEP.js} +1 -1
- package/dist/{chunk-KHGIM2BN.js → chunk-A7XIL2WD.js} +3 -3
- package/dist/{chunk-YXWM4TNX.js → chunk-BYAXXBNO.js} +1 -1
- package/dist/{chunk-TW7KA27C.js → chunk-D4TNSUDY.js} +1 -1
- package/dist/{chunk-P232YODQ.js → chunk-ESLLVHDY.js} +6 -6
- package/dist/{chunk-LZQVAEWP.js → chunk-FAH3D74E.js} +2 -1
- package/dist/{chunk-XOUQUZ43.js → chunk-GIXLZFEY.js} +1 -1
- package/dist/{chunk-PHXU4NOP.js → chunk-GLPWCQ6V.js} +2 -2
- package/dist/{chunk-NDSOOJDX.js → chunk-GS5EI2YL.js} +1 -1
- package/dist/{chunk-R5CU7ED6.js → chunk-H25UB3CG.js} +1 -1
- package/dist/{chunk-LWT34GSY.js → chunk-HGN6VZTY.js} +7 -7
- package/dist/{chunk-WOBHHXW5.js → chunk-IF46POXX.js} +5 -4
- package/dist/{chunk-HCTSTMDD.js → chunk-JCWCTBYH.js} +3 -3
- package/dist/{chunk-XP2KRTZD.js → chunk-KZIXHLPQ.js} +1 -1
- package/dist/{chunk-AFOTOA24.js → chunk-NBCTKC4Z.js} +34 -3
- package/dist/{chunk-5SALHATY.js → chunk-NYHNLMQO.js} +11 -2
- package/dist/{chunk-PEV6ULSM.js → chunk-O5L2OJBB.js} +3 -3
- package/dist/{chunk-QOCWB4Q6.js → chunk-O6RN46OS.js} +3 -3
- package/dist/{chunk-5WLH2ENB.js → chunk-P4JVVJ2D.js} +1 -1
- package/dist/{chunk-XVE52YFZ.js → chunk-Q4UAMWXK.js} +1 -1
- package/dist/{chunk-6HH4IH4K.js → chunk-RGZY77CD.js} +3 -3
- package/dist/{chunk-465UENKO.js → chunk-RQM5SMMR.js} +1 -1
- package/dist/{chunk-RERJ2ZDV.js → chunk-S3CLZSV3.js} +5 -5
- package/dist/{chunk-CDSL3LLO.js → chunk-S3EUZZJB.js} +1 -1
- package/dist/{chunk-AFKOWCMQ.js → chunk-SGZ3IAWF.js} +1 -1
- package/dist/{chunk-GOQHN2UH.js → chunk-TWWLVOPB.js} +1 -1
- package/dist/{chunk-TGG4FWWB.js → chunk-U4FB623J.js} +2 -2
- package/dist/{chunk-34NNTYK6.js → chunk-UCGQEAKZ.js} +1 -1
- package/dist/{chunk-5XKMOZO6.js → chunk-UIN3RD2U.js} +4 -4
- package/dist/{chunk-REIZ5GXG.js → chunk-UTYTPDWN.js} +4 -4
- package/dist/{chunk-35RPUNYU.js → chunk-VENQSVKA.js} +1 -1
- package/dist/{chunk-JZA2JOGO.js → chunk-XJWMPQ6X.js} +1 -1
- package/dist/{chunk-KLZJEMSE.js → chunk-YYRZPEMA.js} +1 -1
- package/dist/{chunk-CKLWJ6EL.js → chunk-ZIGGEKZW.js} +33 -7
- package/dist/{reapply-ADFRVH5N.js → reapply-B3S2LRMT.js} +8 -8
- package/dist/src/index.d.ts +19 -16
- package/dist/src/index.js +12 -12
- package/package.json +1 -1
package/dist/bin/pushary-wait.js
CHANGED
|
@@ -4,15 +4,15 @@ import {
|
|
|
4
4
|
} from "../chunk-CVWG2N3Y.js";
|
|
5
5
|
import {
|
|
6
6
|
exitOnFailedResponse
|
|
7
|
-
} from "../chunk-
|
|
8
|
-
import "../chunk-
|
|
7
|
+
} from "../chunk-GS5EI2YL.js";
|
|
8
|
+
import "../chunk-D4TNSUDY.js";
|
|
9
9
|
import {
|
|
10
10
|
createIo
|
|
11
11
|
} from "../chunk-5RUIFDTP.js";
|
|
12
12
|
import {
|
|
13
13
|
exitOnHelpFlag
|
|
14
|
-
} from "../chunk-
|
|
15
|
-
import "../chunk-
|
|
14
|
+
} from "../chunk-TWWLVOPB.js";
|
|
15
|
+
import "../chunk-FAH3D74E.js";
|
|
16
16
|
import {
|
|
17
17
|
rejectUnknownFlags
|
|
18
18
|
} from "../chunk-GMXKITVA.js";
|
|
@@ -28,7 +28,7 @@ import {
|
|
|
28
28
|
getApiKey,
|
|
29
29
|
getBaseUrl
|
|
30
30
|
} from "../chunk-2UMNXADU.js";
|
|
31
|
-
import "../chunk-
|
|
31
|
+
import "../chunk-7IEB2GV4.js";
|
|
32
32
|
|
|
33
33
|
// bin/pushary-wait.ts
|
|
34
34
|
exitOnHelpFlag("wait");
|
package/dist/bin/pushary.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
SETUP_FLAGS
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-5MSBI6NP.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-7IEB2GV4.js";
|
|
18
18
|
|
|
19
19
|
// src/cli/cowork.ts
|
|
20
20
|
import { readFileSync } from "fs";
|
|
@@ -1,22 +1,24 @@
|
|
|
1
1
|
import {
|
|
2
|
+
activeHookSource,
|
|
2
3
|
activeIdentity
|
|
3
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-HGN6VZTY.js";
|
|
4
5
|
import {
|
|
5
6
|
blockedActionFingerprint,
|
|
6
7
|
defersToNativeMode,
|
|
7
8
|
forgetBlockedActionHint,
|
|
8
9
|
hasBlockedActionHint,
|
|
9
10
|
recordBlockedActionHint
|
|
10
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-JCWCTBYH.js";
|
|
11
12
|
import {
|
|
12
13
|
isGatingMoment,
|
|
13
14
|
recordKeylessMoment
|
|
14
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-5F5QQMCA.js";
|
|
15
16
|
import {
|
|
16
17
|
denyReasonFrom,
|
|
17
18
|
isDeferAnswer
|
|
18
19
|
} from "./chunk-YHG74UFF.js";
|
|
19
20
|
import {
|
|
21
|
+
AUTO_DECISION_WINDOW_MS,
|
|
20
22
|
DEFAULT_SESSION,
|
|
21
23
|
UNNAMED_ACTION,
|
|
22
24
|
deriveAction,
|
|
@@ -34,7 +36,7 @@ import {
|
|
|
34
36
|
scopePathFor,
|
|
35
37
|
settleQuestionsForToolUse,
|
|
36
38
|
throttlePass
|
|
37
|
-
} from "./chunk-
|
|
39
|
+
} from "./chunk-IF46POXX.js";
|
|
38
40
|
import {
|
|
39
41
|
DECISION_STOP_REASON,
|
|
40
42
|
askUser,
|
|
@@ -49,18 +51,22 @@ import {
|
|
|
49
51
|
} from "./chunk-LGXUGYUH.js";
|
|
50
52
|
import {
|
|
51
53
|
getMachineId
|
|
52
|
-
} from "./chunk-
|
|
54
|
+
} from "./chunk-RQM5SMMR.js";
|
|
53
55
|
import {
|
|
54
56
|
getApiKey,
|
|
55
57
|
getBaseUrl
|
|
56
58
|
} from "./chunk-2UMNXADU.js";
|
|
57
59
|
import {
|
|
60
|
+
AGENT_QUESTION_STRATEGY,
|
|
58
61
|
GATE_BLOCK_REASON_MAX_LENGTH,
|
|
59
62
|
GATE_WIRE,
|
|
63
|
+
agentQuestionStrategy,
|
|
60
64
|
buildDecisionEpisodeFeatures,
|
|
61
65
|
claudePermissionDeniedOutput,
|
|
62
66
|
claudePermissionRequestOutput,
|
|
63
67
|
claudePreToolUseOutput,
|
|
68
|
+
claudePromptsBeforeAnEdit,
|
|
69
|
+
editAsksAtTheAgentsPrompt,
|
|
64
70
|
effectiveWaitSeconds,
|
|
65
71
|
hookHoldWindowMs,
|
|
66
72
|
hookWaitClamped,
|
|
@@ -69,11 +75,13 @@ import {
|
|
|
69
75
|
isBlockedActionRequest,
|
|
70
76
|
isPermissionRequestOwnedByPreToolUse,
|
|
71
77
|
isPusharyOwnTool,
|
|
78
|
+
machineDecisionFor,
|
|
72
79
|
parseAgentQuestionAnswers,
|
|
73
80
|
parseAgentQuestions,
|
|
74
81
|
resolveGate,
|
|
75
|
-
stoppedOutput
|
|
76
|
-
|
|
82
|
+
stoppedOutput,
|
|
83
|
+
wireVerdictFor
|
|
84
|
+
} from "./chunk-7IEB2GV4.js";
|
|
77
85
|
|
|
78
86
|
// src/decision-episode.ts
|
|
79
87
|
var EPISODE_PATH = "/api/agent/decision-episode";
|
|
@@ -103,12 +111,38 @@ import { tmpdir } from "os";
|
|
|
103
111
|
import { existsSync, writeFileSync } from "fs";
|
|
104
112
|
var START_MS = Date.now();
|
|
105
113
|
var ACTIVE_AGENT = activeIdentity(process.argv);
|
|
114
|
+
var ACTIVE_SOURCE = activeHookSource(process.argv);
|
|
106
115
|
var agentNameIn = (projectName) => `${ACTIVE_AGENT.label} - ${projectName}`;
|
|
107
116
|
var allow = (reason) => claudePreToolUseOutput("allow", reason);
|
|
108
117
|
var deny = (reason) => claudePreToolUseOutput("deny", reason);
|
|
109
118
|
var allowWithInput = (updatedInput) => claudePreToolUseOutput("allow", void 0, updatedInput);
|
|
110
119
|
var ask = (reason) => claudePreToolUseOutput("ask", reason);
|
|
111
120
|
var halted = (reason) => stoppedOutput(deny(reason), reason);
|
|
121
|
+
var reportMachineDecision = async (input, verdict) => {
|
|
122
|
+
const decision = machineDecisionFor(wireVerdictFor(verdict, 0));
|
|
123
|
+
if (!decision) return;
|
|
124
|
+
const sessionKey = input.session_id || DEFAULT_SESSION;
|
|
125
|
+
const toolTarget = deriveToolTarget(input.tool_name, input.tool_input);
|
|
126
|
+
const throttleKey = `machinedecision:${sessionKey}:${input.tool_name}:${decision.origin}:${toolTarget ?? ""}`;
|
|
127
|
+
if (!throttlePass(throttleKey, AUTO_DECISION_WINDOW_MS)) return;
|
|
128
|
+
await reportEvent(
|
|
129
|
+
{
|
|
130
|
+
event: "permission_denied",
|
|
131
|
+
occurredAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
132
|
+
toolUseId: input.tool_use_id,
|
|
133
|
+
agentType: ACTIVE_AGENT.type,
|
|
134
|
+
agentName: agentNameIn(basename(input.cwd ?? process.cwd())),
|
|
135
|
+
action: permissionDeniedAction(input.tool_name),
|
|
136
|
+
sessionId: input.session_id,
|
|
137
|
+
decisionSource: "policy_auto",
|
|
138
|
+
decisionOrigin: decision.origin,
|
|
139
|
+
decisionOutcome: decision.outcome,
|
|
140
|
+
toolName: input.tool_name,
|
|
141
|
+
toolTarget
|
|
142
|
+
},
|
|
143
|
+
{ maxAttempts: 1, timeoutMs: 800 }
|
|
144
|
+
).catch(() => void 0);
|
|
145
|
+
};
|
|
112
146
|
var storedWaitDeadline = (result, requestedDeadline) => {
|
|
113
147
|
const stored = result.waitEndsAt ? Date.parse(result.waitEndsAt) : Number.NaN;
|
|
114
148
|
return Number.isFinite(stored) ? Math.min(stored, requestedDeadline) : requestedDeadline;
|
|
@@ -519,11 +553,19 @@ var handlePreToolUse = async (input, canonical) => {
|
|
|
519
553
|
try {
|
|
520
554
|
const modeState = await fetchModeState(apiKey, input.session_id);
|
|
521
555
|
const policy = await getPolicy(apiKey, modeState.policyVersion, ACTIVE_AGENT.type, true, input.session_id);
|
|
522
|
-
const
|
|
523
|
-
|
|
524
|
-
if (verdict.kind === "
|
|
556
|
+
const gateInput = claudeGateInput(modeState, policy, input, canonical);
|
|
557
|
+
const verdict = resolveGate(gateInput);
|
|
558
|
+
if (verdict.kind === "kill") {
|
|
559
|
+
await reportMachineDecision(input, verdict);
|
|
560
|
+
return halted(verdict.reason);
|
|
561
|
+
}
|
|
562
|
+
if (verdict.kind === "deny") {
|
|
563
|
+
await reportMachineDecision(input, verdict);
|
|
564
|
+
return deny(verdict.reason);
|
|
565
|
+
}
|
|
525
566
|
if (canonical === null) return deny(unreadableReason);
|
|
526
567
|
if (verdict.kind === "gate" && verdict.scopeReason && (canonical?.toolInputs.length ?? 0) > 1) return deny(batchScopeReason);
|
|
568
|
+
if (agentQuestionStrategy(ACTIVE_SOURCE, "PreToolUse", input.tool_name) === AGENT_QUESTION_STRATEGY.native) return void 0;
|
|
527
569
|
if (input.tool_name === "AskUserQuestion") {
|
|
528
570
|
return handleAskUserQuestion(apiKey, input, modeState);
|
|
529
571
|
}
|
|
@@ -534,6 +576,7 @@ var handlePreToolUse = async (input, canonical) => {
|
|
|
534
576
|
if (!(verdict.kind === "gate" && verdict.scopeReason) && shouldDeferToNativeMode(input.permission_mode, input.tool_name)) {
|
|
535
577
|
return void 0;
|
|
536
578
|
}
|
|
579
|
+
if (claudePromptsBeforeAnEdit(input.permission_mode) && editAsksAtTheAgentsPrompt(gateInput, verdict)) return handleTerminalOnly();
|
|
537
580
|
switch (verdict.kind) {
|
|
538
581
|
case "allow":
|
|
539
582
|
return allow();
|
|
@@ -574,9 +617,16 @@ var handlePermissionRequest = async (input, canonical) => {
|
|
|
574
617
|
const modeState = await fetchModeState(apiKey, input.session_id);
|
|
575
618
|
const policy = await getPolicy(apiKey, modeState.policyVersion, ACTIVE_AGENT.type, true, input.session_id);
|
|
576
619
|
const verdict = resolveGate(claudeGateInput(modeState, policy, input, canonical));
|
|
577
|
-
if (verdict.kind === "kill")
|
|
578
|
-
|
|
620
|
+
if (verdict.kind === "kill") {
|
|
621
|
+
await reportMachineDecision(input, verdict);
|
|
622
|
+
return permReqHalted(verdict.reason);
|
|
623
|
+
}
|
|
624
|
+
if (verdict.kind === "deny") {
|
|
625
|
+
await reportMachineDecision(input, verdict);
|
|
626
|
+
return permReqDeny(verdict.reason);
|
|
627
|
+
}
|
|
579
628
|
if (canonical === null) return permReqDeny(unreadableReason);
|
|
629
|
+
if (agentQuestionStrategy(ACTIVE_SOURCE, "PermissionRequest", input.tool_name) === AGENT_QUESTION_STRATEGY.native) return void 0;
|
|
580
630
|
if (verdict.kind === "gate" && verdict.scopeReason && (canonical?.toolInputs.length ?? 0) > 1) return permReqDeny(batchScopeReason);
|
|
581
631
|
if (!(verdict.kind === "gate" && verdict.scopeReason) && isPermissionRequestOwnedByPreToolUse(input.tool_name, input.permission_mode, shouldDeferToNativeMode)) return void 0;
|
|
582
632
|
switch (verdict.kind) {
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import {
|
|
2
2
|
CLAUDE_HOOK_EVENTS,
|
|
3
3
|
supportedClaudeEvents
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-A7XIL2WD.js";
|
|
5
5
|
import {
|
|
6
6
|
guardBinary,
|
|
7
7
|
holdBudgetOf,
|
|
8
8
|
isProtectedByScope,
|
|
9
9
|
registerHookEntry
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-UCGQEAKZ.js";
|
|
11
11
|
import {
|
|
12
12
|
HOOK_LOCATOR_BINARY,
|
|
13
13
|
withHookHoldBudget
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-7IEB2GV4.js";
|
|
15
15
|
|
|
16
16
|
// src/claude-config.ts
|
|
17
17
|
import { join } from "path";
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
import {
|
|
8
8
|
COMPATIBLE_AGENT_TYPES,
|
|
9
9
|
isValidApiKey
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-7IEB2GV4.js";
|
|
11
11
|
|
|
12
12
|
// src/setup/options.ts
|
|
13
13
|
var AGENT_CHOICES = ["claude_code", "codex", "gemini_cli", "hermes", "cursor", "vscode", "opencode", ...COMPATIBLE_AGENT_TYPES, "custom"];
|
|
@@ -216,7 +216,7 @@ var AGENTS = {
|
|
|
216
216
|
connectVia: "Native hooks",
|
|
217
217
|
setupCommand: "npx @pushary/agent-hooks setup",
|
|
218
218
|
enforcementDetail: "exec, write and edit through native PreToolUse hooks, answered in Devin's own approve/block schema.",
|
|
219
|
-
capabilityNote: "Devin CLI answers PreToolUse with `{decision}` rather than a permission decision.
|
|
219
|
+
capabilityNote: "Devin CLI answers PreToolUse with `{decision}` rather than a permission decision. Pushary blocks an unanswered approval because this adapter cannot request a native prompt reliably. Question and plan dialogs remain with Devin; this adapter does not render their answers. It also fires no Notification event."
|
|
220
220
|
},
|
|
221
221
|
windsurf: {
|
|
222
222
|
...defaults,
|
|
@@ -292,7 +292,8 @@ var toToolLookup = (profile, toolName, toolInput, resolvePath = (path) => path)
|
|
|
292
292
|
var renderPreToolUseVerdict = (profile, verdict) => {
|
|
293
293
|
if (profile.wire === "permission_decision") return verdict;
|
|
294
294
|
const { permissionDecision, permissionDecisionReason, updatedInput } = verdict.hookSpecificOutput;
|
|
295
|
-
if (permissionDecision === "ask"
|
|
295
|
+
if (permissionDecision === "ask") return { decision: "block", reason: permissionDecisionReason ?? "Pushary requires an explicit approval before this tool can run." };
|
|
296
|
+
if (updatedInput) return void 0;
|
|
296
297
|
const stop = verdict.continue === false ? { continue: false, ...verdict.stopReason ? { stopReason: verdict.stopReason } : {} } : {};
|
|
297
298
|
return {
|
|
298
299
|
decision: permissionDecision === "allow" ? "approve" : "block",
|
|
@@ -333,7 +334,9 @@ var QWEN_CODE = {
|
|
|
333
334
|
replace: "Edit",
|
|
334
335
|
read_file: "Read",
|
|
335
336
|
WriteFile: "Write",
|
|
336
|
-
ReadFile: "Read"
|
|
337
|
+
ReadFile: "Read",
|
|
338
|
+
ask_user_question: "AskUserQuestion",
|
|
339
|
+
exit_plan_mode: "ExitPlanMode"
|
|
337
340
|
},
|
|
338
341
|
extraMatchers: ["mcp__.*"],
|
|
339
342
|
pathInputKeys: ["absolute_path"],
|
|
@@ -415,12 +418,14 @@ var DEVIN = {
|
|
|
415
418
|
exec: "Bash",
|
|
416
419
|
write: "Write",
|
|
417
420
|
edit: "Edit",
|
|
421
|
+
apply_patch: "Edit",
|
|
422
|
+
notebook_edit: "NotebookEdit",
|
|
418
423
|
read: "Read",
|
|
419
424
|
webfetch: "WebFetch",
|
|
420
425
|
web_search: "WebSearch",
|
|
421
426
|
run_subagent: "Task"
|
|
422
427
|
},
|
|
423
|
-
extraMatchers: ["mcp__.*"],
|
|
428
|
+
extraMatchers: ["mcp__.*", "mcp_call_tool", "write_to_process"],
|
|
424
429
|
pathInputKeys: [],
|
|
425
430
|
shellCommandKeys: [],
|
|
426
431
|
shellContextKeys: [],
|
|
@@ -602,6 +607,8 @@ var hookWaitClamped = (startMs, policyWaitSeconds, agent, nowMs) => startMs + ho
|
|
|
602
607
|
var effectiveWaitSeconds = (timeoutAction, policySeconds, agent) => timeoutAction === "wait" ? hookMaxWaitSeconds(agent) : policySeconds;
|
|
603
608
|
var OPENCODE_APPROVAL_EVENT = "permission.ask";
|
|
604
609
|
var CURSOR_GATE_EVENTS = ["beforeShellExecution", "beforeMCPExecution", "preToolUse"];
|
|
610
|
+
var SUPPORT_EMAIL = "business@pushary.com";
|
|
611
|
+
var SUPPORT_DISCORD = "https://discord.gg/9v3VvUByrr";
|
|
605
612
|
var HOOK_LOCATOR_BINARY = "pushary-bridge";
|
|
606
613
|
var HOOK_BATCH_MAX_BYTES = 4 * 1024 * 1024;
|
|
607
614
|
var REPO_KEY_MAX_LENGTH = 200;
|
|
@@ -1344,6 +1351,10 @@ var ANSWER_SOURCES = [
|
|
|
1344
1351
|
];
|
|
1345
1352
|
var isAnswerSource = (value) => typeof value === "string" && ANSWER_SOURCES.includes(value);
|
|
1346
1353
|
var SETTLED_OUTCOMES = ["approve", "deny"];
|
|
1354
|
+
var SETTLED_OUTCOME = {
|
|
1355
|
+
approve: "approve",
|
|
1356
|
+
deny: "deny"
|
|
1357
|
+
};
|
|
1347
1358
|
var isSettledOutcome = (value) => typeof value === "string" && SETTLED_OUTCOMES.includes(value);
|
|
1348
1359
|
var classifyDecisionRisk = (toolName, toolTarget) => {
|
|
1349
1360
|
const parts = [toolName, toolTarget ?? ""];
|
|
@@ -1621,6 +1632,10 @@ var resolvePolicyAcross = (config, toolName, modeOverride, toolInputs, cwd, repo
|
|
|
1621
1632
|
};
|
|
1622
1633
|
var isModeStateDegraded = (state) => state?.degraded === true;
|
|
1623
1634
|
var KILL_REASON = "Stopped by user, this agent was halted from Pushary";
|
|
1635
|
+
var GATE_ALLOW_SOURCE = {
|
|
1636
|
+
allowlist: "allowlist",
|
|
1637
|
+
policy: "policy"
|
|
1638
|
+
};
|
|
1624
1639
|
var PUSHARY_TOOL_PREFIX = "mcp__pushary__";
|
|
1625
1640
|
var isPusharyOwnTool = (toolName) => toolName.startsWith(PUSHARY_TOOL_PREFIX);
|
|
1626
1641
|
var strictestScopeVerdict = (scope, paths) => {
|
|
@@ -1649,7 +1664,15 @@ var shouldDeferToNativeMode = (permissionMode, toolName, options = {}) => {
|
|
|
1649
1664
|
if (permissionMode === "bypassPermissions") return options.deferBypass === true;
|
|
1650
1665
|
return false;
|
|
1651
1666
|
};
|
|
1652
|
-
var
|
|
1667
|
+
var AGENT_QUESTION_TOOL = "AskUserQuestion";
|
|
1668
|
+
var AGENT_QUESTION_STRATEGY = { native: "native_dialog", updatedInput: "updated_input", none: "not_a_question" };
|
|
1669
|
+
var UPDATED_INPUT_QUESTION_SOURCES = /* @__PURE__ */ new Set(["claude", "qoder", "codebuddy", "droid"]);
|
|
1670
|
+
function agentQuestionStrategy(source, event, toolName) {
|
|
1671
|
+
if (toolName !== AGENT_QUESTION_TOOL) return AGENT_QUESTION_STRATEGY.none;
|
|
1672
|
+
if (source !== null && event === "PreToolUse" && UPDATED_INPUT_QUESTION_SOURCES.has(source)) return AGENT_QUESTION_STRATEGY.updatedInput;
|
|
1673
|
+
return AGENT_QUESTION_STRATEGY.native;
|
|
1674
|
+
}
|
|
1675
|
+
var ASKED_IN_EVERY_MODE_TOOLS = [AGENT_QUESTION_TOOL, "ExitPlanMode"];
|
|
1653
1676
|
var ASKED_IN_EVERY_MODE = new Set(ASKED_IN_EVERY_MODE_TOOLS);
|
|
1654
1677
|
var isAskedInEveryMode = (toolName) => ASKED_IN_EVERY_MODE.has(toolName);
|
|
1655
1678
|
var NATIVE_BLOCK_EVENTS = /* @__PURE__ */ new Set(["PermissionDenied"]);
|
|
@@ -1728,6 +1751,8 @@ var resolveGate = (input) => {
|
|
|
1728
1751
|
scopePath: scopeReason && "path" in scopeVerdict ? widenablePath(scopeVerdict.path) : void 0
|
|
1729
1752
|
};
|
|
1730
1753
|
};
|
|
1754
|
+
var editAsksAtTheAgentsPrompt = (input, verdict) => verdict.kind === "gate" && !verdict.scopeReason && (input.modeState.mode ?? input.config.modeOverride ?? null) === null && verdict.policy.origin === "builtin" && verdict.policy.mode === "push_first" && ACCEPT_EDITS_DEFER_TOOLS.has(input.toolName);
|
|
1755
|
+
var claudePromptsBeforeAnEdit = (permissionMode) => permissionMode === "default";
|
|
1731
1756
|
var toPolicyVersion = (value) => typeof value === "string" || typeof value === "number" ? String(value) : null;
|
|
1732
1757
|
var modeStateFromResponse = (data) => {
|
|
1733
1758
|
const mode = data.override?.mode;
|
|
@@ -1747,6 +1772,42 @@ var modeStateFromResponse = (data) => {
|
|
|
1747
1772
|
var GATE_WIRE = 1;
|
|
1748
1773
|
var GATE_MAX_TOOL_INPUTS = 32;
|
|
1749
1774
|
var GATE_BLOCK_REASON_MAX_LENGTH = 200;
|
|
1775
|
+
var wireVerdictFor = (verdict, deadlineSeconds) => {
|
|
1776
|
+
switch (verdict.kind) {
|
|
1777
|
+
case "kill":
|
|
1778
|
+
return { kind: "kill", reason: verdict.reason };
|
|
1779
|
+
case "allow":
|
|
1780
|
+
return { kind: "allow", source: verdict.source, policy: verdict.policy };
|
|
1781
|
+
case "deny":
|
|
1782
|
+
return { kind: "deny", reason: verdict.reason, policy: verdict.policy };
|
|
1783
|
+
case "defer":
|
|
1784
|
+
return { kind: "no_opinion", reason: verdict.reason === "own_tool" ? "not_gated" : "degraded" };
|
|
1785
|
+
case "gate":
|
|
1786
|
+
return {
|
|
1787
|
+
kind: "ask",
|
|
1788
|
+
policy: verdict.policy,
|
|
1789
|
+
deadlineSeconds,
|
|
1790
|
+
...verdict.scopeReason ? { scopeReason: verdict.scopeReason } : {},
|
|
1791
|
+
...verdict.scopePath ? { scopePath: verdict.scopePath } : {}
|
|
1792
|
+
};
|
|
1793
|
+
}
|
|
1794
|
+
};
|
|
1795
|
+
var machineDecisionFor = (verdict) => {
|
|
1796
|
+
switch (verdict.kind) {
|
|
1797
|
+
case "kill":
|
|
1798
|
+
return { origin: DECISION_ORIGIN.killSwitch, outcome: SETTLED_OUTCOME.deny };
|
|
1799
|
+
case "allow":
|
|
1800
|
+
return {
|
|
1801
|
+
origin: verdict.source === GATE_ALLOW_SOURCE.allowlist ? DECISION_ORIGIN.safeReadonly : DECISION_ORIGIN.autopilot,
|
|
1802
|
+
outcome: SETTLED_OUTCOME.approve
|
|
1803
|
+
};
|
|
1804
|
+
case "deny":
|
|
1805
|
+
return { origin: DECISION_ORIGIN.autopilot, outcome: SETTLED_OUTCOME.deny };
|
|
1806
|
+
case "ask":
|
|
1807
|
+
case "no_opinion":
|
|
1808
|
+
return null;
|
|
1809
|
+
}
|
|
1810
|
+
};
|
|
1750
1811
|
var claudePermissionDeniedOutput = (decision) => ({
|
|
1751
1812
|
hookSpecificOutput: {
|
|
1752
1813
|
hookEventName: "PermissionDenied",
|
|
@@ -1807,7 +1868,6 @@ var claudePermissionRequestOutput = (decision, reason, updatedInput) => ({
|
|
|
1807
1868
|
decision: decision === "allow" ? { behavior: "allow", ...updatedInput ? { updatedInput } : {} } : { behavior: "deny", ...reason ? { message: reason } : {} }
|
|
1808
1869
|
}
|
|
1809
1870
|
});
|
|
1810
|
-
var COMPATIBLE_GATE_EVENT = "PreToolUse";
|
|
1811
1871
|
var gateOutputFor = (source, event, decision, reason) => {
|
|
1812
1872
|
let output;
|
|
1813
1873
|
if (source === "claude" || source === "vscode") {
|
|
@@ -1847,8 +1907,12 @@ var gateOutputFor = (source, event, decision, reason) => {
|
|
|
1847
1907
|
};
|
|
1848
1908
|
} else {
|
|
1849
1909
|
const profile = hookCompatibleProfileBySource(source);
|
|
1850
|
-
if (profile
|
|
1851
|
-
|
|
1910
|
+
if (profile?.events.includes(event)) {
|
|
1911
|
+
if (event === "PreToolUse") {
|
|
1912
|
+
output = renderPreToolUseVerdict(profile, claudePreToolUseOutput(decision, reason));
|
|
1913
|
+
} else if (event === "PermissionRequest" && decision !== "ask") {
|
|
1914
|
+
output = claudePermissionRequestOutput(decision, reason);
|
|
1915
|
+
}
|
|
1852
1916
|
}
|
|
1853
1917
|
}
|
|
1854
1918
|
return output;
|
|
@@ -2037,6 +2101,8 @@ export {
|
|
|
2037
2101
|
effectiveWaitSeconds,
|
|
2038
2102
|
OPENCODE_APPROVAL_EVENT,
|
|
2039
2103
|
CURSOR_GATE_EVENTS,
|
|
2104
|
+
SUPPORT_EMAIL,
|
|
2105
|
+
SUPPORT_DISCORD,
|
|
2040
2106
|
HOOK_LOCATOR_BINARY,
|
|
2041
2107
|
normalizeRepoRemote,
|
|
2042
2108
|
localRepoKey,
|
|
@@ -2055,6 +2121,8 @@ export {
|
|
|
2055
2121
|
KILL_REASON,
|
|
2056
2122
|
isPusharyOwnTool,
|
|
2057
2123
|
shouldDeferToNativeMode,
|
|
2124
|
+
AGENT_QUESTION_STRATEGY,
|
|
2125
|
+
agentQuestionStrategy,
|
|
2058
2126
|
CODEX_RESCUE_TOOL_NAME,
|
|
2059
2127
|
isBlockedActionRequest,
|
|
2060
2128
|
BLOCKED_ACTION_GRANT_TTL_SECONDS,
|
|
@@ -2063,10 +2131,14 @@ export {
|
|
|
2063
2131
|
isPermissionRequestOwnedByPreToolUse,
|
|
2064
2132
|
CLAUDE_PRETOOLUSE_MATCHER,
|
|
2065
2133
|
resolveGate,
|
|
2134
|
+
editAsksAtTheAgentsPrompt,
|
|
2135
|
+
claudePromptsBeforeAnEdit,
|
|
2066
2136
|
modeStateFromResponse,
|
|
2067
2137
|
GATE_WIRE,
|
|
2068
2138
|
GATE_MAX_TOOL_INPUTS,
|
|
2069
2139
|
GATE_BLOCK_REASON_MAX_LENGTH,
|
|
2140
|
+
wireVerdictFor,
|
|
2141
|
+
machineDecisionFor,
|
|
2070
2142
|
claudePermissionDeniedOutput,
|
|
2071
2143
|
codexStopRescueOutput,
|
|
2072
2144
|
stoppedOutput,
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import {
|
|
2
2
|
NOTIFICATION_MATCHED_TYPES,
|
|
3
3
|
POSTTOOLUSE_MIRRORED_TOOLS
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-KZIXHLPQ.js";
|
|
5
5
|
import {
|
|
6
6
|
isProtectedByScope,
|
|
7
7
|
registerHookEntry
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-UCGQEAKZ.js";
|
|
9
9
|
import {
|
|
10
10
|
CLAUDE_PRETOOLUSE_MATCHER,
|
|
11
11
|
HOOK_BUDGETS,
|
|
12
12
|
HOOK_LOCATOR_BINARY
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-7IEB2GV4.js";
|
|
14
14
|
|
|
15
15
|
// src/gemini-config.ts
|
|
16
16
|
var GEMINI_HOOK_BINARY = "pushary-gemini-hook";
|
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
import {
|
|
14
14
|
isValidApiKey,
|
|
15
15
|
normalizeKeyScope
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-7IEB2GV4.js";
|
|
17
17
|
|
|
18
18
|
// src/session.ts
|
|
19
19
|
var samePusharyAccount = (left, right) => left.kind === "ok" && right.kind === "ok" && left.identity.workspaceId !== "" && left.identity.workspaceId === right.identity.workspaceId && left.identity.siteId === right.identity.siteId;
|
|
@@ -6,16 +6,16 @@ import {
|
|
|
6
6
|
} from "./chunk-SGZJ5LYH.js";
|
|
7
7
|
import {
|
|
8
8
|
hookOwnerOf
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-UTYTPDWN.js";
|
|
10
10
|
import {
|
|
11
11
|
ensureDaemonRunning
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-RGZY77CD.js";
|
|
13
13
|
import {
|
|
14
14
|
buildTranscriptRecords,
|
|
15
15
|
decodePublicKey,
|
|
16
16
|
generateSessionKey,
|
|
17
17
|
wrapSessionKey
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-S3EUZZJB.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-BYAXXBNO.js";
|
|
27
27
|
import {
|
|
28
28
|
codexHome,
|
|
29
29
|
pusharyDir
|
|
30
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-UCGQEAKZ.js";
|
|
31
31
|
import {
|
|
32
32
|
readTranscriptPreference
|
|
33
|
-
} from "./chunk-
|
|
33
|
+
} from "./chunk-NYHNLMQO.js";
|
|
34
34
|
import {
|
|
35
35
|
writeJsonAtomic
|
|
36
36
|
} from "./chunk-T7E75EKA.js";
|
|
@@ -59,7 +59,7 @@ var COMMAND_LIST = [
|
|
|
59
59
|
},
|
|
60
60
|
{ name: "doctor", module: "pushary-doctor", summary: "Verify your Pushary installation is working" },
|
|
61
61
|
{ name: "disconnect", module: "pushary-disconnect", summary: "Turn off one agent (claude|codex|gemini|cursor)" },
|
|
62
|
-
{ name: "clean", module: "pushary-clean", summary: "Remove
|
|
62
|
+
{ name: "clean", module: "pushary-clean", summary: "Remove Pushary from this machine (--everything: the Mac app's setup too, --dry-run: preview)" },
|
|
63
63
|
{ name: "mode", module: "pushary-mode", summary: "Choose where approval requests appear" },
|
|
64
64
|
{ name: "wait", module: "pushary-wait", summary: 'Show or set the "wait for your phone" ladder (pushary wait 45)' },
|
|
65
65
|
{ name: "stats", module: "pushary-stats", summary: "Show the approval moments your agents hit while not connected" },
|
|
@@ -98,6 +98,7 @@ var COMMAND_OPTIONS = {
|
|
|
98
98
|
],
|
|
99
99
|
clean: [
|
|
100
100
|
["--dry-run", "List everything it would remove and change nothing"],
|
|
101
|
+
["--everything", "Also remove what the Mac app set up: quits it, then its keychain items, local state and editor extension"],
|
|
101
102
|
["--yes", "Remove everything without asking"]
|
|
102
103
|
],
|
|
103
104
|
transcripts: [
|
|
@@ -2,10 +2,10 @@ import {
|
|
|
2
2
|
resolveBinary,
|
|
3
3
|
resolveGlobalPackageVersion,
|
|
4
4
|
resolvePackageVersionFromBinary
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-UCGQEAKZ.js";
|
|
6
6
|
import {
|
|
7
7
|
MANAGED_PROVIDERS
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-7IEB2GV4.js";
|
|
9
9
|
|
|
10
10
|
// src/live-capabilities.ts
|
|
11
11
|
var CLAUDE_BRIDGE_CAPABILITY = "claude-bridge";
|
|
@@ -3,28 +3,28 @@ import {
|
|
|
3
3
|
addPusharyToolPermissions,
|
|
4
4
|
isPusharyHook,
|
|
5
5
|
removeClaudeMcpServers
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-5IBVIMWT.js";
|
|
7
7
|
import {
|
|
8
8
|
CLAUDE_HOOK_EVENTS,
|
|
9
9
|
addGeminiMcpServer,
|
|
10
10
|
removeGeminiMcpServer
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-A7XIL2WD.js";
|
|
12
12
|
import {
|
|
13
13
|
CLAUDE_CODE_AGENT,
|
|
14
14
|
parseApplyPatchFiles
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-IF46POXX.js";
|
|
16
16
|
import {
|
|
17
17
|
guardBinary,
|
|
18
18
|
holdBudgetOf,
|
|
19
19
|
registerHookEntry
|
|
20
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-UCGQEAKZ.js";
|
|
21
21
|
import {
|
|
22
22
|
PHONE_ANSWERED_TOOLS,
|
|
23
23
|
hookCompatibleProfile,
|
|
24
24
|
hookCompatibleProfileBySource,
|
|
25
25
|
toToolLookup,
|
|
26
26
|
withHookHoldBudget
|
|
27
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-7IEB2GV4.js";
|
|
28
28
|
|
|
29
29
|
// src/compatible-config.ts
|
|
30
30
|
import { homedir } from "os";
|
|
@@ -50,14 +50,14 @@ var namedSource = (argv) => {
|
|
|
50
50
|
const inline = argv.find((argument) => argument.startsWith(`${SOURCE_FLAG}=`));
|
|
51
51
|
if (inline) return inline.slice(SOURCE_FLAG.length + 1);
|
|
52
52
|
const index = argv.indexOf(SOURCE_FLAG);
|
|
53
|
-
return index === -1 ? void 0 : argv[index + 1];
|
|
53
|
+
return index === -1 ? void 0 : argv[index + 1] ?? "";
|
|
54
54
|
};
|
|
55
55
|
var activeHookSource = (argv) => {
|
|
56
56
|
const named = namedAgent(argv);
|
|
57
57
|
if (named !== void 0) return hookCompatibleProfile(named)?.source ?? null;
|
|
58
58
|
const source = namedSource(argv);
|
|
59
59
|
if (source === void 0) return "claude";
|
|
60
|
-
return hookCompatibleProfileBySource(source)?.source ??
|
|
60
|
+
return source === "claude" ? "claude" : hookCompatibleProfileBySource(source)?.source ?? null;
|
|
61
61
|
};
|
|
62
62
|
var PATCH_INPUT_KEYS = ["command", "patch", "input"];
|
|
63
63
|
var patchedFiles = (toolInput) => [...new Set(PATCH_INPUT_KEYS.flatMap((key) => parseApplyPatchFiles(toolInput[key])))];
|