@pushary/agent-hooks 0.32.2 → 0.33.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.
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  removeClaudeMcpServers,
4
4
  removePusharySettings
5
- } from "../chunk-M6YUEVRV.js";
5
+ } from "../chunk-AV2F2ZTZ.js";
6
6
  import {
7
7
  removeCodexHooks,
8
8
  removeGeminiSettings,
@@ -32,7 +32,7 @@ import {
32
32
  toCodexWire,
33
33
  toPolicyLookup,
34
34
  waitForAnswer
35
- } from "../chunk-P7B3U6DR.js";
35
+ } from "../chunk-OCPDWNG2.js";
36
36
  import {
37
37
  isGatingMoment,
38
38
  recordKeylessMoment
@@ -4,7 +4,7 @@ import {
4
4
  getMachineId,
5
5
  reportEvent,
6
6
  waitForAnswer
7
- } from "../chunk-P7B3U6DR.js";
7
+ } from "../chunk-OCPDWNG2.js";
8
8
  import "../chunk-DWED7BS3.js";
9
9
  import "../chunk-Z5PL3K7C.js";
10
10
  import {
@@ -24,7 +24,7 @@ import {
24
24
  savePendingQuestion,
25
25
  sendNotification,
26
26
  waitForAnswer
27
- } from "../chunk-P7B3U6DR.js";
27
+ } from "../chunk-OCPDWNG2.js";
28
28
  import {
29
29
  isGatingMoment,
30
30
  recordKeylessMoment
@@ -1,9 +1,9 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  handlePreToolUse
4
- } from "../chunk-2AMV2BDM.js";
4
+ } from "../chunk-UU3ETDK4.js";
5
5
  import "../chunk-KQYIHZ5E.js";
6
- import "../chunk-P7B3U6DR.js";
6
+ import "../chunk-OCPDWNG2.js";
7
7
  import "../chunk-R5AJNXZS.js";
8
8
  import "../chunk-DWED7BS3.js";
9
9
  import "../chunk-Z5PL3K7C.js";
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  handleNotification
4
- } from "../chunk-P7B3U6DR.js";
4
+ } from "../chunk-OCPDWNG2.js";
5
5
  import "../chunk-DWED7BS3.js";
6
6
  import "../chunk-Z5PL3K7C.js";
7
7
  import "../chunk-NKXSILEW.js";
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  handlePostToolUse
4
- } from "../chunk-P7B3U6DR.js";
4
+ } from "../chunk-OCPDWNG2.js";
5
5
  import "../chunk-DWED7BS3.js";
6
6
  import "../chunk-Z5PL3K7C.js";
7
7
  import "../chunk-NKXSILEW.js";
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  handleUserPrompt
4
- } from "../chunk-P7B3U6DR.js";
4
+ } from "../chunk-OCPDWNG2.js";
5
5
  import "../chunk-DWED7BS3.js";
6
6
  import "../chunk-Z5PL3K7C.js";
7
7
  import "../chunk-NKXSILEW.js";
@@ -0,0 +1 @@
1
+ #!/usr/bin/env node
@@ -0,0 +1,21 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ handleSessionStart
4
+ } from "../chunk-OCPDWNG2.js";
5
+ import "../chunk-DWED7BS3.js";
6
+ import "../chunk-Z5PL3K7C.js";
7
+ import "../chunk-NKXSILEW.js";
8
+
9
+ // bin/pushary-session-start-hook.ts
10
+ var main = async () => {
11
+ let rawInput = "";
12
+ for await (const chunk of process.stdin) {
13
+ rawInput += chunk;
14
+ }
15
+ try {
16
+ const input = rawInput.trim() ? JSON.parse(rawInput) : {};
17
+ await handleSessionStart(input);
18
+ } catch {
19
+ }
20
+ };
21
+ main();
@@ -3,7 +3,7 @@ import {
3
3
  addClaudeMcpServer,
4
4
  addPusharyHooks,
5
5
  addPusharyToolPermissions
6
- } from "../chunk-M6YUEVRV.js";
6
+ } from "../chunk-AV2F2ZTZ.js";
7
7
  import {
8
8
  GEMINI_HOOK_BINARY,
9
9
  addCodexHookTrust,
@@ -24,7 +24,7 @@ import {
24
24
  } from "../chunk-J7JWI3KU.js";
25
25
  import {
26
26
  reportEvent
27
- } from "../chunk-P7B3U6DR.js";
27
+ } from "../chunk-OCPDWNG2.js";
28
28
  import "../chunk-DWED7BS3.js";
29
29
  import {
30
30
  isValidApiKey
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  handleStop
4
- } from "../chunk-P7B3U6DR.js";
4
+ } from "../chunk-OCPDWNG2.js";
5
5
  import "../chunk-DWED7BS3.js";
6
6
  import "../chunk-Z5PL3K7C.js";
7
7
  import "../chunk-NKXSILEW.js";
@@ -20,7 +20,7 @@ var isPusharyHook = (entry) => {
20
20
  if (!Array.isArray(hooks)) return false;
21
21
  return hooks.some((hook) => {
22
22
  const command = String(asRecord(hook)?.command ?? "");
23
- return command.includes("pushary-hook") || command.includes("pushary-post-hook") || command.includes("pushary-stop-hook") || command.includes("pushary-prompt-hook") || command.includes("pushary-notification-hook");
23
+ return command.includes("pushary-hook") || command.includes("pushary-post-hook") || command.includes("pushary-stop-hook") || command.includes("pushary-prompt-hook") || command.includes("pushary-notification-hook") || command.includes("pushary-session-start-hook");
24
24
  });
25
25
  };
26
26
  var addClaudeMcpServer = (config, apiKey) => {
@@ -77,7 +77,7 @@ var addPusharyHooks = (settings, binDir) => {
77
77
  hooks.PreToolUse = preToolUse;
78
78
  const postToolUse = (Array.isArray(hooks.PostToolUse) ? hooks.PostToolUse : []).filter((entry) => !isPusharyHook(entry));
79
79
  postToolUse.push({
80
- matcher: "Bash|Write|Edit|NotebookEdit",
80
+ matcher: "Bash|Write|Edit|NotebookEdit|TodoWrite",
81
81
  hooks: [{
82
82
  type: "command",
83
83
  command: resolve("pushary-post-hook"),
@@ -113,6 +113,16 @@ var addPusharyHooks = (settings, binDir) => {
113
113
  }]
114
114
  });
115
115
  hooks.Notification = notification;
116
+ const sessionStart = (Array.isArray(hooks.SessionStart) ? hooks.SessionStart : []).filter((entry) => !isPusharyHook(entry));
117
+ sessionStart.push({
118
+ matcher: "startup|resume|clear",
119
+ hooks: [{
120
+ type: "command",
121
+ command: resolve("pushary-session-start-hook"),
122
+ timeout: 10
123
+ }]
124
+ });
125
+ hooks.SessionStart = sessionStart;
116
126
  };
117
127
  var removePusharySettings = (settings) => {
118
128
  let changed = removeClaudeMcpServers(settings);
@@ -131,7 +141,7 @@ var removePusharySettings = (settings) => {
131
141
  }
132
142
  const hooks = asRecord(settings.hooks);
133
143
  if (hooks) {
134
- for (const key of ["PreToolUse", "PostToolUse", "Stop", "UserPromptSubmit", "Notification"]) {
144
+ for (const key of ["PreToolUse", "PostToolUse", "Stop", "UserPromptSubmit", "Notification", "SessionStart"]) {
135
145
  const entries = hooks[key];
136
146
  if (!Array.isArray(entries)) continue;
137
147
  const filtered = entries.filter((entry) => !isPusharyHook(entry));
@@ -194,11 +194,24 @@ var hookPrefixes = {
194
194
  Edit: (input) => `edit file: ${input.file_path ?? "(unknown path)"}`,
195
195
  Read: (input) => `read file: ${input.file_path ?? "(unknown path)"}`
196
196
  };
197
+ var describeTodoProgress = (todos) => {
198
+ if (!Array.isArray(todos)) return "updated the plan";
199
+ const items = todos.filter((t) => !!t && typeof t === "object");
200
+ const total = items.length;
201
+ if (total === 0) return "updated the plan";
202
+ const done = items.filter((t) => t.status === "completed").length;
203
+ const current = items.find((t) => t.status === "in_progress");
204
+ const label = current ? [current.activeForm, current.content].find((v) => typeof v === "string" && v.trim().length > 0) : void 0;
205
+ if (done >= total) return `finished all ${total} tasks`;
206
+ if (label) return `${label.trim()} (${done}/${total} done)`;
207
+ return `${done}/${total} tasks done`;
208
+ };
197
209
  var eventPrefixes = {
198
210
  Bash: (input) => `ran: ${String(input.command ?? "")}`,
199
211
  Write: (input) => `wrote: ${input.file_path ?? "unknown"}`,
200
212
  Edit: (input) => `edited: ${input.file_path ?? "unknown"}`,
201
- Read: (input) => `read: ${input.file_path ?? "unknown"}`
213
+ Read: (input) => `read: ${input.file_path ?? "unknown"}`,
214
+ TodoWrite: (input) => describeTodoProgress(input.todos)
202
215
  };
203
216
  var EVENT_ACTION_MAX = 120;
204
217
  var HOOK_FALLBACK_MAX = 200;
@@ -919,6 +932,20 @@ var handleStop = async (input, agent = CLAUDE_CODE_AGENT) => {
919
932
  return void 0;
920
933
  }
921
934
  };
935
+ var handleSessionStart = async (input, agent = CLAUDE_CODE_AGENT) => {
936
+ try {
937
+ const projectName = basename(input.cwd ?? process.cwd());
938
+ const action = input.source === "resume" ? "Session resumed" : "Session started";
939
+ await reportEvent({
940
+ event: "session_start",
941
+ agentType: agent.type,
942
+ agentName: `${agent.label} - ${projectName}`,
943
+ action,
944
+ sessionId: input.session_id
945
+ }, { maxAttempts: 1, timeoutMs: 800 });
946
+ } catch {
947
+ }
948
+ };
922
949
  var NOTIFICATION_PUSH_TYPES = /* @__PURE__ */ new Set(["idle_prompt", "agent_needs_input"]);
923
950
  var NOTIFICATION_THROTTLE_MS = 60 * 1e3;
924
951
  var handleNotification = async (input, agent = CLAUDE_CODE_AGENT) => {
@@ -990,5 +1017,6 @@ export {
990
1017
  handlePostToolUse,
991
1018
  handleUserPrompt,
992
1019
  handleStop,
1020
+ handleSessionStart,
993
1021
  handleNotification
994
1022
  };
@@ -20,7 +20,7 @@ import {
20
20
  savePendingQuestion,
21
21
  sendNotification,
22
22
  waitForAnswer
23
- } from "./chunk-P7B3U6DR.js";
23
+ } from "./chunk-OCPDWNG2.js";
24
24
  import {
25
25
  isGatingMoment,
26
26
  recordKeylessMoment
package/dist/src/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  handlePreToolUse
3
- } from "../chunk-2AMV2BDM.js";
3
+ } from "../chunk-UU3ETDK4.js";
4
4
  import "../chunk-KQYIHZ5E.js";
5
5
  import {
6
6
  askUser,
@@ -14,7 +14,7 @@ import {
14
14
  reportEvent,
15
15
  resolvePolicy,
16
16
  waitForAnswer
17
- } from "../chunk-P7B3U6DR.js";
17
+ } from "../chunk-OCPDWNG2.js";
18
18
  import "../chunk-R5AJNXZS.js";
19
19
  import "../chunk-DWED7BS3.js";
20
20
  import "../chunk-Z5PL3K7C.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pushary/agent-hooks",
3
- "version": "0.32.2",
3
+ "version": "0.33.0",
4
4
  "description": "Permission hooks for AI coding agents: route tool approvals through Pushary push notifications",
5
5
  "keywords": [
6
6
  "pushary",
@@ -48,6 +48,7 @@
48
48
  "pushary-stop-hook": "./dist/bin/pushary-stop-hook.js",
49
49
  "pushary-prompt-hook": "./dist/bin/pushary-prompt-hook.js",
50
50
  "pushary-notification-hook": "./dist/bin/pushary-notification-hook.js",
51
+ "pushary-session-start-hook": "./dist/bin/pushary-session-start-hook.js",
51
52
  "pushary-claude": "./dist/bin/pushary-claude.js",
52
53
  "pushary-codex": "./dist/bin/pushary-codex.js",
53
54
  "pushary-codex-hook": "./dist/bin/pushary-codex-hook.js",