@pushary/agent-hooks 0.85.0 → 0.85.2
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 +29 -0
- package/data/cursor-plugin/CHANGELOG.md +21 -0
- package/data/cursor-plugin/scripts/pushary-gate.mjs +54 -222
- package/data/cursor-plugin/scripts/pushary-gate.test.mjs +11 -106
- package/data/vscode-plugin/CHANGELOG.md +26 -0
- package/data/vscode-plugin/scripts/pushary-gate.mjs +66 -74
- package/dist/bin/pushary-bell-hook.js +4 -4
- package/dist/bin/pushary-bell.js +6 -6
- package/dist/bin/pushary-claude.js +12 -11
- package/dist/bin/pushary-clean.js +6 -6
- package/dist/bin/pushary-codex-bridge.js +5 -5
- package/dist/bin/pushary-codex-hook.js +9 -9
- 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 +5 -5
- package/dist/bin/pushary-doctor.js +11 -11
- package/dist/bin/pushary-gemini-bridge.js +5 -5
- package/dist/bin/pushary-gemini-hook.js +17 -12
- package/dist/bin/pushary-hook.js +8 -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 +8 -8
- package/dist/bin/pushary-permission-hook.js +8 -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 +14 -14
- 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 +6 -6
- package/dist/bin/pushary-wait.js +3 -3
- package/dist/{chunk-ADISVXZL.js → chunk-4U2YRHNF.js} +1 -1
- package/dist/{chunk-WEAQQSHQ.js → chunk-4YMWLMAP.js} +1 -1
- package/dist/{chunk-437T77TY.js → chunk-CWV4CMB6.js} +1 -1
- package/dist/{chunk-EXMUM226.js → chunk-DPDUB4XF.js} +62 -156
- package/dist/{chunk-7PZPJSWI.js → chunk-GM74DUMS.js} +1 -1
- package/dist/{chunk-DOXSWT4Q.js → chunk-GY3I353G.js} +6 -6
- package/dist/chunk-HSGEEBBL.js +37 -0
- package/dist/{chunk-ERYKGH4J.js → chunk-JBLRZGTT.js} +1 -1
- package/dist/{chunk-4QPOMJUB.js → chunk-JT5NQQCE.js} +2 -2
- package/dist/{chunk-MQMPG5X4.js → chunk-K337LIBD.js} +260 -10
- package/dist/{chunk-HVZIHTOO.js → chunk-KJW6NKF7.js} +7 -7
- package/dist/{chunk-K7CSRGKZ.js → chunk-KZIGJLOX.js} +1 -1
- package/dist/{chunk-6LC4WSCL.js → chunk-LCA2EQTK.js} +1 -1
- package/dist/{chunk-F52SIIDG.js → chunk-LSB6PFLN.js} +1 -1
- package/dist/{chunk-YKW6JCWI.js → chunk-LXWISFF3.js} +1 -1
- package/dist/{chunk-FBGBJXVC.js → chunk-NTIUQB3E.js} +1 -1
- package/dist/{chunk-NJ7JT26G.js → chunk-PKUNB3SN.js} +1 -1
- package/dist/{chunk-AXRATIS6.js → chunk-Q4URN3E7.js} +1 -1
- package/dist/{chunk-GCKAWHFP.js → chunk-T54OT7IY.js} +1 -1
- package/dist/{chunk-64PXDATC.js → chunk-XJDL3MUE.js} +17 -17
- package/dist/{chunk-GFM3STWO.js → chunk-Y7E2MC3G.js} +20 -49
- package/dist/chunk-YHG74UFF.js +12 -0
- package/dist/src/index.d.ts +7 -29
- package/dist/src/index.js +10 -9
- package/package.json +4 -2
- package/dist/chunk-GXIFADGD.js +0 -66
- package/dist/chunk-PWTKKQQI.js +0 -27
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
} from "./chunk-SAF6HGAA.js";
|
|
11
11
|
import {
|
|
12
12
|
reportedInstallSource
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-CWV4CMB6.js";
|
|
14
14
|
import {
|
|
15
15
|
getApiKey,
|
|
16
16
|
getBaseUrl
|
|
@@ -18,19 +18,16 @@ import {
|
|
|
18
18
|
import {
|
|
19
19
|
ACTION_BODY_MAX,
|
|
20
20
|
DECISION_LINE_MAX,
|
|
21
|
-
|
|
22
|
-
isApprovalMode,
|
|
21
|
+
gateOutputFor,
|
|
23
22
|
isAutoApprove,
|
|
24
|
-
isAutoDeny,
|
|
25
|
-
isSafeReadOnlyCommand,
|
|
26
|
-
isScopeContract,
|
|
27
23
|
localRepoKey,
|
|
24
|
+
modeStateFromResponse,
|
|
28
25
|
normalizeRepoRemote,
|
|
29
|
-
policyArgForms,
|
|
30
26
|
redactSecrets,
|
|
31
27
|
redactSecretsDeep,
|
|
32
|
-
|
|
33
|
-
|
|
28
|
+
resolveAutoResolveOrigin,
|
|
29
|
+
resolvePolicy
|
|
30
|
+
} from "./chunk-K337LIBD.js";
|
|
34
31
|
|
|
35
32
|
// src/policy.ts
|
|
36
33
|
import { createHash } from "crypto";
|
|
@@ -120,66 +117,6 @@ var getPolicy = async (apiKey, expectedVersion, agent, repoAware = false, sessio
|
|
|
120
117
|
throw new Error("Failed to fetch policy and no cached policy available");
|
|
121
118
|
}
|
|
122
119
|
};
|
|
123
|
-
var autoApprove = (tool) => ({
|
|
124
|
-
tool,
|
|
125
|
-
timeoutSeconds: 0,
|
|
126
|
-
timeoutAction: "approve",
|
|
127
|
-
mode: "terminal_only",
|
|
128
|
-
pushFirstSeconds: 0
|
|
129
|
-
});
|
|
130
|
-
var resolveAutoResolveOrigin = (config, toolName, toolInput, cwd, repoKey, sessionId) => {
|
|
131
|
-
const args = toolInput ? policyArgForms(toolName, toolInput, cwd) : [];
|
|
132
|
-
const arg = args[0];
|
|
133
|
-
const match = selectGoverningRule(config.policies, toolName, args, repoKey, sessionId);
|
|
134
|
-
const governedBySpecificRule = match?.rank === "exact" || match?.rank === "prefix";
|
|
135
|
-
if (!governedBySpecificRule && toolName === "Bash" && typeof arg === "string" && isSafeReadOnlyCommand(arg)) {
|
|
136
|
-
return "safe_readonly";
|
|
137
|
-
}
|
|
138
|
-
return "policy_timeout";
|
|
139
|
-
};
|
|
140
|
-
var resolvePolicy = (config, toolName, modeOverride, toolInput, cwd, repoKey, sessionId) => {
|
|
141
|
-
const args = toolInput ? policyArgForms(toolName, toolInput, cwd) : [];
|
|
142
|
-
const arg = args[0];
|
|
143
|
-
const match = selectGoverningRule(config.policies, toolName, args, repoKey, sessionId);
|
|
144
|
-
let base = match?.policy ?? config.policies.find((p) => p.tool === "*") ?? {
|
|
145
|
-
tool: toolName,
|
|
146
|
-
timeoutSeconds: config.defaultTimeoutSeconds,
|
|
147
|
-
timeoutAction: config.defaultTimeoutAction,
|
|
148
|
-
mode: config.defaultMode ?? "push_first",
|
|
149
|
-
pushFirstSeconds: config.defaultPushFirstSeconds ?? 20
|
|
150
|
-
};
|
|
151
|
-
const governedBySpecificRule = match?.rank === "exact" || match?.rank === "prefix";
|
|
152
|
-
if (!governedBySpecificRule && toolName === "Bash" && typeof arg === "string" && isSafeReadOnlyCommand(arg)) {
|
|
153
|
-
base = autoApprove(base.tool);
|
|
154
|
-
}
|
|
155
|
-
const wouldAutoApprove = isAutoApprove(base);
|
|
156
|
-
if (!governedBySpecificRule && wouldAutoApprove && toolName === "Bash" && typeof arg === "string" && classifyDecisionRisk(toolName, arg) === "destructive") {
|
|
157
|
-
base = {
|
|
158
|
-
tool: base.tool,
|
|
159
|
-
timeoutSeconds: config.defaultTimeoutSeconds,
|
|
160
|
-
timeoutAction: "wait",
|
|
161
|
-
mode: "push_first",
|
|
162
|
-
pushFirstSeconds: config.defaultPushFirstSeconds ?? 20
|
|
163
|
-
};
|
|
164
|
-
}
|
|
165
|
-
const effectiveOverride = modeOverride ?? config.modeOverride;
|
|
166
|
-
if (effectiveOverride) {
|
|
167
|
-
return { ...base, mode: effectiveOverride };
|
|
168
|
-
}
|
|
169
|
-
return base;
|
|
170
|
-
};
|
|
171
|
-
var restraintRank = (policy) => {
|
|
172
|
-
if (isAutoDeny(policy)) return 4;
|
|
173
|
-
if (isAutoApprove(policy)) return 0;
|
|
174
|
-
if (policy.mode === "push_only") return 3;
|
|
175
|
-
return policy.mode === "terminal_only" || policy.mode === "notify_only" ? 1 : 2;
|
|
176
|
-
};
|
|
177
|
-
var strictestPolicy = (a, b) => restraintRank(b) > restraintRank(a) ? b : a;
|
|
178
|
-
var resolvePolicyAcross = (config, toolName, modeOverride, toolInputs, cwd, repoKey, sessionId) => {
|
|
179
|
-
if (toolInputs.length === 0) return resolvePolicy(config, toolName, modeOverride, void 0, cwd, repoKey, sessionId);
|
|
180
|
-
return toolInputs.map((input) => resolvePolicy(config, toolName, modeOverride, input, cwd, repoKey, sessionId)).reduce(strictestPolicy);
|
|
181
|
-
};
|
|
182
|
-
var isModeStateDegraded = (state) => state?.degraded === true;
|
|
183
120
|
var MODE_GRACE_MS = 60 * 1e3;
|
|
184
121
|
var modeStateCacheFile = (apiKey) => {
|
|
185
122
|
const hash = createHash("sha256").update(`mode:${apiKey}`).digest("hex").slice(0, 12);
|
|
@@ -220,7 +157,6 @@ var degradedFallback = (apiKey, authoritative = false) => {
|
|
|
220
157
|
}
|
|
221
158
|
return unknownMode();
|
|
222
159
|
};
|
|
223
|
-
var toPolicyVersion = (value) => typeof value === "string" || typeof value === "number" ? String(value) : null;
|
|
224
160
|
var MODE_REUSE_MS = CACHE_TTL_MS;
|
|
225
161
|
var readReusableMode = (apiKey, sessionId, maxAgeMs) => {
|
|
226
162
|
const last = readLastGoodMode(apiKey);
|
|
@@ -243,19 +179,7 @@ var fetchModeState = async (apiKey, sessionId, reuseWithinMs = 0) => {
|
|
|
243
179
|
if (!response.ok) {
|
|
244
180
|
return degradedFallback(apiKey, response.status === 401 || response.status === 403);
|
|
245
181
|
}
|
|
246
|
-
const
|
|
247
|
-
const mode = data.override?.mode;
|
|
248
|
-
const state = {
|
|
249
|
-
mode: isApprovalMode(mode) ? mode : null,
|
|
250
|
-
kill: data.kill === true,
|
|
251
|
-
policyVersion: toPolicyVersion(data.policyVersion),
|
|
252
|
-
relayUrl: typeof data.relayUrl === "string" && data.relayUrl.length > 0 ? data.relayUrl : null,
|
|
253
|
-
trainingConsent: data.trainingConsent === true,
|
|
254
|
-
// Validated rather than cast: a malformed contract must read as no contract,
|
|
255
|
-
// never as one that silently matches nothing.
|
|
256
|
-
scope: isScopeContract(data.scope) ? data.scope : null,
|
|
257
|
-
degraded: false
|
|
258
|
-
};
|
|
182
|
+
const state = modeStateFromResponse(await response.json());
|
|
259
183
|
writeLastGoodMode(apiKey, state, sessionId);
|
|
260
184
|
return state;
|
|
261
185
|
} catch {
|
|
@@ -265,9 +189,11 @@ var fetchModeState = async (apiKey, sessionId, reuseWithinMs = 0) => {
|
|
|
265
189
|
var fetchModeOverride = async (apiKey) => (await fetchModeState(apiKey)).mode;
|
|
266
190
|
|
|
267
191
|
// src/api.ts
|
|
192
|
+
import { randomUUID } from "crypto";
|
|
268
193
|
installProxyDispatcher();
|
|
269
194
|
var askUser = async (apiKey, params, timeoutMs = 15e3) => {
|
|
270
|
-
const
|
|
195
|
+
const identified = params.toolUseId || params.requestId ? params : { ...params, requestId: randomUUID() };
|
|
196
|
+
const result = await callMcpTool(apiKey, "ask_user", { ...identified, wait: false }, { maxRetries: 3, timeoutMs });
|
|
271
197
|
if (!isAskUserResponse(result)) throw new Error("Invalid ask_user response");
|
|
272
198
|
return result;
|
|
273
199
|
};
|
|
@@ -286,7 +212,7 @@ var sendNotification = async (apiKey, params, timeoutMs = 15e3) => {
|
|
|
286
212
|
await callMcpTool(apiKey, "send_notification", { ...params }, { maxRetries: 3, timeoutMs });
|
|
287
213
|
};
|
|
288
214
|
|
|
289
|
-
// src/describe.ts
|
|
215
|
+
// ../hook-mapping/src/describe.ts
|
|
290
216
|
import { isAbsolute, relative } from "path";
|
|
291
217
|
var hookPrefixes = {
|
|
292
218
|
Bash: (input) => `bash: ${input.command ?? "(no command)"}`,
|
|
@@ -455,6 +381,36 @@ var deriveBlocker = (mode, reason) => {
|
|
|
455
381
|
return text.slice(0, DECISION_LINE_MAX);
|
|
456
382
|
};
|
|
457
383
|
|
|
384
|
+
// ../hook-mapping/src/map.ts
|
|
385
|
+
import { basename } from "path";
|
|
386
|
+
var TASK_TITLE_MAX_LENGTH = 120;
|
|
387
|
+
var STOP_SUMMARY_MAX_LENGTH = 200;
|
|
388
|
+
var SESSION_END_ACTIONS = {
|
|
389
|
+
clear: "Session cleared",
|
|
390
|
+
logout: "Logged out",
|
|
391
|
+
resume: "Session suspended",
|
|
392
|
+
prompt_input_exit: "Session ended",
|
|
393
|
+
bypass_permissions_disabled: "Session ended",
|
|
394
|
+
other: "Session ended"
|
|
395
|
+
};
|
|
396
|
+
var countArray = (value) => Array.isArray(value) ? value.length : 0;
|
|
397
|
+
var summarizeFinalMessage = (message) => {
|
|
398
|
+
if (typeof message !== "string") return "Session ended";
|
|
399
|
+
const collapsed = message.replace(/\s+/g, " ").trim();
|
|
400
|
+
if (!collapsed) return "Session ended";
|
|
401
|
+
return collapsed.slice(0, STOP_SUMMARY_MAX_LENGTH);
|
|
402
|
+
};
|
|
403
|
+
var summarizeStop = (input) => {
|
|
404
|
+
const running = countArray(input.background_tasks);
|
|
405
|
+
if (running > 0) return `Paused with ${running} background task${running === 1 ? "" : "s"} still running`;
|
|
406
|
+
const crons = countArray(input.session_crons);
|
|
407
|
+
if (crons > 0) return `Idle until a scheduled task wakes it (${crons} pending)`;
|
|
408
|
+
return summarizeFinalMessage(input.last_assistant_message);
|
|
409
|
+
};
|
|
410
|
+
var sessionStartAction = (source) => source === "resume" ? "Session resumed" : "Session started";
|
|
411
|
+
var sessionEndAction = (reason) => typeof reason === "string" && SESSION_END_ACTIONS[reason] || "Session ended";
|
|
412
|
+
var taskTitleFrom = (prompt) => typeof prompt === "string" ? prompt.replace(/\s+/g, " ").trim().slice(0, TASK_TITLE_MAX_LENGTH) || void 0 : void 0;
|
|
413
|
+
|
|
458
414
|
// src/pending.ts
|
|
459
415
|
import { join as join2 } from "path";
|
|
460
416
|
import { tmpdir as tmpdir2 } from "os";
|
|
@@ -503,7 +459,7 @@ var removePendingSession = (sessionId) => {
|
|
|
503
459
|
|
|
504
460
|
// src/repo.ts
|
|
505
461
|
import { existsSync as existsSync3, readFileSync as readFileSync2, statSync as statSync2 } from "fs";
|
|
506
|
-
import { basename, dirname, isAbsolute as isAbsolute2, join as join3, resolve } from "path";
|
|
462
|
+
import { basename as basename2, dirname, isAbsolute as isAbsolute2, join as join3, resolve } from "path";
|
|
507
463
|
var MAX_PARENT_WALK = 64;
|
|
508
464
|
var GIT_FILE_PREFIX = "gitdir:";
|
|
509
465
|
var findGitDir = (startDir) => {
|
|
@@ -562,9 +518,9 @@ var deriveRepoKey = (cwd) => {
|
|
|
562
518
|
const normalized = remote ? normalizeRepoRemote(remote) : void 0;
|
|
563
519
|
if (normalized) return normalized;
|
|
564
520
|
const root = gitDir.endsWith(".git") ? dirname(gitDir) : dir;
|
|
565
|
-
return localRepoKey(
|
|
521
|
+
return localRepoKey(basename2(root));
|
|
566
522
|
}
|
|
567
|
-
return localRepoKey(
|
|
523
|
+
return localRepoKey(basename2(resolve(dir)));
|
|
568
524
|
} catch {
|
|
569
525
|
return void 0;
|
|
570
526
|
}
|
|
@@ -763,35 +719,13 @@ var codexAllow = () => ({ kind: "allow" });
|
|
|
763
719
|
var codexDeny = (reason) => ({ kind: "deny", reason });
|
|
764
720
|
var codexPass = () => ({ kind: "pass" });
|
|
765
721
|
var toCodexWire = (event, decision) => {
|
|
766
|
-
if (
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
};
|
|
774
|
-
}
|
|
775
|
-
if (decision.kind === "deny") {
|
|
776
|
-
return {
|
|
777
|
-
hookSpecificOutput: {
|
|
778
|
-
hookEventName: "PermissionRequest",
|
|
779
|
-
decision: { behavior: "deny", message: decision.reason }
|
|
780
|
-
}
|
|
781
|
-
};
|
|
782
|
-
}
|
|
783
|
-
return null;
|
|
784
|
-
}
|
|
785
|
-
if (event === "PreToolUse" && decision.kind === "deny") {
|
|
786
|
-
return {
|
|
787
|
-
hookSpecificOutput: {
|
|
788
|
-
hookEventName: "PreToolUse",
|
|
789
|
-
permissionDecision: "deny",
|
|
790
|
-
permissionDecisionReason: decision.reason
|
|
791
|
-
}
|
|
792
|
-
};
|
|
793
|
-
}
|
|
794
|
-
return null;
|
|
722
|
+
if (decision.kind === "pass") return null;
|
|
723
|
+
return gateOutputFor(
|
|
724
|
+
"codex",
|
|
725
|
+
event,
|
|
726
|
+
decision.kind,
|
|
727
|
+
decision.kind === "deny" ? decision.reason : void 0
|
|
728
|
+
) ?? null;
|
|
795
729
|
};
|
|
796
730
|
var parseApplyPatchOps = (command) => {
|
|
797
731
|
if (typeof command !== "string") return [];
|
|
@@ -869,7 +803,7 @@ var throttlePass = (key, windowMs) => {
|
|
|
869
803
|
};
|
|
870
804
|
|
|
871
805
|
// src/events.ts
|
|
872
|
-
import { basename as
|
|
806
|
+
import { basename as basename3, join as join6 } from "path";
|
|
873
807
|
import { existsSync as existsSync5, mkdirSync as mkdirSync4, readFileSync as readFileSync4, statSync as statSync5, writeFileSync as writeFileSync5 } from "fs";
|
|
874
808
|
import { tmpdir as tmpdir5 } from "os";
|
|
875
809
|
var INTENT_DIR = join6(tmpdir5(), "pushary-intent");
|
|
@@ -1058,7 +992,7 @@ var reportEvent = async (event, options = {}) => {
|
|
|
1058
992
|
var NON_GATED_MIRROR_TOOLS = /* @__PURE__ */ new Set(["TodoWrite"]);
|
|
1059
993
|
var handlePostToolUse = async (input, agent = CLAUDE_CODE_AGENT) => {
|
|
1060
994
|
try {
|
|
1061
|
-
const projectName =
|
|
995
|
+
const projectName = basename3(input.cwd ?? process.cwd());
|
|
1062
996
|
const action = describeToolCall(input.tool_name, input.tool_input, "event");
|
|
1063
997
|
const lookup = toPolicyLookup(input.tool_name, input.tool_input);
|
|
1064
998
|
const toolResult = input.tool_response ?? input.tool_result;
|
|
@@ -1110,13 +1044,12 @@ var handlePostToolUse = async (input, agent = CLAUDE_CODE_AGENT) => {
|
|
|
1110
1044
|
return void 0;
|
|
1111
1045
|
}
|
|
1112
1046
|
};
|
|
1113
|
-
var TASK_TITLE_MAX_LENGTH = 120;
|
|
1114
1047
|
var handleUserPrompt = async (input, agent = CLAUDE_CODE_AGENT) => {
|
|
1115
1048
|
try {
|
|
1116
|
-
const projectName =
|
|
1049
|
+
const projectName = basename3(input.cwd ?? process.cwd());
|
|
1117
1050
|
const sessionKey = input.session_id || DEFAULT_SESSION;
|
|
1118
1051
|
const titlesEnabled = process.env.PUSHARY_TASK_TITLES !== "off";
|
|
1119
|
-
const taskTitle = titlesEnabled ? input.prompt
|
|
1052
|
+
const taskTitle = titlesEnabled ? taskTitleFrom(input.prompt) : void 0;
|
|
1120
1053
|
if (input.prompt) saveLastPrompt(sessionKey, input.prompt);
|
|
1121
1054
|
const late = await reconcilePendingQuestions(sessionKey);
|
|
1122
1055
|
let additionalContext;
|
|
@@ -1141,24 +1074,9 @@ var handleUserPrompt = async (input, agent = CLAUDE_CODE_AGENT) => {
|
|
|
1141
1074
|
return void 0;
|
|
1142
1075
|
}
|
|
1143
1076
|
};
|
|
1144
|
-
var STOP_SUMMARY_MAX_LENGTH = 200;
|
|
1145
|
-
var summarizeFinalMessage = (message) => {
|
|
1146
|
-
if (typeof message !== "string") return "Session ended";
|
|
1147
|
-
const collapsed = message.replace(/\s+/g, " ").trim();
|
|
1148
|
-
if (!collapsed) return "Session ended";
|
|
1149
|
-
return collapsed.slice(0, STOP_SUMMARY_MAX_LENGTH);
|
|
1150
|
-
};
|
|
1151
|
-
var countArray = (value) => Array.isArray(value) ? value.length : 0;
|
|
1152
|
-
var summarizeStop = (input) => {
|
|
1153
|
-
const running = countArray(input.background_tasks);
|
|
1154
|
-
if (running > 0) return `Paused with ${running} background task${running === 1 ? "" : "s"} still running`;
|
|
1155
|
-
const crons = countArray(input.session_crons);
|
|
1156
|
-
if (crons > 0) return `Idle until a scheduled task wakes it (${crons} pending)`;
|
|
1157
|
-
return summarizeFinalMessage(input.last_assistant_message);
|
|
1158
|
-
};
|
|
1159
1077
|
var handleStop = async (input, agent = CLAUDE_CODE_AGENT) => {
|
|
1160
1078
|
try {
|
|
1161
|
-
const projectName =
|
|
1079
|
+
const projectName = basename3(input.cwd ?? process.cwd());
|
|
1162
1080
|
const sessionKey = input.session_id || DEFAULT_SESSION;
|
|
1163
1081
|
const late = await reconcilePendingQuestions(sessionKey);
|
|
1164
1082
|
const tasks = [
|
|
@@ -1194,8 +1112,8 @@ var handleStop = async (input, agent = CLAUDE_CODE_AGENT) => {
|
|
|
1194
1112
|
};
|
|
1195
1113
|
var handleSessionStart = async (input, agent = CLAUDE_CODE_AGENT) => {
|
|
1196
1114
|
try {
|
|
1197
|
-
const projectName =
|
|
1198
|
-
const action = input.source
|
|
1115
|
+
const projectName = basename3(input.cwd ?? process.cwd());
|
|
1116
|
+
const action = sessionStartAction(input.source);
|
|
1199
1117
|
await reportEvent({
|
|
1200
1118
|
event: "session_start",
|
|
1201
1119
|
agentType: agent.type,
|
|
@@ -1206,18 +1124,10 @@ var handleSessionStart = async (input, agent = CLAUDE_CODE_AGENT) => {
|
|
|
1206
1124
|
} catch {
|
|
1207
1125
|
}
|
|
1208
1126
|
};
|
|
1209
|
-
var SESSION_END_ACTIONS = {
|
|
1210
|
-
clear: "Session cleared",
|
|
1211
|
-
logout: "Logged out",
|
|
1212
|
-
resume: "Session suspended",
|
|
1213
|
-
prompt_input_exit: "Session ended",
|
|
1214
|
-
bypass_permissions_disabled: "Session ended",
|
|
1215
|
-
other: "Session ended"
|
|
1216
|
-
};
|
|
1217
1127
|
var handleSessionEnd = async (input, agent = CLAUDE_CODE_AGENT) => {
|
|
1218
1128
|
try {
|
|
1219
|
-
const projectName =
|
|
1220
|
-
const action =
|
|
1129
|
+
const projectName = basename3(input.cwd ?? process.cwd());
|
|
1130
|
+
const action = sessionEndAction(input.reason);
|
|
1221
1131
|
const sessionKey = input.session_id || DEFAULT_SESSION;
|
|
1222
1132
|
const late = await reconcilePendingQuestions(sessionKey);
|
|
1223
1133
|
if (late.length > 0) {
|
|
@@ -1240,7 +1150,7 @@ var NOTIFICATION_PUSH_TYPES = /* @__PURE__ */ new Set(["idle_prompt", "agent_nee
|
|
|
1240
1150
|
var NOTIFICATION_THROTTLE_MS = 60 * 1e3;
|
|
1241
1151
|
var handleNotification = async (input, agent = CLAUDE_CODE_AGENT) => {
|
|
1242
1152
|
try {
|
|
1243
|
-
const projectName =
|
|
1153
|
+
const projectName = basename3(input.cwd ?? process.cwd());
|
|
1244
1154
|
const notifType = input.notification_type ?? input.type ?? "";
|
|
1245
1155
|
const sessionKey = input.session_id || DEFAULT_SESSION;
|
|
1246
1156
|
if (NOTIFICATION_PUSH_TYPES.has(notifType)) {
|
|
@@ -1313,7 +1223,7 @@ var handleStopFailure = async (input, agent = CLAUDE_CODE_AGENT) => {
|
|
|
1313
1223
|
} catch {
|
|
1314
1224
|
return;
|
|
1315
1225
|
}
|
|
1316
|
-
const projectName =
|
|
1226
|
+
const projectName = basename3(input.cwd ?? process.cwd());
|
|
1317
1227
|
const mode = await fetchModeState(apiKey, input.session_id, MODE_REUSE_MS).catch(() => null);
|
|
1318
1228
|
if (mode?.kill || mode?.mode === "terminal_only") return;
|
|
1319
1229
|
const reason = describeStopFailure(input.error);
|
|
@@ -1332,10 +1242,6 @@ var handleStopFailure = async (input, agent = CLAUDE_CODE_AGENT) => {
|
|
|
1332
1242
|
export {
|
|
1333
1243
|
policyRequestFor,
|
|
1334
1244
|
getPolicy,
|
|
1335
|
-
resolveAutoResolveOrigin,
|
|
1336
|
-
resolvePolicy,
|
|
1337
|
-
resolvePolicyAcross,
|
|
1338
|
-
isModeStateDegraded,
|
|
1339
1245
|
fetchModeState,
|
|
1340
1246
|
fetchModeOverride,
|
|
1341
1247
|
askUser,
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import {
|
|
2
2
|
HOOK_BUDGETS
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-K337LIBD.js";
|
|
4
4
|
|
|
5
5
|
// src/gemini-config.ts
|
|
6
6
|
var GEMINI_HOOK_BINARY = "pushary-gemini-hook";
|
|
7
7
|
var GEMINI_MCP_URL = "https://pushary.com/api/mcp/mcp";
|
|
8
8
|
var GEMINI_HOOK_EVENTS = [
|
|
9
|
-
{ event: "BeforeTool", matcher: "run_shell_command|write_file|replace", timeoutMs: HOOK_BUDGETS.gemini.budgetSeconds * 1e3 },
|
|
10
|
-
{ event: "AfterTool", matcher: "run_shell_command|write_file|replace", timeoutMs: 1e4 },
|
|
11
|
-
{ event: "BeforeAgent", timeoutMs: 1e4 },
|
|
12
|
-
{ event: "SessionStart", timeoutMs: 1e4 },
|
|
13
|
-
{ event: "SessionEnd", timeoutMs: 1e4 }
|
|
9
|
+
{ event: "BeforeTool", matcher: "run_shell_command|write_file|replace", delivery: "approval", timeoutMs: HOOK_BUDGETS.gemini.budgetSeconds * 1e3 },
|
|
10
|
+
{ event: "AfterTool", matcher: "run_shell_command|write_file|replace", delivery: "telemetry", timeoutMs: 1e4 },
|
|
11
|
+
{ event: "BeforeAgent", delivery: "telemetry", timeoutMs: 1e4 },
|
|
12
|
+
{ event: "SessionStart", delivery: "telemetry", timeoutMs: 1e4 },
|
|
13
|
+
{ event: "SessionEnd", delivery: "telemetry", timeoutMs: 1e4 }
|
|
14
14
|
];
|
|
15
15
|
var asRecord = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
16
16
|
var ensureRecord = (target, key) => {
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import {
|
|
2
|
+
quoteIfNeeded
|
|
3
|
+
} from "./chunk-VT4IVERX.js";
|
|
4
|
+
|
|
5
|
+
// src/hook-command.ts
|
|
6
|
+
var HOOK_SHELL = "/bin/sh -c";
|
|
7
|
+
var LOCATE = 'B=$(command -v "$0") || exit 0; [ -f "$B" ] || exit 0; [ -x "$B" ] || exit 0';
|
|
8
|
+
var NODE_PRESENT = "command -v node >/dev/null 2>&1 || exit 0";
|
|
9
|
+
var HOOK_GUARD_SCRIPTS = {
|
|
10
|
+
native_binary: `${LOCATE}; exec "$B"`,
|
|
11
|
+
node_binary: `${LOCATE}; ${NODE_PRESENT}; exec "$B"`,
|
|
12
|
+
node_script: `[ -f "$0" ] || exit 0; ${NODE_PRESENT}; exec node "$0"`
|
|
13
|
+
};
|
|
14
|
+
var BINARY_GUARDS = {
|
|
15
|
+
native: "native_binary",
|
|
16
|
+
node: "node_binary"
|
|
17
|
+
};
|
|
18
|
+
var guardKindOf = (target) => {
|
|
19
|
+
switch (target.kind) {
|
|
20
|
+
case "node":
|
|
21
|
+
return "node_script";
|
|
22
|
+
case "binary":
|
|
23
|
+
return BINARY_GUARDS[target.runtime];
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
var guardHookCommand = (target, platform = process.platform) => {
|
|
27
|
+
const path = quoteIfNeeded(target.kind === "node" ? target.script : target.path);
|
|
28
|
+
if (platform === "win32") return target.kind === "node" ? `node ${path}` : path;
|
|
29
|
+
return `${HOOK_SHELL} '${HOOK_GUARD_SCRIPTS[guardKindOf(target)]}' ${path}`;
|
|
30
|
+
};
|
|
31
|
+
var guardBinary = (path, platform) => guardHookCommand({ kind: "binary", path, runtime: "node" }, platform);
|
|
32
|
+
var guardNodeScript = (script, platform) => guardHookCommand({ kind: "node", script }, platform);
|
|
33
|
+
|
|
34
|
+
export {
|
|
35
|
+
guardBinary,
|
|
36
|
+
guardNodeScript
|
|
37
|
+
};
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
hasGeminiHooks
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-GY3I353G.js";
|
|
4
4
|
import {
|
|
5
5
|
hasCodexHooks
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-KJW6NKF7.js";
|
|
7
7
|
|
|
8
8
|
// src/diagnostics/wiring.ts
|
|
9
9
|
var record = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : null;
|