@pushary/agent-hooks 1.9.83 → 1.9.85

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.
Files changed (127) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/dist/{api-EKLKVJQG.js → api-4WEMR2G3.js} +10 -10
  3. package/dist/bin/pushary-bell-hook.js +26 -26
  4. package/dist/bin/pushary-bell.js +10 -10
  5. package/dist/bin/pushary-claude.js +32 -31
  6. package/dist/bin/pushary-clean.js +35 -33
  7. package/dist/bin/pushary-codex-bridge.js +21 -21
  8. package/dist/bin/pushary-codex-hook.js +44 -43
  9. package/dist/bin/pushary-codex-session.js +8 -8
  10. package/dist/bin/pushary-codex.js +14 -13
  11. package/dist/bin/pushary-connect.js +27 -26
  12. package/dist/bin/pushary-cowork.js +5 -5
  13. package/dist/bin/pushary-daemon.js +70 -43
  14. package/dist/bin/pushary-disconnect.js +26 -25
  15. package/dist/bin/pushary-display-hook.js +17 -17
  16. package/dist/bin/pushary-doctor.js +42 -41
  17. package/dist/bin/pushary-elicitation-hook.js +26 -26
  18. package/dist/bin/pushary-gemini-bridge.js +15 -15
  19. package/dist/bin/pushary-gemini-hook.js +35 -34
  20. package/dist/bin/pushary-hook.js +30 -30
  21. package/dist/bin/pushary-login.js +20 -20
  22. package/dist/bin/pushary-logout.js +25 -24
  23. package/dist/bin/pushary-mcp.js +11 -11
  24. package/dist/bin/pushary-mode.js +15 -15
  25. package/dist/bin/pushary-notification-hook.js +25 -25
  26. package/dist/bin/pushary-opencode-hook.js +35 -34
  27. package/dist/bin/pushary-permission-denied-hook.js +30 -30
  28. package/dist/bin/pushary-permission-hook.js +30 -30
  29. package/dist/bin/pushary-post-hook.js +25 -25
  30. package/dist/bin/pushary-prompt-hook.js +25 -25
  31. package/dist/bin/pushary-session-end-hook.js +27 -27
  32. package/dist/bin/pushary-session-start-hook.js +35 -35
  33. package/dist/bin/pushary-setup.js +48 -47
  34. package/dist/bin/pushary-stats.js +5 -5
  35. package/dist/bin/pushary-status.js +32 -31
  36. package/dist/bin/pushary-stop-hook.js +25 -25
  37. package/dist/bin/pushary-stopfailure-hook.js +25 -25
  38. package/dist/bin/pushary-suggestions.js +15 -15
  39. package/dist/bin/pushary-transcript-register.js +21 -20
  40. package/dist/bin/pushary-transcripts.js +30 -20
  41. package/dist/bin/pushary-upgrade.js +40 -39
  42. package/dist/bin/pushary-wait.js +15 -15
  43. package/dist/bin/pushary.js +7 -7
  44. package/dist/{chunk-BLM6O2QL.js → chunk-254B34JU.js} +1 -1
  45. package/dist/{chunk-XYEGVQST.js → chunk-2VZY5XQ5.js} +7 -7
  46. package/dist/chunk-3MWQZKIO.js +843 -0
  47. package/dist/{chunk-46P53RBT.js → chunk-42DNYOC4.js} +23 -21
  48. package/dist/{chunk-7YYJASRF.js → chunk-4J3NGYHG.js} +2 -2
  49. package/dist/{chunk-ZGZ2L3QN.js → chunk-4OP5GWHQ.js} +5 -5
  50. package/dist/{chunk-5UPZR3C3.js → chunk-4QGV3II7.js} +4 -4
  51. package/dist/{chunk-MHUKYYYR.js → chunk-4TMKTLQX.js} +44 -1
  52. package/dist/{chunk-2B7YU4EK.js → chunk-5Z43EFX2.js} +2 -2
  53. package/dist/{chunk-YIAJOV2X.js → chunk-64XK7DLE.js} +3 -3
  54. package/dist/{chunk-VRHVOMH2.js → chunk-6HBWJXU6.js} +3 -3
  55. package/dist/{chunk-IUZCERPQ.js → chunk-7GYDMVHV.js} +2 -2
  56. package/dist/{chunk-BG4YJEFE.js → chunk-7ZYVX2KN.js} +1 -1
  57. package/dist/{chunk-KR3KVDXD.js → chunk-BGMYSRMY.js} +1 -1
  58. package/dist/{chunk-OUYFUUWB.js → chunk-BS5MTP34.js} +2 -2
  59. package/dist/{chunk-VCMDY6YL.js → chunk-BUS7MXEE.js} +3 -3
  60. package/dist/{chunk-EMT7I74E.js → chunk-CIICMXVH.js} +3 -3
  61. package/dist/{chunk-4P256ZAU.js → chunk-CSOVOAX5.js} +6 -6
  62. package/dist/{chunk-VBY2AHSX.js → chunk-CZ7C5AJT.js} +1 -1
  63. package/dist/{chunk-HCLP2QBX.js → chunk-DNBBWBYA.js} +5 -5
  64. package/dist/{chunk-BJN7LMMK.js → chunk-EKWDNEPN.js} +3 -3
  65. package/dist/{chunk-TNWQ6SKS.js → chunk-EX33ZFJ6.js} +3 -3
  66. package/dist/{chunk-TMBLBDPB.js → chunk-FNC4SPOD.js} +2 -2
  67. package/dist/{chunk-IBULUTHA.js → chunk-FRPR4OTH.js} +4 -4
  68. package/dist/{chunk-ACM4OINM.js → chunk-FSSA76HW.js} +1 -1
  69. package/dist/{chunk-J2PAQ3HF.js → chunk-G2GOVKBU.js} +6 -6
  70. package/dist/{chunk-2KVELJZX.js → chunk-GGGOFJBL.js} +1 -1
  71. package/dist/{chunk-GKWPIE6R.js → chunk-GWHZUHIK.js} +1 -1
  72. package/dist/{chunk-BUXMFD5C.js → chunk-H6IJOGDH.js} +4 -4
  73. package/dist/{chunk-SN22OXY3.js → chunk-HARHFDZM.js} +1 -1
  74. package/dist/{chunk-44R5ATBR.js → chunk-HLAW7HUT.js} +2 -2
  75. package/dist/{chunk-G4HTRKCP.js → chunk-HVZJ2EEI.js} +6 -6
  76. package/dist/{chunk-6BD5ZZLL.js → chunk-HWT42Z4O.js} +5 -5
  77. package/dist/{chunk-L4THAI7Q.js → chunk-JHWOM55B.js} +2 -0
  78. package/dist/{chunk-NDLOWIYO.js → chunk-JJCMQRBF.js} +3 -3
  79. package/dist/{chunk-7MRX5JYA.js → chunk-JLJWVKMJ.js} +54 -835
  80. package/dist/{chunk-TBU4WXA4.js → chunk-JSZT4Q23.js} +1 -1
  81. package/dist/{chunk-MA6FJ7U3.js → chunk-LUSWC2MV.js} +3 -3
  82. package/dist/{chunk-C5EWCNJF.js → chunk-OGTZ7JR7.js} +1 -1
  83. package/dist/{chunk-FGWRVOBP.js → chunk-OKWHHDV5.js} +5 -5
  84. package/dist/{chunk-XHHX63PY.js → chunk-OSEGZLCO.js} +3 -3
  85. package/dist/{chunk-B2RDWRKR.js → chunk-PHBZK4SC.js} +2 -2
  86. package/dist/{chunk-S55CXRFD.js → chunk-POKCUYIQ.js} +1 -1
  87. package/dist/{chunk-YZVAAY6B.js → chunk-QF6OJUWQ.js} +1 -1
  88. package/dist/{chunk-5FM4BQOM.js → chunk-QG5Y5A36.js} +10 -10
  89. package/dist/{chunk-UNEJNC6X.js → chunk-QSDZE2B7.js} +5 -5
  90. package/dist/{chunk-Y32CL7XZ.js → chunk-RPNT4D3K.js} +1 -1
  91. package/dist/{chunk-6CJ4MSZU.js → chunk-SAPRO7FI.js} +6 -6
  92. package/dist/{chunk-LLQBPDFQ.js → chunk-SBK7WGSE.js} +2 -2
  93. package/dist/{chunk-GMZTABMV.js → chunk-TD5PW2VI.js} +6 -6
  94. package/dist/{chunk-VUI4HK5O.js → chunk-TFJQAPIA.js} +2 -2
  95. package/dist/{chunk-OKZC4FHN.js → chunk-TNPKYKXU.js} +166 -24
  96. package/dist/{chunk-2BDGGE2G.js → chunk-TSCFJJIB.js} +6 -6
  97. package/dist/{chunk-MND7HQ4P.js → chunk-TZDEHPYZ.js} +1 -1
  98. package/dist/{chunk-FEF3ILT6.js → chunk-UGELL4RB.js} +2 -2
  99. package/dist/{chunk-6WOG2SCC.js → chunk-UIDWJ24H.js} +6 -13
  100. package/dist/{chunk-ZS27XXDA.js → chunk-UWL6VVE3.js} +4 -4
  101. package/dist/{chunk-JIC5PGNI.js → chunk-V4JZHAOY.js} +2 -2
  102. package/dist/{chunk-35ABA2JQ.js → chunk-VD24OIWR.js} +1 -1
  103. package/dist/{chunk-GGI6GTBL.js → chunk-VJZGR4N3.js} +7 -5
  104. package/dist/{chunk-CVPVP4KP.js → chunk-VVWL6AB4.js} +5 -5
  105. package/dist/{chunk-A3TMREYJ.js → chunk-W2IRYDG5.js} +4 -4
  106. package/dist/{chunk-SSNLMIFR.js → chunk-WRKRZJCW.js} +10 -8
  107. package/dist/{chunk-ASEHRBD4.js → chunk-YQCCJ6U5.js} +3 -3
  108. package/dist/{chunk-42RQG2VG.js → chunk-YU5ACKJP.js} +4 -4
  109. package/dist/{chunk-HIMEVTA5.js → chunk-Z75D2NJN.js} +3 -3
  110. package/dist/{chunk-6PWU2LBT.js → chunk-ZHL6F2KC.js} +3 -3
  111. package/dist/{chunk-SVAGMJOH.js → chunk-ZNFAF74M.js} +1 -1
  112. package/dist/{chunk-ELYJNNXG.js → chunk-ZUZ7NTWO.js} +181 -75
  113. package/dist/{chunk-QPJQAE2L.js → chunk-ZWKF7WE4.js} +4 -4
  114. package/dist/{codex-app-cards-switch-CTAOTOCH.js → codex-app-cards-switch-26N5XSSZ.js} +11 -11
  115. package/dist/{codex-desktop-launch-2DZVA5C7.js → codex-desktop-launch-UU6CPB2I.js} +1 -1
  116. package/dist/{codex-session-launch-TMOSTWEH.js → codex-session-launch-66LBR4MG.js} +18 -18
  117. package/dist/{config-OV6WLZXO.js → config-ESAAVJWO.js} +3 -3
  118. package/dist/{global-upgrade-FI42NJNL.js → global-upgrade-QJONTWQI.js} +10 -10
  119. package/dist/{identity-PCA25OI5.js → identity-IZVPSC7B.js} +4 -4
  120. package/dist/{live-capabilities-CYFXHTOI.js → live-capabilities-OEUPZX67.js} +5 -5
  121. package/dist/{paths-4YFDMUK6.js → paths-GDWS3B46.js} +3 -3
  122. package/dist/{reapply-PBQ46BPS.js → reapply-P2VOZGWQ.js} +28 -27
  123. package/dist/src/index.js +29 -29
  124. package/dist/{upgrade-lock-22J2AMVY.js → upgrade-lock-3QABNXBZ.js} +4 -4
  125. package/dist/{usage-7KTINNRK.js → usage-KDRZPUZS.js} +3 -3
  126. package/package.json +1 -1
  127. package/dist/chunk-7EIMASAA.js +0 -74
@@ -1,6 +1,36 @@
1
+ import {
2
+ AGENT_IDENTITIES,
3
+ COST_TRACKING_ENV,
4
+ DEFAULT_MODEL_PRICES,
5
+ TEAMMATE_IDLE_ACTION,
6
+ canonicalGateInputs,
7
+ compactionAction,
8
+ deriveReceiptMeta,
9
+ deriveToolTarget,
10
+ describeStopFailure,
11
+ describeToolCall,
12
+ estimateMessageCostUsd,
13
+ isModelPrice,
14
+ isToolResultError,
15
+ notificationAction,
16
+ notificationTypeOf,
17
+ parseApplyPatchFiles,
18
+ parseApplyPatchOps,
19
+ readTranscriptMessageUsage,
20
+ rememberTranscriptMessage,
21
+ sessionEndAction,
22
+ sessionIdentityOf,
23
+ sessionStartAction,
24
+ subagentStopSummary,
25
+ summarizeStop,
26
+ taskTitleFrom,
27
+ toolResultErrorText,
28
+ transcriptTokensIn,
29
+ transcriptUsageRequest
30
+ } from "./chunk-3MWQZKIO.js";
1
31
  import {
2
32
  repoKeyFor
3
- } from "./chunk-C5EWCNJF.js";
33
+ } from "./chunk-OGTZ7JR7.js";
4
34
  import {
5
35
  cancelQuestion,
6
36
  clientErrorKindOf,
@@ -8,847 +38,54 @@ import {
8
38
  reportClientError,
9
39
  sendNotification,
10
40
  waitForAnswer
11
- } from "./chunk-6BD5ZZLL.js";
41
+ } from "./chunk-HWT42Z4O.js";
12
42
  import {
13
43
  withRetry
14
- } from "./chunk-QPJQAE2L.js";
44
+ } from "./chunk-ZWKF7WE4.js";
15
45
  import {
16
46
  getMachineId
17
- } from "./chunk-JIC5PGNI.js";
47
+ } from "./chunk-V4JZHAOY.js";
18
48
  import {
19
49
  reportedInstallSource
20
- } from "./chunk-FEF3ILT6.js";
50
+ } from "./chunk-UGELL4RB.js";
21
51
  import {
22
52
  IDLE_PROMPT_NOTIFICATION,
23
53
  NOTIFICATION_PUSH_TYPES,
24
54
  POSTTOOLUSE_MIRROR_ONLY_TOOLS,
25
55
  canonicalJson,
26
56
  claudeConfigDir
27
- } from "./chunk-B2RDWRKR.js";
57
+ } from "./chunk-PHBZK4SC.js";
28
58
  import {
29
59
  compareVersion,
30
60
  parseVersion,
31
61
  writeFileAtomic,
32
62
  writeJsonAtomicDurable
33
- } from "./chunk-YIAJOV2X.js";
63
+ } from "./chunk-64XK7DLE.js";
34
64
  import {
35
65
  getApiKey,
36
66
  getBaseUrl
37
- } from "./chunk-TBU4WXA4.js";
67
+ } from "./chunk-JSZT4Q23.js";
38
68
  import {
39
- ACTION_BODY_MAX,
40
- AGENTS,
41
- AGENT_LABELS_BY_TYPE,
42
- BLANK_TASK_INPUT_TOOL,
43
69
  BLOCKED_ACTION_GRANT_TTL_SECONDS,
44
- CODEX_SHELL_COMMAND_FLAGS,
45
70
  COMMAND_RECOVERY,
46
- DECISION_LINE_MAX,
47
- FILE_TARGET_TOOLS,
48
- GATE_MAX_TOOL_INPUTS,
49
- HOOK_COMPATIBLE_PROFILES,
50
71
  HOOK_SOURCES,
51
72
  REPO_AWARE_AGENTS,
52
- TASK_OUTPUT_TOOL,
53
- TASK_STOP_TOOL,
54
73
  blockedActionIdentity,
55
74
  canCarryPendingCommand,
56
- canonicalToolName,
57
75
  claudeTurnEndOutput,
58
- conversationText,
59
76
  gateOutputFor,
60
- hookCompatibleProfileBySource,
61
77
  isAutoApprove,
62
78
  isClaudeWakePrompt,
63
79
  isRecord,
64
- isTokenCount,
65
80
  modeStateFromResponse,
66
81
  nativeRecord,
67
- parseMcpToolName,
68
82
  pendingCommandEvents,
69
83
  pendingCommandInstruction,
70
84
  questionLimitHandBack,
71
- redactSecrets,
72
- redactSecretsDeep,
73
- reportableSessionId,
74
85
  resolveAutoResolveOrigin,
75
86
  resolvePolicy,
76
- toToolLookup,
77
- truncateLine,
78
87
  unansweredRefusalReason
79
- } from "./chunk-L4THAI7Q.js";
80
-
81
- // ../hook-mapping/src/describe.ts
82
- import { isAbsolute, relative, resolve } from "path";
83
- var hookPrefixes = {
84
- Bash: (input) => `bash: ${input.command ?? "(no command)"}`,
85
- PowerShell: (input) => `powershell: ${input.command ?? "(no command)"}`,
86
- Monitor: (input) => `monitor: ${input.command ?? "(no command)"}`,
87
- Write: (input) => `write file: ${input.file_path ?? "(unknown path)"}`,
88
- Edit: (input) => `edit file: ${editTarget(input) ?? "(unknown path)"}`,
89
- MultiEdit: (input) => `edit file: ${editTarget(input) ?? "(unknown path)"}`,
90
- Read: (input) => `read file: ${input.file_path ?? "(unknown path)"}`,
91
- // Without an entry here the fallback stringifies the whole tool input, and for
92
- // ExitPlanMode that input IS the plan: the action line became a truncated dump of
93
- // the plan markdown. The plan belongs in the body, not the one-line summary.
94
- ExitPlanMode: () => "finished planning and wants to start coding",
95
- // Mirrored on PostToolUse since the matcher was widened. Without entries the
96
- // fallback prints `Task: done` and `WebSearch: done`, which name the tool and
97
- // drop the only part a person reads: which subagent, and what it looked for.
98
- Task: (input) => `subagent: ${describeTaskCall(input)}`,
99
- WebSearch: (input) => `web search: ${firstString(input.query) ?? "(no query)"}`,
100
- [TASK_OUTPUT_TOOL]: (input) => {
101
- const task = firstString(input.task_id);
102
- return task ? `check background task ${task}` : "list background tasks";
103
- },
104
- [TASK_STOP_TOOL]: (input) => `stop background task ${firstString(input.task_id) ?? "(unnamed)"}`,
105
- [BLANK_TASK_INPUT_TOOL]: (input) => `send blank input, such as Enter, to background task ${firstString(input.task_id) ?? "(unnamed)"}`
106
- };
107
- var describeTaskCall = (input) => firstString(input.description) ?? firstString(input.subagent_type) ?? "(unnamed)";
108
- var describeTodoProgress = (todos) => {
109
- if (!Array.isArray(todos)) return "updated the plan";
110
- const items = todos.filter((t) => !!t && typeof t === "object");
111
- const total = items.length;
112
- if (total === 0) return "updated the plan";
113
- const done = items.filter((t) => t.status === "completed").length;
114
- const current = items.find((t) => t.status === "in_progress");
115
- const label = current ? [current.activeForm, current.content].find((v) => typeof v === "string" && v.trim().length > 0) : void 0;
116
- if (done >= total) return `finished all ${total} tasks`;
117
- if (label) return `${label.trim()} (${done}/${total} done)`;
118
- return `${done}/${total} tasks done`;
119
- };
120
- var editTarget = (input) => {
121
- if (typeof input.file_path === "string") return input.file_path;
122
- if (!Array.isArray(input.file_paths) || !input.file_paths.every((path) => typeof path === "string")) return void 0;
123
- return input.file_paths.join(", ");
124
- };
125
- var eventPrefixes = {
126
- Bash: (input) => `ran: ${String(input.command ?? "")}`,
127
- PowerShell: (input) => `ran: ${String(input.command ?? "")}`,
128
- Monitor: (input) => `ran: ${String(input.command ?? "")}`,
129
- Write: (input) => `wrote: ${input.file_path ?? "unknown"}`,
130
- Edit: (input) => `edited: ${editTarget(input) ?? "unknown"}`,
131
- MultiEdit: (input) => `edited: ${editTarget(input) ?? "unknown"}`,
132
- Read: (input) => `read: ${input.file_path ?? "unknown"}`,
133
- TodoWrite: (input) => describeTodoProgress(input.todos),
134
- Task: (input) => `ran subagent: ${describeTaskCall(input)}`,
135
- WebSearch: (input) => `searched: ${firstString(input.query) ?? "the web"}`
136
- };
137
- var NETWORK_TARGET_KEYS = ["url", "urls", "href", "host", "hosts", "hostname", "domain", "domains"];
138
- var ABSOLUTE_HTTP_URL = /^https?:\/\//i;
139
- var HOSTNAME = /^(?=.{1,253}$)[a-z0-9](?:[a-z0-9-]*[a-z0-9])?(?:\.[a-z0-9](?:[a-z0-9-]*[a-z0-9])?)+(?::\d{1,5})?$/i;
140
- var hostOfUrl = (value) => {
141
- try {
142
- return new URL(value).host || void 0;
143
- } catch {
144
- return void 0;
145
- }
146
- };
147
- var hostOf = (value, bareHostnames) => {
148
- if (typeof value !== "string") return void 0;
149
- const trimmed = value.trim();
150
- if (ABSOLUTE_HTTP_URL.test(trimmed)) return hostOfUrl(trimmed);
151
- return bareHostnames && HOSTNAME.test(trimmed) ? trimmed : void 0;
152
- };
153
- var firstHost = (value, bareHostnames) => Array.isArray(value) ? value.map((entry) => hostOf(entry, bareHostnames)).find((host) => host !== void 0) : hostOf(value, bareHostnames);
154
- var deriveNetworkTarget = (toolInput) => {
155
- for (const key of NETWORK_TARGET_KEYS) {
156
- const host = firstHost(toolInput[key], true);
157
- if (host) return host;
158
- }
159
- return Object.values(toolInput).map((value) => firstHost(value, false)).find((host) => host !== void 0);
160
- };
161
- var describeUnbuiltCall = (toolName, toolInput, format) => {
162
- const mcp = parseMcpToolName(toolName);
163
- const host = deriveNetworkTarget(toolInput);
164
- if (mcp) {
165
- if (format === "event") return `called ${mcp.tool} on ${mcp.server}`;
166
- return host ? `call ${mcp.tool} on ${mcp.server} to reach ${host}` : `call ${mcp.tool} on ${mcp.server}`;
167
- }
168
- if (host) return format === "event" ? `accessed ${host}` : `network access to ${host}`;
169
- return void 0;
170
- };
171
- var EVENT_ACTION_MAX = 120;
172
- var HOOK_FALLBACK_MAX = 200;
173
- var UNNAMED_ACTION = "this request";
174
- var describeToolCall = (toolName, toolInput, format = "hook") => {
175
- if (!toolName) return "";
176
- const prefixes = format === "hook" ? hookPrefixes : eventPrefixes;
177
- const builder = prefixes[toolName];
178
- const unbuilt = builder ? void 0 : describeUnbuiltCall(toolName, toolInput ?? {}, format);
179
- const detail = JSON.stringify(toolInput ?? {});
180
- const raw = builder ? builder(toolInput) : unbuilt ?? (format === "hook" ? detail === "{}" || detail === void 0 ? toolName : `${toolName}: ${detail}` : `${toolName}: done`);
181
- const redacted = redactSecrets(raw);
182
- if (format === "event") return redacted.slice(0, EVENT_ACTION_MAX);
183
- return builder || unbuilt ? redacted : redacted.slice(0, HOOK_FALLBACK_MAX);
184
- };
185
- var TOOL_TARGET_MAX_LENGTH = 80;
186
- var deriveCommandHead = (command) => {
187
- if (typeof command !== "string") return void 0;
188
- const head = command.trim().split(/\s+/).slice(0, 2).join(" ");
189
- return head ? redactSecrets(head).slice(0, TOOL_TARGET_MAX_LENGTH) : void 0;
190
- };
191
- var deriveToolTarget = (toolName, toolInput) => {
192
- if (toolName === "Bash" || toolName === "PowerShell" || toolName === "Monitor") {
193
- return deriveCommandHead(toolInput.command);
194
- }
195
- if (FILE_TARGET_TOOLS.has(toolName)) {
196
- const filePath = toolInput.file_path;
197
- if (typeof filePath !== "string") return void 0;
198
- const separator = Math.max(filePath.lastIndexOf("/"), filePath.lastIndexOf("\\"));
199
- const base = filePath.slice(separator + 1);
200
- const dot = base.lastIndexOf(".");
201
- if (dot <= 0) return void 0;
202
- return base.slice(dot).slice(0, TOOL_TARGET_MAX_LENGTH);
203
- }
204
- const mcp = parseMcpToolName(toolName);
205
- if (mcp) return mcp.server.slice(0, TOOL_TARGET_MAX_LENGTH);
206
- return deriveNetworkTarget(toolInput)?.slice(0, TOOL_TARGET_MAX_LENGTH);
207
- };
208
- var SCRIPT_RUNNERS = /* @__PURE__ */ new Set(["npm", "pnpm", "yarn", "bun", "npx", "deno", "rake", "make", "just", "task", "turbo"]);
209
- var RUN_SUBCOMMANDS = /* @__PURE__ */ new Set(["run", "run-script", "exec", "task"]);
210
- var deriveReceiptCommandHead = (command) => {
211
- if (typeof command !== "string") return void 0;
212
- const tokens = command.trim().split(/\s+/);
213
- const [first, second] = tokens;
214
- const keep = first && second && SCRIPT_RUNNERS.has(first.toLowerCase()) && RUN_SUBCOMMANDS.has(second.toLowerCase()) ? 3 : 2;
215
- const head = tokens.slice(0, keep).join(" ");
216
- return head ? redactSecrets(head).slice(0, TOOL_TARGET_MAX_LENGTH) : void 0;
217
- };
218
- var RECEIPT_TARGET_MAX_LENGTH = 256;
219
- var parseApplyPatchOps = (command) => {
220
- if (typeof command !== "string") return [];
221
- const ops = [];
222
- for (const line of command.split("\n")) {
223
- const file = line.match(/^\s*\*\*\*\s+(Add|Update|Delete) File:\s+(.+?)\s*$/);
224
- if (file) {
225
- ops.push({ op: file[1].toLowerCase(), path: file[2] });
226
- continue;
227
- }
228
- const move = line.match(/^\s*\*\*\*\s+Move to:\s+(.+?)\s*$/);
229
- if (move) ops.push({ op: "move", path: move[1] });
230
- }
231
- return ops;
232
- };
233
- var parseApplyPatchFiles = (command) => [...new Set(parseApplyPatchOps(command).map((entry) => entry.path))];
234
- var patchDeletesFiles = (toolName, toolInput) => toolName === "apply_patch" && parseApplyPatchOps(toolInput.command).some((entry) => entry.op === "delete");
235
- var OPENCODE_TOOL_NAMES = {
236
- bash: "Bash",
237
- shell: "Bash",
238
- // A shell command reaching outside the worktree asks a second time under its
239
- // own key. It is still the same command, and still Bash.
240
- external_directory: "Bash",
241
- edit: "Edit",
242
- patch: "Edit",
243
- apply_patch: "Edit",
244
- write: "Write",
245
- read: "Read",
246
- glob: "Glob",
247
- grep: "Grep",
248
- webfetch: "WebFetch",
249
- websearch: "WebSearch",
250
- task: "Task",
251
- subagent: "Task"
252
- };
253
- var PATCH_ARG_KEYS = ["command", "patch", "input"];
254
- var patchedFilesIn = (input) => [...new Set(PATCH_ARG_KEYS.flatMap((key) => parseApplyPatchFiles(input[key])))];
255
- var lookupsForInput = (profile, toolName, input, absolute) => {
256
- const gateInput = profile.source === "grok" && toolName === "apply_patch" ? { patch: input.patch, diff: input.patch } : input;
257
- const lookup = toToolLookup(profile, toolName, gateInput, absolute);
258
- if (!lookup.unreadable) return [lookup];
259
- const files = patchedFilesIn(gateInput);
260
- if (files.length === 0) return [lookup];
261
- return files.slice(0, GATE_MAX_TOOL_INPUTS + 1).map((file) => toToolLookup(profile, toolName, { ...gateInput, file_path: absolute(file) }, absolute));
262
- };
263
- var compatibleToolLookup = (profile, toolName, input, cwd) => {
264
- const absolute = (path) => cwd && !isAbsolute(path) ? resolve(cwd, path) : path;
265
- const lookups = lookupsForInput(profile, toolName, input, absolute);
266
- const first = lookups[0];
267
- if (!first) return { tool: canonicalToolName(profile, toolName), input, unreadable: true };
268
- if (lookups.length === 1) return first;
269
- const { file_path, ...content } = first.input;
270
- return {
271
- tool: first.tool,
272
- input: { ...content, file_paths: lookups.map((lookup) => lookup.input.file_path) },
273
- unreadable: lookups.length > GATE_MAX_TOOL_INPUTS || lookups.some((lookup) => lookup.unreadable)
274
- };
275
- };
276
- var compatibleGateInputs = (profile, toolName, toolInputs, cwd) => {
277
- const absolute = (path) => cwd && !isAbsolute(path) ? resolve(cwd, path) : path;
278
- const lookups = toolInputs.flatMap((input) => lookupsForInput(profile, toolName, input, absolute));
279
- if (lookups.length > GATE_MAX_TOOL_INPUTS) return null;
280
- if (lookups.some((lookup) => lookup.unreadable)) return null;
281
- return {
282
- toolName: lookups[0]?.tool ?? canonicalToolName(profile, toolName),
283
- toolInputs: lookups.map((lookup) => lookup.input)
284
- };
285
- };
286
- var canonicalGateInputs = (source, toolName, toolInputs, cwd) => {
287
- if (source === "codex" && toolName === "apply_patch" || source === "vscode" && ["apply_patch", "applyPatch", "copilot_applyPatch"].includes(toolName)) {
288
- const paths = [...new Set(toolInputs.flatMap((input) => parseApplyPatchFiles(input.command ?? input.input ?? input.patch)))];
289
- if (paths.length > GATE_MAX_TOOL_INPUTS) return null;
290
- return {
291
- toolName: "Edit",
292
- toolInputs: paths.length === 0 ? toolInputs.map((input) => ({ file_path: input.command })) : paths.map((path) => ({ file_path: cwd && !isAbsolute(path) ? resolve(cwd, path) : path }))
293
- };
294
- }
295
- if (source === "opencode") {
296
- const canonical2 = OPENCODE_TOOL_NAMES[toolName] ?? toolName;
297
- return {
298
- toolName: canonical2,
299
- toolInputs: toolInputs.map((input) => {
300
- const path = input.file_path;
301
- return typeof path === "string" && path.length > 0 && cwd && !isAbsolute(path) ? { ...input, file_path: resolve(cwd, path) } : input;
302
- })
303
- };
304
- }
305
- if (source === "vscode" || source === "cursor") {
306
- if (source === "vscode" && toolName.startsWith("mcp_pushary_")) return { toolName: `mcp__pushary__${toolName.slice("mcp_pushary_".length)}`, toolInputs };
307
- const alias = toolName.replace(/^copilot_/, "").toLowerCase().replace(/[^a-z0-9]/g, "");
308
- const shells = [
309
- "runterminalcommand",
310
- "runinterminal",
311
- "runcommand",
312
- "terminalcommand",
313
- "executecommand",
314
- "runinterminalcommand",
315
- "bash",
316
- "shell",
317
- "terminal",
318
- "sendtoterminal",
319
- "powershell",
320
- "localshell"
321
- ];
322
- const canonical2 = shells.includes(alias) ? "Bash" : ["createfile", "write", "createdirectory", "createnewjupyternotebook"].includes(alias) ? "Write" : ["replacestringinfile", "multireplacestringinfile", "replacestring", "multireplacestring", "inserteditintofile", "insertedit", "edit", "editfile", "editfiles", "editnotebookfile", "editnotebook"].includes(alias) ? "Edit" : [
323
- "readfile",
324
- "viewimage",
325
- "listdir",
326
- "listdirectory",
327
- "filesearch",
328
- "findfiles",
329
- "grepsearch",
330
- "findtextinfiles",
331
- "semanticsearch",
332
- "searchcodebase",
333
- "searchworkspacesymbols",
334
- "geterrors",
335
- "getchangedfiles",
336
- "readprojectstructure",
337
- "getnotebooksummary",
338
- "readnotebookcelloutput",
339
- "testsearch",
340
- "findtestfiles",
341
- "testfailure",
342
- "getvscodeapi",
343
- "getterminaloutput",
344
- "gettaskoutput",
345
- "terminalselection",
346
- "terminallastcommand"
347
- ].includes(alias) ? "Read" : toolName;
348
- const inputs = toolInputs.flatMap((input) => ["multireplacestringinfile", "multireplacestring"].includes(alias) && Array.isArray(input.replacements) ? input.replacements.filter((item) => !!item && typeof item === "object" && !Array.isArray(item)) : alias === "editfiles" && Array.isArray(input.files) ? input.files.map((file) => typeof file === "string" ? { file_path: file } : file).filter((file) => !!file && typeof file === "object" && !Array.isArray(file)) : [input]);
349
- if (inputs.length > GATE_MAX_TOOL_INPUTS) return null;
350
- return { toolName: canonical2, toolInputs: inputs.map((input) => {
351
- if (canonical2 === "Bash") return { ...input, command: [input.command, input.commandLine, input.command_line, input.cmd, input.script, input.input, input.text].find((value) => typeof value === "string") };
352
- const path = input.file_path ?? input.filePath ?? input.path;
353
- return typeof path === "string" ? { ...input, file_path: cwd && !isAbsolute(path) ? resolve(cwd, path) : path } : input;
354
- }) };
355
- }
356
- const profile = hookCompatibleProfileBySource(source);
357
- if (profile) return compatibleGateInputs(profile, toolName, toolInputs, cwd);
358
- if (source !== "gemini") return { toolName, toolInputs };
359
- if (toolName === "run_shell_command") {
360
- return { toolName: "Bash", toolInputs: toolInputs.map((input) => ({ command: input.command })) };
361
- }
362
- const canonical = { write_file: "Write", replace: "Edit", read_file: "Read" }[toolName];
363
- if (!canonical) return { toolName, toolInputs };
364
- return {
365
- toolName: canonical,
366
- toolInputs: toolInputs.map((input) => {
367
- const path = [input.file_path, input.absolute_path, input.path].find((value) => typeof value === "string" && value.length > 0);
368
- return path ? { file_path: cwd && !isAbsolute(path) ? resolve(cwd, path) : path } : {};
369
- })
370
- };
371
- };
372
- var EXIT_CODE_FAILURE = /^Error: Exit code \d+/;
373
- var isToolResultError = (toolResult) => {
374
- try {
375
- if (typeof toolResult === "string") return EXIT_CODE_FAILURE.test(toolResult);
376
- if (!toolResult || typeof toolResult !== "object") return false;
377
- return "error" in toolResult || "is_error" in toolResult;
378
- } catch {
379
- return false;
380
- }
381
- };
382
- var toolResultErrorText = (toolResult) => {
383
- try {
384
- const raw = typeof toolResult === "string" ? toolResult : toolResult && typeof toolResult === "object" ? String(
385
- toolResult.error ?? toolResult.stderr ?? ""
386
- ) : "";
387
- return redactSecrets(raw);
388
- } catch {
389
- return "";
390
- }
391
- };
392
- var relativizeReceiptPath = (filePath, cwd) => {
393
- if (!cwd || !isAbsolute(filePath)) return filePath;
394
- return relative(cwd, filePath);
395
- };
396
- var deriveReceiptMeta = (toolName, toolInput, toolResult, cwd) => {
397
- try {
398
- const ok = !isToolResultError(toolResult);
399
- if (toolName === "apply_patch") {
400
- const files = parseApplyPatchFiles(toolInput.command);
401
- const target = files.length === 1 ? files[0] : toolInput.command;
402
- if (typeof target !== "string" || !target) return void 0;
403
- return { kind: "edit", target: redactSecrets(target).slice(0, RECEIPT_TARGET_MAX_LENGTH), ok };
404
- }
405
- const canonicalTool = {
406
- run_shell_command: "Bash",
407
- write_file: "Write",
408
- replace: "Edit"
409
- }[toolName] ?? toolName;
410
- const canonicalInput = canonicalTool === toolName ? toolInput : {
411
- ...toolInput,
412
- file_path: toolInput.file_path ?? toolInput.absolute_path ?? toolInput.path
413
- };
414
- if (canonicalTool === "Edit" && Array.isArray(canonicalInput.file_paths)) {
415
- const patch = firstString(canonicalInput.diff, canonicalInput.command, canonicalInput.patch, canonicalInput.input);
416
- if (patch) return { kind: "edit", target: redactSecrets(patch).slice(0, RECEIPT_TARGET_MAX_LENGTH), ok };
417
- }
418
- if (FILE_TARGET_TOOLS.has(canonicalTool)) {
419
- const filePath = canonicalInput.file_path;
420
- if (typeof filePath !== "string" || !filePath) return void 0;
421
- return {
422
- kind: canonicalTool === "Write" ? "write" : "edit",
423
- // A path is an unlikely place for a credential but not an impossible one
424
- // (a token in a temp directory name), and this field is persisted.
425
- target: redactSecrets(relativizeReceiptPath(filePath, cwd)).slice(0, RECEIPT_TARGET_MAX_LENGTH),
426
- ok
427
- };
428
- }
429
- if (canonicalTool === "Bash" || canonicalTool === "PowerShell" || canonicalTool === "Monitor") {
430
- const head = deriveReceiptCommandHead(canonicalInput.command);
431
- if (!head) return void 0;
432
- return {
433
- kind: head === "git commit" ? "commit" : "bash",
434
- target: head,
435
- ok
436
- };
437
- }
438
- return void 0;
439
- } catch {
440
- return void 0;
441
- }
442
- };
443
- var scopePathFor = (toolName, toolInput, cwd) => {
444
- const meta = deriveReceiptMeta(toolName, toolInput, void 0, cwd);
445
- if (!meta) return void 0;
446
- return meta.kind === "edit" || meta.kind === "write" ? meta.target : void 0;
447
- };
448
- var firstString = (...values) => values.find((v) => typeof v === "string" && v.length > 0);
449
- var ACTION_BODY_TRUNCATION_MARKER = "\n\u2026 [truncated]";
450
- var capActionBody = (text) => truncateLine(text, ACTION_BODY_MAX, ACTION_BODY_TRUNCATION_MARKER);
451
- var rawActionBody = (toolName, toolInput) => {
452
- if (toolName === "Edit" || toolName === "replace") {
453
- const before = firstString(toolInput.old_string);
454
- const after = firstString(toolInput.new_string);
455
- if (before === void 0 && after === void 0) return firstString(toolInput.diff);
456
- return `- ${before ?? ""}
457
- + ${after ?? ""}`;
458
- }
459
- if (toolName === "Write" || toolName === "write_file") {
460
- return firstString(toolInput.content) ?? firstString(toolInput.diff);
461
- }
462
- if (toolName === "ExitPlanMode") return firstString(toolInput.plan);
463
- if (toolName === "Bash" || toolName === "PowerShell" || toolName === "Monitor" || toolName === "run_shell_command" || toolName === "shell" || toolName === "apply_patch") {
464
- return firstString(toolInput.command);
465
- }
466
- if (toolName === "write_stdin" || toolName === "request_permissions") return JSON.stringify(toolInput, null, 2);
467
- return firstString(toolInput.url, toolInput.href);
468
- };
469
- var deriveActionBody = (toolName, toolInput) => {
470
- try {
471
- const raw = rawActionBody(toolName, toolInput);
472
- if (!raw) return void 0;
473
- return capActionBody(redactSecretsDeep(raw));
474
- } catch {
475
- return void 0;
476
- }
477
- };
478
- var deriveAction = (toolName, toolInput) => truncateLine(describeToolCall(toolName, toolInput, "hook"), DECISION_LINE_MAX);
479
- var BLOCKER_BY_MODE = {
480
- push_only: "Approval required before this runs",
481
- push_first: "Paused for your approval before continuing",
482
- escalate: "Escalated to you after the approval timeout"
483
- };
484
- var deriveBlocker = (mode, reason) => {
485
- const text = reason?.replace(/\s+/g, " ").trim() || BLOCKER_BY_MODE[mode] || "Waiting for your approval";
486
- return truncateLine(text, DECISION_LINE_MAX);
487
- };
488
-
489
- // ../hook-mapping/src/map.ts
490
- import { basename } from "path";
491
- var AGENT_IDENTITIES = {
492
- claude: { type: "claude_code", label: AGENT_LABELS_BY_TYPE.claude_code },
493
- codex: { type: "codex", label: AGENT_LABELS_BY_TYPE.codex },
494
- gemini: { type: "gemini_cli", label: AGENT_LABELS_BY_TYPE.gemini_cli },
495
- cursor: { type: "cursor", label: AGENT_LABELS_BY_TYPE.cursor },
496
- vscode: { type: "vscode", label: AGENT_LABELS_BY_TYPE.vscode },
497
- opencode: { type: "opencode", label: AGENT_LABELS_BY_TYPE.opencode },
498
- qwen: { type: "qwen_code", label: AGENT_LABELS_BY_TYPE.qwen_code },
499
- codebuddy: { type: "codebuddy", label: AGENT_LABELS_BY_TYPE.codebuddy },
500
- qoder: { type: "qoder", label: AGENT_LABELS_BY_TYPE.qoder },
501
- droid: { type: "droid", label: AGENT_LABELS_BY_TYPE.droid },
502
- devin: { type: "devin", label: AGENT_LABELS_BY_TYPE.devin },
503
- antigravity: { type: "antigravity_cli", label: AGENT_LABELS_BY_TYPE.antigravity_cli },
504
- grok: { type: "grok", label: AGENTS.grok.label }
505
- };
506
- var TEAMMATE_IDLE_ACTION = "A teammate went idle";
507
- var CLAUDE_MEANINGS = {
508
- PostToolUse: { kind: "tool", event: "tool_complete" },
509
- UserPromptSubmit: { kind: "prompt", event: "user_prompt" },
510
- Stop: { kind: "stop", event: "session_end" },
511
- SubagentStop: { kind: "subagent_stop", event: "session_end" },
512
- PreCompact: { kind: "compaction", event: "compaction" },
513
- PostCompact: { kind: "compaction", event: "compaction" },
514
- SessionStart: { kind: "session_start", event: "session_start" },
515
- SessionEnd: { kind: "session_closed", event: "session_closed" },
516
- SubagentStart: { kind: "session_start", event: "session_start", action: "Subagent started" },
517
- Notification: { kind: "notification", event: "notification" },
518
- TeammateIdle: { kind: "teammate_idle", event: "teammate_idle", action: TEAMMATE_IDLE_ACTION },
519
- StopFailure: { kind: "stop_failure", event: "turn_error" },
520
- PermissionDenied: { kind: "permission_denied", event: "permission_denied" }
521
- };
522
- var compatibleMeanings = (agentType) => {
523
- const events = HOOK_COMPATIBLE_PROFILES.find((profile) => profile.agentType === agentType)?.events ?? [];
524
- return Object.fromEntries(events.flatMap((event) => {
525
- const meaning = CLAUDE_MEANINGS[event];
526
- return meaning ? [[event, meaning]] : [];
527
- }));
528
- };
529
- var MEANING_BY_HOOK = {
530
- claude: CLAUDE_MEANINGS,
531
- qwen: compatibleMeanings("qwen_code"),
532
- codebuddy: compatibleMeanings("codebuddy"),
533
- qoder: compatibleMeanings("qoder"),
534
- droid: compatibleMeanings("droid"),
535
- devin: compatibleMeanings("devin"),
536
- antigravity: compatibleMeanings("antigravity_cli"),
537
- grok: { ...compatibleMeanings("grok"), PostToolUseFailure: { kind: "tool", event: "tool_complete" }, StopCancelled: { kind: "stop_failure", event: "turn_error" } },
538
- codex: {
539
- PostToolUse: { kind: "tool", event: "tool_complete" },
540
- UserPromptSubmit: { kind: "prompt", event: "user_prompt" },
541
- Stop: { kind: "stop", event: "session_end" },
542
- SessionStart: { kind: "session_start", event: "session_begin", action: "Session started" },
543
- SessionEnd: { kind: "session_closed", event: "session_closed" },
544
- // Codex names all four in its own HookEventName enum, and the CLI registers
545
- // them. A row missing here is the same defect as the dropped Codex
546
- // SessionEnd: the CLI reports the event, the Mac app forwards the identical
547
- // envelope, and only the app's copy vanishes.
548
- SubagentStart: { kind: "session_start", event: "session_begin", action: "Subagent started" },
549
- SubagentStop: { kind: "subagent_stop", event: "session_end" },
550
- PreCompact: { kind: "compaction", event: "compaction" },
551
- PostCompact: { kind: "compaction", event: "compaction" }
552
- },
553
- gemini: {
554
- AfterTool: { kind: "tool", event: "tool_complete" },
555
- BeforeAgent: { kind: "prompt", event: "user_prompt" },
556
- AfterAgent: { kind: "stop", event: "session_end" },
557
- SessionStart: { kind: "session_start", event: "session_begin", action: "Session started" },
558
- SessionEnd: { kind: "session_closed", event: "session_closed" }
559
- },
560
- cursor: {
561
- afterShellExecution: { kind: "tool", event: "tool_complete" },
562
- afterFileEdit: { kind: "tool", event: "tool_complete" },
563
- postToolUse: { kind: "tool", event: "tool_complete" },
564
- stop: { kind: "stop", event: "session_end" },
565
- sessionStart: { kind: "session_start", event: "session_begin" },
566
- sessionEnd: { kind: "session_closed", event: "session_closed" },
567
- beforeSubmitPrompt: { kind: "prompt", event: "user_prompt" },
568
- preCompact: { kind: "compaction", event: "compaction" },
569
- subagentStart: { kind: "session_start", event: "session_begin", action: "Subagent started" },
570
- subagentStop: { kind: "subagent_stop", event: "notification" }
571
- },
572
- vscode: {
573
- PostToolUse: { kind: "tool", event: "tool_complete" },
574
- Stop: { kind: "stop", event: "session_end" },
575
- SessionStart: { kind: "session_start", event: "session_begin" },
576
- UserPromptSubmit: { kind: "prompt", event: "user_prompt" },
577
- PreCompact: { kind: "compaction", event: "compaction" },
578
- SubagentStart: { kind: "session_start", event: "session_begin", action: "Subagent started" },
579
- SubagentStop: { kind: "subagent_stop", event: "session_end" }
580
- },
581
- // OpenCode's own names, because the plugin sends the hook it was called from
582
- // rather than translating. `session.idle` is the turn boundary — its Stop, not
583
- // its SessionEnd — and there is no session-start entry on purpose: OpenCode
584
- // publishes `session.created` for every subagent fork too.
585
- opencode: {
586
- "tool.execute.after": { kind: "tool", event: "tool_complete" },
587
- "chat.message": { kind: "prompt", event: "user_prompt" },
588
- "session.idle": { kind: "stop", event: "session_end" }
589
- }
590
- };
591
- var TASK_TITLE_MAX_LENGTH = 120;
592
- var STOP_SUMMARY_MAX_LENGTH = 200;
593
- var SESSION_END_ACTIONS = {
594
- clear: "Session cleared",
595
- logout: "Logged out",
596
- resume: "Session suspended",
597
- prompt_input_exit: "Session ended",
598
- bypass_permissions_disabled: "Session ended",
599
- other: "Session ended"
600
- };
601
- var countArray = (value) => Array.isArray(value) ? value.length : 0;
602
- var summarizeFinalMessage = (message) => {
603
- if (typeof message !== "string") return "Session ended";
604
- const collapsed = conversationText(message).replace(/\s+/g, " ").trim();
605
- if (!collapsed) return "Session ended";
606
- return collapsed.slice(0, STOP_SUMMARY_MAX_LENGTH);
607
- };
608
- var summarizeStop = (input) => {
609
- const running = countArray(input.background_tasks);
610
- if (running > 0) return `Paused with ${running} background task${running === 1 ? "" : "s"} still running`;
611
- const crons = countArray(input.session_crons);
612
- if (crons > 0) return `Idle until a scheduled task wakes it (${crons} pending)`;
613
- return summarizeFinalMessage(input.last_assistant_message ?? input.prompt_response);
614
- };
615
- var subagentStopAction = (agentType) => {
616
- const name = typeof agentType === "string" ? agentType.replace(/\s+/g, " ").trim() : "";
617
- return name ? `${name} subagent finished` : "Subagent finished";
618
- };
619
- var subagentStopSummary = (input) => {
620
- const message = input.last_assistant_message ?? input.prompt_response;
621
- if (typeof message === "string" && message.trim()) return summarizeStop(input);
622
- return subagentStopAction(input.agent_type);
623
- };
624
- var COMPACTION_TRIGGERS = {
625
- manual: "on request",
626
- auto: "automatically"
627
- };
628
- var compactionAction = (hookEvent, trigger) => {
629
- const how = typeof trigger === "string" ? COMPACTION_TRIGGERS[trigger] : void 0;
630
- const base = hookEvent === "PostCompact" ? "Compacted context" : "Compacting context";
631
- return how ? `${base} ${how}` : base;
632
- };
633
- var sessionStartAction = (source) => source === "resume" ? "Session resumed" : "Session started";
634
- var sessionEndAction = (reason) => typeof reason === "string" && SESSION_END_ACTIONS[reason] || "Session ended";
635
- var taskTitleFrom = (prompt) => typeof prompt === "string" && !isClaudeWakePrompt(prompt) ? conversationText(prompt).replace(/\s+/g, " ").trim().slice(0, TASK_TITLE_MAX_LENGTH) || void 0 : void 0;
636
- var asString = (value) => typeof value === "string" && value.length > 0 ? value : void 0;
637
- var NOTIFICATION_ACTION_MAX_LENGTH = 200;
638
- var STOP_FAILURE_REASON_MAX_LENGTH = 300;
639
- var notificationTypeOf = (payload) => asString(payload.notification_type) ?? asString(payload.type);
640
- var notificationAction = (payload) => {
641
- const text = asString(payload.message) ?? asString(payload.title);
642
- const collapsed = redactSecrets(text ?? "").replace(/\s+/g, " ").trim();
643
- return collapsed ? collapsed.slice(0, NOTIFICATION_ACTION_MAX_LENGTH) : "Notification";
644
- };
645
- var STOP_FAILURE_REASONS = {
646
- rate_limit: "Rate limited by the API",
647
- overloaded: "The API is overloaded right now",
648
- authentication_failed: "Authentication failed",
649
- billing_error: "A billing error stopped the turn"
650
- };
651
- var STOP_FAILURE_FALLBACK = "The turn ended on an API error (rate limit, billing, or auth).";
652
- var describeStopFailure = (error) => {
653
- const fromString = (value) => {
654
- const trimmed = value.trim();
655
- if (!trimmed) return void 0;
656
- return STOP_FAILURE_REASONS[trimmed] ?? redactSecrets(trimmed).slice(0, STOP_FAILURE_REASON_MAX_LENGTH);
657
- };
658
- if (typeof error === "string") {
659
- const described = fromString(error);
660
- if (described) return described;
661
- } else if (error && typeof error === "object") {
662
- for (const key of ["type", "message", "error", "code"]) {
663
- const value = error[key];
664
- if (typeof value === "string") {
665
- const described = fromString(value);
666
- if (described) return described;
667
- }
668
- }
669
- }
670
- return STOP_FAILURE_FALLBACK;
671
- };
672
- var permissionDeniedAction = (toolName) => {
673
- const tool = asString(toolName);
674
- return tool ? `Auto-mode blocked ${tool}` : "Auto-mode blocked a tool call";
675
- };
676
- var sessionIdentityOf = (payload) => {
677
- const sessionId = asString(payload.session_id ?? payload.sessionId ?? payload.conversation_id);
678
- const agentId = asString(payload.agent_id);
679
- if (!agentId) return { sessionId };
680
- return { sessionId: agentId, parentSessionId: sessionId };
681
- };
682
-
683
- // ../hook-mapping/src/json-record.ts
684
- var asRecord = (value) => value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
685
- var parseRecord = (text) => {
686
- try {
687
- return asRecord(JSON.parse(text));
688
- } catch {
689
- return null;
690
- }
691
- };
692
-
693
- // ../hook-mapping/src/codex-rollout.ts
694
- var CODEX_TURN_CONTEXT_TYPE = "turn_context";
695
- var CODEX_AUTO_REVIEWER = "auto_review";
696
- var CODEX_GUARDIAN_THREAD_SOURCE = "guardian_review";
697
- var CODEX_PLANNED_ACTION_MARKER = "Planned action JSON:\n";
698
- var CODEX_APPROVAL_REQUEST_END = ">>> APPROVAL REQUEST END";
699
- var CODEX_SHELL_TOOL = "exec_command";
700
- var nonEmptyString = (value) => typeof value === "string" && value.length > 0 ? value : void 0;
701
- var isTimestamp = (value) => typeof value === "string" && Number.isFinite(Date.parse(value));
702
- var readCodexTurnContext = (line) => {
703
- const entry = parseRecord(line);
704
- if (entry?.type !== CODEX_TURN_CONTEXT_TYPE) return null;
705
- const payload = asRecord(entry.payload);
706
- const turnId = nonEmptyString(payload?.turn_id);
707
- if (!payload || !turnId) return null;
708
- return {
709
- turnId,
710
- approvalsReviewer: payload.approvals_reviewer === CODEX_AUTO_REVIEWER ? "auto_review" : "user",
711
- ...isTimestamp(entry.timestamp) ? { startedAt: entry.timestamp } : {}
712
- };
713
- };
714
- var isCodexGuardianRolloutHead = (line, sessionId) => {
715
- if (!sessionId) return false;
716
- const entry = parseRecord(line);
717
- const payload = asRecord(entry?.payload);
718
- return entry?.type === "session_meta" && payload?.parent_thread_id === sessionId && payload.thread_source === CODEX_GUARDIAN_THREAD_SOURCE;
719
- };
720
- var readCodexPlannedAction = (message) => {
721
- const marker = message.lastIndexOf(CODEX_PLANNED_ACTION_MARKER);
722
- if (marker < 0) return null;
723
- const body = message.slice(marker + CODEX_PLANNED_ACTION_MARKER.length);
724
- const end = body.lastIndexOf(CODEX_APPROVAL_REQUEST_END);
725
- if (end < 0 || body.slice(end + CODEX_APPROVAL_REQUEST_END.length).trim().length > 0) return null;
726
- return parseRecord(body.slice(0, end).trim());
727
- };
728
- var readCodexReviewVerdict = (message) => {
729
- const verdict = parseRecord(message.trim());
730
- if (verdict?.outcome !== "allow" && verdict?.outcome !== "deny") return null;
731
- const rationale = typeof verdict.rationale === "string" ? verdict.rationale.trim() : "";
732
- return { outcome: verdict.outcome, ...rationale ? { rationale } : {} };
733
- };
734
- var scanCodexGuardianReviews = (lines) => {
735
- const reviews = [];
736
- let pending = null;
737
- for (const line of lines) {
738
- const entry = parseRecord(line.text);
739
- const payload = asRecord(entry?.payload);
740
- if (entry?.type !== "event_msg" || typeof payload?.message !== "string") continue;
741
- if (payload.type === "user_message") {
742
- const plannedAction = readCodexPlannedAction(payload.message);
743
- pending = plannedAction ? { offset: line.offset, plannedAction, ...isTimestamp(entry.timestamp) ? { requestedAt: entry.timestamp } : {} } : null;
744
- continue;
745
- }
746
- if (payload.type !== "agent_message" || !pending) continue;
747
- const verdict = readCodexReviewVerdict(payload.message);
748
- if (!verdict) continue;
749
- reviews.push({ ...pending, verdict });
750
- pending = null;
751
- }
752
- return { reviews, ...pending ? { pendingOffset: pending.offset } : {} };
753
- };
754
- var codexPlannedShellCommand = (plannedAction) => {
755
- if (plannedAction?.tool !== CODEX_SHELL_TOOL) return null;
756
- const argv = plannedAction.command;
757
- if (!Array.isArray(argv) || argv.length !== 3) return null;
758
- const [shell, flag, command] = argv;
759
- if (typeof shell !== "string" || shell.trim().length === 0) return null;
760
- if (typeof flag !== "string" || !CODEX_SHELL_COMMAND_FLAGS.includes(flag)) return null;
761
- if (typeof command !== "string" || command.trim().length === 0) return null;
762
- const cwd = nonEmptyString(plannedAction.cwd);
763
- return { command, ...cwd ? { cwd } : {} };
764
- };
765
- var codexReviewerDenialsSince = (reviews, since) => {
766
- const sinceMs = Date.parse(since);
767
- if (!Number.isFinite(sinceMs)) return [];
768
- return reviews.flatMap((review) => {
769
- if (review.verdict.outcome !== "deny" || !review.requestedAt) return [];
770
- if (Date.parse(review.requestedAt) < sinceMs) return [];
771
- const shell = codexPlannedShellCommand(review.plannedAction);
772
- if (!shell) return [];
773
- return [{
774
- ...shell,
775
- offset: review.offset,
776
- requestedAt: review.requestedAt,
777
- plannedAction: review.plannedAction,
778
- ...review.verdict.rationale ? { rationale: review.verdict.rationale } : {}
779
- }];
780
- });
781
- };
782
-
783
- // ../hook-mapping/src/transcript-usage.ts
784
- var TRANSCRIPT_ASSISTANT_TYPE = "assistant";
785
- var TRANSCRIPT_SYNTHETIC_MODEL = "<synthetic>";
786
- var TRANSCRIPT_RECENT_ID_LIMIT = 200;
787
- var TRANSCRIPT_USAGE_EVENTS = ["PostToolUse", "Stop"];
788
- var TRANSCRIPT_USAGE_SOURCES = ["claude", "qwen", "codebuddy", "qoder", "droid", "devin"];
789
- var COST_TRACKING_ENV = "PUSHARY_COST_TRACKING";
790
- var COST_TRACKING_OFF = "off";
791
- var TURN_END_EVENT = "Stop";
792
- var DEFAULT_MODEL_PRICES = [
793
- { match: "opus-4-1", in: 15, out: 75 },
794
- { match: "opus-4-0", in: 15, out: 75 },
795
- { match: "3-opus", in: 15, out: 75 },
796
- { match: "opus", in: 5, out: 25 },
797
- { match: "haiku", in: 1, out: 5 },
798
- { match: "sonnet", in: 3, out: 15 }
799
- ];
800
- var FALLBACK_MODEL_PRICE = { match: "", in: 3, out: 15 };
801
- var CACHE_WRITE_MULTIPLIER = 1.25;
802
- var CACHE_READ_MULTIPLIER = 0.1;
803
- var TOKENS_PER_PRICE_UNIT = 1e6;
804
- var isPrice = (value) => typeof value === "number" && Number.isFinite(value) && value >= 0;
805
- var isModelPrice = (value) => {
806
- const price = asRecord(value);
807
- return price !== null && typeof price.match === "string" && isPrice(price.in) && isPrice(price.out);
808
- };
809
- var estimateMessageCostUsd = (usage, model, prices = DEFAULT_MODEL_PRICES) => {
810
- const price = prices.find((candidate) => model.includes(candidate.match)) ?? FALLBACK_MODEL_PRICE;
811
- const perTokenIn = price.in / TOKENS_PER_PRICE_UNIT;
812
- const perTokenOut = price.out / TOKENS_PER_PRICE_UNIT;
813
- return usage.inputTokens * perTokenIn + usage.outputTokens * perTokenOut + usage.cacheCreationTokens * perTokenIn * CACHE_WRITE_MULTIPLIER + usage.cacheReadTokens * perTokenIn * CACHE_READ_MULTIPLIER;
814
- };
815
- var transcriptTokensIn = (usage) => usage.inputTokens + usage.cacheCreationTokens + usage.cacheReadTokens;
816
- var tokenCountOf = (value) => isTokenCount(value) ? value : 0;
817
- var nonEmptyString2 = (value) => typeof value === "string" && value.length > 0 ? value : null;
818
- var readTranscriptMessageUsage = (line) => {
819
- const entry = parseRecord(line);
820
- if (entry?.type !== TRANSCRIPT_ASSISTANT_TYPE) return null;
821
- const message = asRecord(entry.message);
822
- const usage = asRecord(message?.usage);
823
- if (!message || !usage) return null;
824
- const model = typeof message.model === "string" ? message.model : "";
825
- if (model.includes(TRANSCRIPT_SYNTHETIC_MODEL)) return null;
826
- return {
827
- ...typeof message.id === "string" ? { id: message.id } : {},
828
- model,
829
- usage: {
830
- inputTokens: tokenCountOf(usage.input_tokens),
831
- outputTokens: tokenCountOf(usage.output_tokens),
832
- cacheCreationTokens: tokenCountOf(usage.cache_creation_input_tokens),
833
- cacheReadTokens: tokenCountOf(usage.cache_read_input_tokens)
834
- }
835
- };
836
- };
837
- var rememberTranscriptMessage = (recentIds, id) => {
838
- if (!id) return { counted: true, recentIds };
839
- if (recentIds.includes(id)) return { counted: false, recentIds };
840
- return { counted: true, recentIds: [...recentIds, id].slice(-TRANSCRIPT_RECENT_ID_LIMIT) };
841
- };
842
- var isTranscriptUsageEvent = (event) => TRANSCRIPT_USAGE_EVENTS.includes(event);
843
- var endsASubagentTurn = (hook) => hook.event === TURN_END_EVENT && nonEmptyString2(hook.payload.agent_id) !== null;
844
- var transcriptUsageRequest = (hook) => {
845
- if (hook.costTracking === COST_TRACKING_OFF) return null;
846
- if (!TRANSCRIPT_USAGE_SOURCES.includes(hook.source) || !isTranscriptUsageEvent(hook.event)) return null;
847
- if (endsASubagentTurn(hook)) return null;
848
- const transcriptPath = nonEmptyString2(hook.payload.transcript_path);
849
- const sessionId = reportableSessionId(hook.payload.session_id);
850
- return transcriptPath && sessionId ? { transcriptPath, sessionId } : null;
851
- };
88
+ } from "./chunk-JHWOM55B.js";
852
89
 
853
90
  // src/pending.ts
854
91
  import { join } from "path";
@@ -1078,8 +315,8 @@ var stageHookCommand = (command) => {
1078
315
  staged.push(command);
1079
316
  return true;
1080
317
  };
1081
- var writeOutput = (output) => new Promise((resolve3, reject) => {
1082
- process.stdout.write(output, (error) => error ? reject(error) : resolve3());
318
+ var writeOutput = (output) => new Promise((resolve2, reject) => {
319
+ process.stdout.write(output, (error) => error ? reject(error) : resolve2());
1083
320
  });
1084
321
  var emitHookOutput = async (render, write = writeOutput) => {
1085
322
  const staged = [];
@@ -1400,7 +637,7 @@ var readNewUsage = (transcriptPath, sessionId) => {
1400
637
  };
1401
638
 
1402
639
  // src/codex-adapter.ts
1403
- import { resolve as resolve2 } from "path";
640
+ import { resolve } from "path";
1404
641
  var CODEX_AGENT = { type: "codex", label: "Codex" };
1405
642
  var codexAllow = () => ({ kind: "allow" });
1406
643
  var codexDeny = (reason) => ({ kind: "deny", reason });
@@ -1429,7 +666,7 @@ var toPolicyLookup = (toolName, toolInput, cwd) => {
1429
666
  const command = toolInput.command;
1430
667
  const files = parseApplyPatchFiles(command);
1431
668
  if (files.length === 1) {
1432
- return { tool: "Edit", input: { file_path: cwd ? resolve2(cwd, files[0]) : files[0] } };
669
+ return { tool: "Edit", input: { file_path: cwd ? resolve(cwd, files[0]) : files[0] } };
1433
670
  }
1434
671
  return { tool: "Edit", input: typeof command === "string" ? { file_path: command } : {} };
1435
672
  };
@@ -1445,7 +682,7 @@ var toPolicyLookups = (toolName, toolInput, cwd) => {
1445
682
  }
1446
683
  return {
1447
684
  tool: "Edit",
1448
- inputs: files.map((file) => ({ file_path: cwd ? resolve2(cwd, file) : file }))
685
+ inputs: files.map((file) => ({ file_path: cwd ? resolve(cwd, file) : file }))
1449
686
  };
1450
687
  };
1451
688
  var codexQuestionLimitDecision = (facts) => {
@@ -1776,7 +1013,7 @@ var isWaitingOnBackgroundWork = (sessionKey, nowMs = Date.now()) => {
1776
1013
  };
1777
1014
 
1778
1015
  // src/events.ts
1779
- import { basename as basename2, join as join9 } from "path";
1016
+ import { basename, join as join9 } from "path";
1780
1017
  import { existsSync as existsSync6, mkdirSync as mkdirSync7, readFileSync as readFileSync7, statSync as statSync8, writeFileSync as writeFileSync7 } from "fs";
1781
1018
  import { tmpdir as tmpdir8 } from "os";
1782
1019
  var INTENT_DIR = join9(tmpdir8(), "pushary-intent");
@@ -2084,7 +1321,7 @@ var handlePostToolUse = async (input, agent = CLAUDE_CODE_AGENT) => {
2084
1321
  const deadline = Date.now() + HOOK_BUDGET_MS;
2085
1322
  const signal = AbortSignal.timeout(HOOK_BUDGET_MS);
2086
1323
  try {
2087
- const projectName = basename2(input.cwd ?? process.cwd());
1324
+ const projectName = basename(input.cwd ?? process.cwd());
2088
1325
  const action = describeToolCall(input.tool_name, input.tool_input, "event");
2089
1326
  const lookup = toPolicyLookup(input.tool_name, input.tool_input);
2090
1327
  const toolResult = input.tool_response ?? input.tool_result;
@@ -2151,7 +1388,7 @@ var handleUserPrompt = async (input, agent = CLAUDE_CODE_AGENT) => {
2151
1388
  const deadline = Date.now() + HOOK_BUDGET_MS;
2152
1389
  const signal = AbortSignal.timeout(HOOK_BUDGET_MS);
2153
1390
  try {
2154
- const projectName = basename2(input.cwd ?? process.cwd());
1391
+ const projectName = basename(input.cwd ?? process.cwd());
2155
1392
  const sessionKey = input.session_id || DEFAULT_SESSION;
2156
1393
  const titlesEnabled = process.env.PUSHARY_TASK_TITLES !== "off";
2157
1394
  const taskTitle = titlesEnabled ? taskTitleFrom(input.prompt) : void 0;
@@ -2190,7 +1427,7 @@ var handleStop = async (input, agent = CLAUDE_CODE_AGENT) => {
2190
1427
  const deadline = Date.now() + HOOK_BUDGET_MS;
2191
1428
  const signal = AbortSignal.timeout(HOOK_BUDGET_MS);
2192
1429
  try {
2193
- const projectName = basename2(input.cwd ?? process.cwd());
1430
+ const projectName = basename(input.cwd ?? process.cwd());
2194
1431
  const sessionKey = input.session_id || DEFAULT_SESSION;
2195
1432
  noteBackgroundWork(sessionKey, hasRunningBackgroundTasks(input.background_tasks));
2196
1433
  const late = await reconcilePendingQuestions(sessionKey, void 0, signal);
@@ -2231,7 +1468,7 @@ var isSubagentStop = (input) => input.hook_event_name === "SubagentStop" || type
2231
1468
  var SUBAGENT_STOP_REPORT_TIMEOUT_MS = 4e3;
2232
1469
  var handleSubagentStop = async (input, agent = CLAUDE_CODE_AGENT) => {
2233
1470
  try {
2234
- const projectName = basename2(input.cwd ?? process.cwd());
1471
+ const projectName = basename(input.cwd ?? process.cwd());
2235
1472
  await reportEvent({
2236
1473
  event: "session_end",
2237
1474
  agentType: agent.type,
@@ -2249,7 +1486,7 @@ var isCompactionEvent = (hookEventName) => hookEventName === "PreCompact" || hoo
2249
1486
  var COMPACTION_REPORT_TIMEOUT_MS = 4e3;
2250
1487
  var handleCompaction = async (input, agent = CLAUDE_CODE_AGENT) => {
2251
1488
  try {
2252
- const projectName = basename2(input.cwd ?? process.cwd());
1489
+ const projectName = basename(input.cwd ?? process.cwd());
2253
1490
  await reportEvent({
2254
1491
  event: "compaction",
2255
1492
  agentType: agent.type,
@@ -2262,7 +1499,7 @@ var handleCompaction = async (input, agent = CLAUDE_CODE_AGENT) => {
2262
1499
  };
2263
1500
  var handleSessionStart = async (input, agent = CLAUDE_CODE_AGENT) => {
2264
1501
  try {
2265
- const projectName = basename2(input.cwd ?? process.cwd());
1502
+ const projectName = basename(input.cwd ?? process.cwd());
2266
1503
  const action = input.agent_id ? "Subagent started" : sessionStartAction(input.source);
2267
1504
  await reportEvent({
2268
1505
  event: "session_start",
@@ -2276,7 +1513,7 @@ var handleSessionStart = async (input, agent = CLAUDE_CODE_AGENT) => {
2276
1513
  };
2277
1514
  var handleSessionEnd = async (input, agent = CLAUDE_CODE_AGENT, options = {}) => {
2278
1515
  try {
2279
- const projectName = basename2(input.cwd ?? process.cwd());
1516
+ const projectName = basename(input.cwd ?? process.cwd());
2280
1517
  const action = sessionEndAction(input.reason);
2281
1518
  const sessionKey = input.session_id || DEFAULT_SESSION;
2282
1519
  if (options.reconcile ?? true) {
@@ -2304,7 +1541,7 @@ var pushesNotification = (notifType, sessionKey) => NOTIFICATION_PUSH_TYPES.has(
2304
1541
  var handleNotification = async (input, agent = CLAUDE_CODE_AGENT) => {
2305
1542
  const signal = AbortSignal.timeout(HOOK_BUDGET_MS);
2306
1543
  try {
2307
- const projectName = basename2(input.cwd ?? process.cwd());
1544
+ const projectName = basename(input.cwd ?? process.cwd());
2308
1545
  const notifType = notificationTypeOf(input) ?? "";
2309
1546
  const sessionKey = input.session_id || DEFAULT_SESSION;
2310
1547
  const teammateIdle = input.hook_event_name === "TeammateIdle";
@@ -2365,7 +1602,7 @@ var handleStopFailure = async (input, agent = CLAUDE_CODE_AGENT) => {
2365
1602
  } catch {
2366
1603
  return;
2367
1604
  }
2368
- const projectName = basename2(input.cwd ?? process.cwd());
1605
+ const projectName = basename(input.cwd ?? process.cwd());
2369
1606
  const reason = describeStopFailure(input.error);
2370
1607
  await reportEvent({
2371
1608
  event: "turn_error",
@@ -2395,24 +1632,6 @@ var handleStopFailure = async (input, agent = CLAUDE_CODE_AGENT) => {
2395
1632
  };
2396
1633
 
2397
1634
  export {
2398
- HOOK_FALLBACK_MAX,
2399
- UNNAMED_ACTION,
2400
- describeToolCall,
2401
- deriveToolTarget,
2402
- patchDeletesFiles,
2403
- OPENCODE_TOOL_NAMES,
2404
- compatibleToolLookup,
2405
- canonicalGateInputs,
2406
- scopePathFor,
2407
- deriveActionBody,
2408
- deriveAction,
2409
- deriveBlocker,
2410
- permissionDeniedAction,
2411
- sessionIdentityOf,
2412
- readCodexTurnContext,
2413
- isCodexGuardianRolloutHead,
2414
- scanCodexGuardianReviews,
2415
- codexReviewerDenialsSince,
2416
1635
  DEFAULT_SESSION,
2417
1636
  readPendingCommandById,
2418
1637
  readPendingCommand,